├── .clang-format ├── .github ├── docker │ └── fedora.dockerfile └── workflows │ └── build-and-test.yaml ├── .gitignore ├── .readthedocs.yaml ├── CMakeLists.txt ├── COPYRIGHT ├── LGPL ├── README.md ├── cmake ├── config.cmake.in ├── gotcha.cmake ├── gotcha_config.h.in └── gotcha_testing.cmake ├── docs ├── .clang-format ├── .gitignore ├── Makefile ├── _static │ └── theme_overrides.css ├── _themes │ └── sphinx_rtd_theme │ │ ├── __init__.py │ │ ├── breadcrumbs.html │ │ ├── footer.html │ │ ├── layout.html │ │ ├── search.html │ │ ├── searchbox.html │ │ ├── static │ │ ├── css │ │ │ ├── badge_only.css │ │ │ └── theme.css │ │ ├── fonts │ │ │ ├── Inconsolata-Bold.ttf │ │ │ ├── Inconsolata-Regular.ttf │ │ │ ├── Lato-Bold.ttf │ │ │ ├── Lato-Regular.ttf │ │ │ ├── RobotoSlab-Bold.ttf │ │ │ ├── RobotoSlab-Regular.ttf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ └── js │ │ │ ├── modernizr.min.js │ │ │ └── theme.js │ │ ├── theme.conf │ │ └── versions.html ├── api.rst ├── build.rst ├── conf.py ├── definitions.rst ├── developer-guide.rst ├── examples.rst ├── images │ └── gotcha-logo.png ├── index.rst ├── limitations.rst ├── overview.rst ├── requirements.txt ├── style-guides.rst └── testing.rst ├── include ├── CMakeLists.txt └── gotcha │ ├── Doxyfile │ ├── gotcha.h │ └── gotcha_types.h ├── src ├── CMakeLists.txt ├── elf_ops.c ├── elf_ops.h ├── example │ ├── CMakeLists.txt │ ├── autotee │ │ ├── CMakeLists.txt │ │ ├── autotee.c │ │ └── test_autotee.c │ └── minimal │ │ ├── CMakeLists.txt │ │ ├── sampleLib.c │ │ ├── sampleLib.h │ │ └── symbolLookup.c ├── gotcha.c ├── gotcha_auxv.c ├── gotcha_auxv.h ├── gotcha_dl.c ├── gotcha_dl.h ├── gotcha_utils.c ├── gotcha_utils.h ├── hash.c ├── hash.h ├── libc_wrappers.c ├── libc_wrappers.h ├── library_filters.c ├── library_filters.h ├── tool.c ├── tool.h ├── translations.c └── translations.h └── test ├── CMakeLists.txt ├── dispatcher ├── CMakeLists.txt ├── libdispatcher.c ├── libimpl.c └── main.c ├── dlopen ├── CMakeLists.txt ├── num.c ├── num2.c └── test_dlopen.c ├── filter ├── CMakeLists.txt ├── num.c ├── num.h └── test_filter.c ├── function_ptr ├── CMakeLists.txt ├── num.c ├── num.h └── test_function_ptr.c ├── hammer ├── CMakeLists.txt ├── addref.cc ├── gen.cc ├── gen_externals_h.sh ├── hammer.cc ├── math.hpp ├── multref.cc ├── wrap.cc └── wrap.h ├── ppc_stress_multi_module ├── CMakeLists.txt ├── app.c ├── tool1.c ├── tool1.h ├── tool2.c └── tool2.h ├── priority ├── CMakeLists.txt ├── app.c ├── lib1.c ├── lib1.h ├── tool1.c ├── tool1.h ├── tool2.c ├── tool2.h ├── tool3.c └── tool3.h ├── rogot ├── CMakeLists.txt ├── autotee.c └── test_autotee.c ├── stack ├── CMakeLists.txt ├── app.c ├── lib1.c ├── lib1.h ├── tool1.c ├── tool1.h ├── tool2.c └── tool2.h ├── symver ├── CMakeLists.txt ├── retX.h ├── retX_new.c ├── retX_old.c ├── sym_macro.h ├── symver.map └── test_symver.c ├── unit ├── CMakeLists.txt ├── gotcha_unit_tests.c ├── testing_lib.c └── testing_lib.h └── wrap_main ├── CMakeLists.txt ├── app.c ├── lib.c └── lib.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google -------------------------------------------------------------------------------- /.github/docker/fedora.dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | RUN dnf -y update 3 | RUN dnf -y install check-devel cmake git gcc-c++ python3-sphinx 4 | RUN dnf clean all 5 | COPY GOTCHA GOTCHA 6 | WORKDIR /GOTCHA 7 | RUN cmake . -B build -DGOTCHA_ENABLE_TESTS=ON -DDEPENDENCIES_PREINSTALLED=TRUE -DCMAKE_BUILD_TYPE=PROFILE -DGOTCHA_ENABLE_WARNING_ERROR=ON 8 | RUN cmake --build build 9 | RUN ctest --test-dir build -VV 10 | -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yaml: -------------------------------------------------------------------------------- 1 | name: GOTCHA Build and Test 2 | 3 | on: 4 | pull_request: 5 | branches: [ main, develop ] 6 | push: 7 | 8 | jobs: 9 | build-and-test-ubuntu: 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: [ubuntu-20.04, ubuntu-22.04] 14 | 15 | name: ${{ matrix.os }} 16 | 17 | runs-on: ${{ matrix.os }} 18 | 19 | env: 20 | CC: gcc 21 | CXX: g++ 22 | 23 | steps: 24 | - name: Push checkout 25 | if: github.event_name == 'push' 26 | uses: actions/checkout@v3 27 | with: 28 | fetch-depth: 2 29 | - name: PR checkout 30 | if: github.event_name == 'pull_request' 31 | uses: actions/checkout@v3 32 | with: 33 | ref: ${{ github.event.pull_request.head.sha }} 34 | fetch-depth: 2 35 | 36 | - name: Install additional packages 37 | run: | 38 | sudo apt-get update 39 | sudo apt-get install cmake gcovr check clang-format 40 | 41 | - name: Check code formatting 42 | if: matrix.os == 'ubuntu-22.04' 43 | run: | 44 | git clang-format --diff HEAD~1 -q 45 | if git clang-format --diff HEAD~1 -q | grep -m 1 '^' >/dev/null; then 46 | echo >&2 "Failed clang-format check. Run: git clang-format HEAD~1" 47 | exit 1 48 | fi 49 | - name: Configure and Build 50 | run: | 51 | cmake . -B build -DGOTCHA_ENABLE_TESTS=ON -DCMAKE_BUILD_TYPE=PROFILE -DGOTCHA_ENABLE_WARNING_ERROR=ON 52 | cmake --build build 53 | - name: Unit Tests 54 | run: | 55 | ctest --test-dir build -VV 56 | - name: Create Coverage 57 | if: matrix.os == 'ubuntu-22.04' 58 | run : | 59 | mkdir coverage 60 | FILE=$PWD/coverage/coverage.json 61 | cd build 62 | COVERALLS_REPO_TOKEN=${{ secrets.GITHUB_TOKEN }} gcovr -r ../ . --coveralls $FILE -e ../test/ -e ../src/example 63 | if [ -e '$FILE' ]; then 64 | sed -i'' -e 's/"service_name": "github-actions-ci"/"service_name": "github"/' '$FILE' 65 | fi 66 | cat $FILE 67 | curl -v -F json_file=@$FILE https://coveralls.io/api/v1/jobs 68 | 69 | build-and-test-fedora: 70 | name: fedora 71 | runs-on: ubuntu-latest 72 | 73 | steps: 74 | - name: Setup Podman 75 | run: | 76 | sudo apt update 77 | sudo apt-get -y install podman 78 | podman pull fedora:latest 79 | - name: Get source 80 | uses: actions/checkout@v3 81 | with: 82 | path: 'GOTCHA' 83 | - name: Create container and run tests 84 | run: | 85 | cp GOTCHA/.github/docker/fedora.dockerfile . 86 | podman build --tag fedora_latest_test --file=fedora.dockerfile 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw* 2 | **/.envrc 3 | .envrc 4 | build 5 | tags 6 | **/tags 7 | *.core 8 | .cache 9 | .idea 10 | .vscode 11 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: docs/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | python: 31 | install: 32 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | option(GOTCHA_ENABLE_TESTS "Enable internal tests" Off) 3 | option(GOTCHA_ENABLE_WARNING_ERROR "Enable throw error for build warning" Off) 4 | project(gotcha) 5 | include(CheckCXXCompilerFlag) 6 | include(cmake/gotcha.cmake) 7 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 8 | 9 | set(LIBTOOL_INTERFACE 2) 10 | set(LIBTOOL_REVISION 4) 11 | set(LIBTOOL_AGE 2) 12 | 13 | set(GOTCHA_VERSION "(1, 0, 8)") 14 | 15 | 16 | set(DEFAULT_SYMBOL_VISIBILITY hidden) 17 | 18 | if(GOTCHA_ENABLE_TESTS) 19 | enable_testing() 20 | set(DEFAULT_SYMBOL_VISIBILITY default) 21 | add_definitions("-DGOTCHA_ENABLE_TESTING") 22 | if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") 23 | set(CMAKE_C_FLAGS_PROFILE --coverage) 24 | set(CMAKE_CXX_FLAGS_PROFILE --coverage) 25 | endif() 26 | endif() 27 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) 28 | include_directories(${CMAKE_BINARY_DIR}/include) 29 | add_subdirectory(include) 30 | add_subdirectory(src) 31 | if(GOTCHA_ENABLE_TESTS) 32 | add_subdirectory(test) 33 | setup_coverage_target() 34 | endif() 35 | 36 | include(CMakePackageConfigHelpers) 37 | 38 | # Configure gotcha-config-version.cmake 39 | write_basic_package_version_file( 40 | "${CMAKE_CURRENT_BINARY_DIR}/gotcha-config-version.cmake" 41 | VERSION ${LIBTOOL_INTERFACE}.${LIBTOOL_REVISION}.${LIBTOOL_AGE} 42 | COMPATIBILITY SameMajorVersion) 43 | 44 | set(gotcha_INSTALL_INCLUDE_DIR include/) 45 | set(gotcha_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}) 46 | 47 | # Configure gotcha-config.cmake 48 | configure_package_config_file( 49 | "cmake/config.cmake.in" 50 | "${CMAKE_CURRENT_BINARY_DIR}/gotcha-config.cmake" 51 | INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/gotcha" 52 | PATH_VARS gotcha_INSTALL_INCLUDE_DIR PATH_VARS gotcha_INSTALL_LIBRARY_DIR) 53 | 54 | install( 55 | FILES "${CMAKE_CURRENT_BINARY_DIR}/gotcha-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/gotcha-config-version.cmake" 56 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/gotcha") 57 | 58 | # Write the configure file 59 | configure_file("${CMAKE_SOURCE_DIR}/cmake/gotcha_config.h.in" 60 | "${CMAKE_CURRENT_BINARY_DIR}/include/gotcha/gotcha_config.h" @ONLY) 61 | install( 62 | FILES "${CMAKE_CURRENT_BINARY_DIR}/include/gotcha/gotcha_config.h" 63 | DESTINATION "${gotcha_INSTALL_INCLUDE_DIR}/gotcha") 64 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | GOTCHA is developed by Lawrence Livermore National Security. 2 | The following copyrights apply: 3 | 4 | Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at 5 | the Lawrence Livermore National Laboratory. Written by Hariharan Devarajan 'hariharandev1 at llnl dot gov', 6 | David Poliakoff 'poliakoff1 at llnl dot gov', and Matthew LeGendre 'legendre1 at llnl dot gov'. 7 | CODE-730558. All rights reserved. 8 | 9 | This program is free software; you can redistribute it and/or modify it under 10 | the terms of the GNU Lesser General Public License (as published by the Free Software 11 | Foundation) version 2.1 dated February 1999. This program is distributed in 12 | the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 13 | IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 | the terms and conditions of the GNU Lesser General Public License for more details. 15 | You should have received a copy of the GNU Lesser General Public License along 16 | with this program; if not, write to the Free Software Foundation, Inc., 59 17 | Temple Place, Suite 330, Boston, MA 02111-1307 USA. 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GOTCHA v1.0.8 2 | ============ 3 | [![GOTCHA Build and Test](https://github.com/LLNL/GOTCHA/actions/workflows/build-and-test.yaml/badge.svg)](https://github.com/LLNL/GOTCHA/actions/workflows/build-and-test.yaml) 4 | [![Coverage Status](https://coveralls.io/repos/github/LLNL/GOTCHA/badge.svg?branch=develop)](https://coveralls.io/github/LLNL/GOTCHA?branch=develop) 5 | [![Documentation Status](https://readthedocs.org/projects/gotcha/badge/?version=latest)](https://gotcha.readthedocs.io/en/latest/?badge=latest) 6 | 7 | Gotcha is a library that wraps functions. Tools can use gotcha to install hooks into other libraries, for example putting a wrapper function around libc's malloc. 8 | It is similar to LD_PRELOAD, but operates via a programmable API. 9 | This enables easy methods of accomplishing tasks like code instrumentation or wholesale replacement of mechanisms in programs 10 | without disrupting their source code. 11 | 12 | Quick Start 13 | ----------- 14 | 15 | *Building Gotcha* is trivial. In the root directory of the repo 16 | 17 | ``` 18 | mkdir build 19 | cd build 20 | cmake -DCMAKE_INSTALL_PREFIX= ../ 21 | make install 22 | ``` 23 | *Usage* is fairly simple. For us to wrap a function, we need to know its name, what you want it wrapped with (the wrapper), and we need to give you some ability to call the function you wrapped (wrappee). Gotcha works on triplets containing this information. We have [small sample uses](src/example/autotee/autotee.c), but the standard workflow looks like 24 | 25 | 26 | ``` 27 | #include 28 | static gotcha_wrappee_handle_t wrappee_puts_handle; 29 | static int puts_wrapper(const char* str); //this is the declaration of your wrapper 30 | static gotcha_wrappee_handle_t wrappee_fputs_handle; 31 | static int fputs_wrapper(const char* str, FILE* f); 32 | struct gotcha_binding_t wrap_actions [] = { 33 | { "puts", puts_wrapper, &wrappee_puts_handle }, 34 | { "fputs", fputs_wrapper, &wrappee_fputs_handle }, 35 | }; 36 | int init_mytool(){ 37 | gotcha_wrap(wrap_actions, sizeof(wrap_actions)/sizeof(struct gotcha_binding_t), "my_tool_name"); 38 | } 39 | static int fputs_wrapper(const char* str, FILE* f){ 40 | // insert clever tool logic here 41 | typeof(&fputs_wrapper) wrappee_fputs = gotcha_get_wrappee(wrappee_fputs_handle); // get my wrappee from Gotcha 42 | return wrappee_fputs(str, f); //wrappee_fputs was directed to the original fputs by gotcha_wrap 43 | } 44 | 45 | ``` 46 | 47 | *Building your tool* changes little, you just need to add the prefix you installed Gotcha to your include directories, the location 48 | the library was installed (default is /lib) to your library search directories (-L...), and link 49 | libgotcha.so (-lgotcha) with your tool. Very often this becomes "add -lgotcha to your link line," and nicer CMake integration is coming down the pipe. 50 | 51 | A more advanced example can be seen in the [GOTCHA-tracer](https://github.com/llnl/GOTCHA-tracer) project. 52 | This example shows how to implement a simple tracer with GOTCHA, including linking to GOTCHA through CMake and testing GOTCHA through direct invocation and using `LD_PRELOAD`. 53 | 54 | That should represent all the work your application needs to do to use Gotcha. 55 | 56 | Contact/Legal 57 | ----------- 58 | 59 | The license is [LGPL](LGPL). 60 | 61 | Primary contact/Lead developer 62 | 63 | Hariharan Devarajan (hariharandev1@llnl.gov) 64 | -------------------------------------------------------------------------------- /cmake/config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | set_and_check(gotcha_INCLUDE_DIR "@PACKAGE_gotcha_INSTALL_INCLUDE_DIR@") 4 | set(gotcha_LIBRARY_PATH "@PACKAGE_gotcha_INSTALL_LIBRARY_DIR@") 5 | link_directories(${gotcha_LIBRARY_PATH}) 6 | if (NOT TARGET gotcha) 7 | include(${CMAKE_CURRENT_LIST_DIR}/gotcha-targets.cmake) 8 | endif() 9 | 10 | set(gotcha_INCLUDE_DIRS ${gotcha_INCLUDE_DIR}) 11 | set(gotcha_LIBRARIES gotcha) 12 | 13 | check_required_components(gotcha) 14 | -------------------------------------------------------------------------------- /cmake/gotcha.cmake: -------------------------------------------------------------------------------- 1 | include(cmake/gotcha_testing.cmake) 2 | -------------------------------------------------------------------------------- /cmake/gotcha_config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef GOTCHA_CONFIG_H 2 | #define GOTCHA_CONFIG_H 3 | 4 | #define GOTCHA_GET_VERSION(MAJOR, MINOR, PATCH) (MAJOR * 100000 + MINOR * 100 + PATCH) 5 | #define GOTCHA_VERSION (GOTCHA_GET_VERSION @GOTCHA_VERSION@) 6 | #define GOTCHA_VERSION_MAJOR (GOTCHA_VERSION / 100000) 7 | #define GOTCHA_VERSION_MINOR ((GOTCHA_VERSION / 100) % 1000) 8 | #define GOTCHA_VERSION_PATCH (GOTCHA_VERSION % 100) 9 | 10 | #endif /* GOTCHA_CONFIG_H */ 11 | -------------------------------------------------------------------------------- /cmake/gotcha_testing.cmake: -------------------------------------------------------------------------------- 1 | set_property(GLOBAL PROPERTY COVERAGE_FILES "") 2 | function(gotcha_add_test) 3 | add_test(${ARGV}) 4 | set_tests_properties(${ARGV0} PROPERTIES 5 | ENVIRONMENT "LLVM_PROFILE_FILE=${ARGV0}.profraw") 6 | get_property(OLD_CF GLOBAL PROPERTY COVERAGE_FILES) 7 | set(NEW_CF ${OLD_CF} ${CMAKE_CURRENT_BINARY_DIR}/${ARGV0}.profraw) 8 | set_property(GLOBAL PROPERTY COVERAGE_FILES ${NEW_CF}) 9 | endfunction() 10 | 11 | macro(environment_add target type property) 12 | get_property(local_env ${type} ${target} PROPERTY ENVIRONMENT) 13 | set_property(${type} ${target} PROPERTY ENVIRONMENT ${local_env} ${property}) 14 | endmacro() 15 | 16 | macro(setup_coverage_target) 17 | get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) 18 | add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) 19 | add_custom_target(merged_coverage DEPENDS default.profdata) 20 | endmacro() 21 | -------------------------------------------------------------------------------- /docs/.clang-format: -------------------------------------------------------------------------------- 1 | DisableFormat: true 2 | SortIncludes: Never 3 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | -------------------------------------------------------------------------------- /docs/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* override table width restrictions */ 2 | 3 | .wy-table-responsive table td, .wy-table-responsive table th { 4 | white-space: normal !important; 5 | } 6 | .wy-table-responsive { 7 | margin-bottom: 24px; 8 | max-width: 100%; 9 | overflow: auto !important; 10 | } 11 | 12 | /* wide table scroll-bar */ 13 | 14 | table.scrollwide { 15 | display: block; 16 | width: 700px; 17 | background-color: #E0; 18 | overflow: scroll; !important 19 | } 20 | table.scrollwide td { 21 | white-space: nowrap; 22 | } 23 | 24 | /* override navigation sidebar out-of-view on page scrolling */ 25 | 26 | .wy-nav-side { 27 | position: fixed; 28 | padding-bottom: 2em; 29 | width: 300px; 30 | overflow-x: hidden; 31 | overflow-y: scroll; 32 | min-height: 100%; 33 | background: #343131; 34 | z-index: 200; 35 | } 36 | 37 | /* changed side navigation bg colors */ 38 | .wy-side-nav-search { 39 | background: #222c32 !important; 40 | } 41 | 42 | .wy-nav-side { 43 | background: #222c32; 44 | } 45 | 46 | .rst-versions{ 47 | border-top:solid 10px #222c32; 48 | } 49 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/__init__.py: -------------------------------------------------------------------------------- 1 | """Sphinx ReadTheDocs theme. 2 | 3 | From https://github.com/ryan-roemer/sphinx-bootstrap-theme. 4 | 5 | """ 6 | import os 7 | 8 | __version__ = '0.2.5b1' 9 | __version_full__ = __version__ 10 | 11 | 12 | def get_html_theme_path(): 13 | """Return list of HTML theme paths.""" 14 | cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 15 | return cur_dir 16 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/breadcrumbs.html: -------------------------------------------------------------------------------- 1 | {# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #} 2 | 3 | {% if page_source_suffix %} 4 | {% set suffix = page_source_suffix %} 5 | {% else %} 6 | {% set suffix = source_suffix %} 7 | {% endif %} 8 | 9 | {% if meta is defined and meta is not none %} 10 | {% set check_meta = True %} 11 | {% else %} 12 | {% set check_meta = False %} 13 | {% endif %} 14 | 15 | {% if check_meta and 'github_url' in meta %} 16 | {% set display_github = True %} 17 | {% endif %} 18 | 19 | {% if check_meta and 'bitbucket_url' in meta %} 20 | {% set display_bitbucket = True %} 21 | {% endif %} 22 | 23 | {% if check_meta and 'gitlab_url' in meta %} 24 | {% set display_gitlab = True %} 25 | {% endif %} 26 | 27 |
28 | 29 | 70 | 71 | {% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %} 72 | 80 | {% endif %} 81 |
82 |
83 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/footer.html: -------------------------------------------------------------------------------- 1 |
2 | {% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %} 3 | 11 | {% endif %} 12 | 13 |
14 | 15 |
16 |

17 | {%- if show_copyright %} 18 | {%- if hasdoc('copyright') %} 19 | {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} 20 | {%- else %} 21 | {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} 22 | {%- endif %} 23 | {%- endif %} 24 | 25 | {%- if build_id and build_url %} 26 | {% trans build_url=build_url, build_id=build_id %} 27 | 28 | Build 29 | {{ build_id }}. 30 | 31 | {% endtrans %} 32 | {%- elif commit %} 33 | {% trans commit=commit %} 34 | 35 | Revision {{ commit }}. 36 | 37 | {% endtrans %} 38 | {%- elif last_updated %} 39 | {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} 40 | {%- endif %} 41 | 42 |

43 |
44 | 45 | {%- if show_sphinx %} 46 | {% trans %}Built with Sphinx using a theme provided by Read the Docs{% endtrans %}. 47 | {%- endif %} 48 | 49 | {%- block extrafooter %} {% endblock %} 50 | 51 |
52 | 53 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/search.html: -------------------------------------------------------------------------------- 1 | {# 2 | basic/search.html 3 | ~~~~~~~~~~~~~~~~~ 4 | 5 | Template for the search page. 6 | 7 | :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. 8 | :license: BSD, see LICENSE for details. 9 | #} 10 | {%- extends "layout.html" %} 11 | {% set title = _('Search') %} 12 | {% set script_files = script_files + ['_static/searchtools.js'] %} 13 | {% block footer %} 14 | 17 | {# this is used when loading the search index using $.ajax fails, 18 | such as on Chrome for documents on localhost #} 19 | 20 | {{ super() }} 21 | {% endblock %} 22 | {% block body %} 23 | 31 | 32 | {% if search_performed %} 33 |

{{ _('Search Results') }}

34 | {% if not search_results %} 35 |

{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

36 | {% endif %} 37 | {% endif %} 38 |
39 | {% if search_results %} 40 |
    41 | {% for href, caption, context in search_results %} 42 |
  • 43 | {{ caption }} 44 |

    {{ context|e }}

    45 |
  • 46 | {% endfor %} 47 |
48 | {% endif %} 49 |
50 | {% endblock %} 51 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/searchbox.html: -------------------------------------------------------------------------------- 1 | {%- if builder != 'singlehtml' %} 2 |
3 |
4 | 5 | 6 | 7 |
8 |
9 | {%- endif %} 10 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")} .fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit} a .fa{display:inline-block;text-decoration:inherit} li .fa{display:inline-block} li .fa-large:before,li .fa-large:before{width:1.875em} ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em} ul.fas li .fa{width:.8em} ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline} .fa-book:before{content:""} .icon-book:before{content:""} .fa-caret-down:before{content:""} .icon-caret-down:before{content:""} .fa-caret-up:before{content:""} .icon-caret-up:before{content:""} .fa-caret-left:before{content:""} .icon-caret-left:before{content:""} .fa-caret-right:before{content:""} .icon-caret-right:before{content:""} .rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400} .rst-versions a{color:#2980B9;text-decoration:none} .rst-versions .rst-badge-small{display:none} .rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1} .rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""} .rst-versions .rst-current-version:after{clear:both} .rst-versions .rst-current-version .fa{color:#fcfcfc} .rst-versions .rst-current-version .fa-book{float:left} .rst-versions .rst-current-version .icon-book{float:left} .rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff} .rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000} .rst-versions.shift-up .rst-other-versions{display:block} .rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none} .rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d} .rst-versions .rst-other-versions dd{display:inline-block;margin:0} .rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc} .rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px} .rst-versions.rst-badge .icon-book{float:none} .rst-versions.rst-badge .fa-book{float:none} .rst-versions.rst-badge.shift-up .rst-current-version{text-align:right} .rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left} .rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left} .rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none} .rst-versions.shift{display:block}} 2 | /*# sourceMappingURL=badge_only.css.map */ 3 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/static/js/theme.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o"); 80 | 81 | // Add expand links to all parents of nested ul 82 | $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () { 83 | var link = $(this); 84 | expand = $(''); 85 | expand.on('click', function (ev) { 86 | self.toggleCurrent(link); 87 | ev.stopPropagation(); 88 | return false; 89 | }); 90 | link.prepend(expand); 91 | }); 92 | }; 93 | 94 | nav.reset = function () { 95 | // Get anchor from URL and open up nested nav 96 | var anchor = encodeURI(window.location.hash); 97 | if (anchor) { 98 | try { 99 | var link = $('.wy-menu-vertical') 100 | .find('[href="' + anchor + '"]'); 101 | // If we didn't find a link, it may be because we clicked on 102 | // something that is not in the sidebar (eg: when using 103 | // sphinxcontrib.httpdomain it generates headerlinks but those 104 | // aren't picked up and placed in the toctree). So let's find 105 | // the closest header in the document and try with that one. 106 | if (link.length === 0) { 107 | var doc_link = $('.document a[href="' + anchor + '"]'); 108 | var closest_section = doc_link.closest('div.section'); 109 | // Try again with the closest section entry. 110 | link = $('.wy-menu-vertical') 111 | .find('[href="#' + closest_section.attr("id") + '"]'); 112 | 113 | } 114 | $('.wy-menu-vertical li.toctree-l1 li.current') 115 | .removeClass('current'); 116 | link.closest('li.toctree-l2').addClass('current'); 117 | link.closest('li.toctree-l3').addClass('current'); 118 | link.closest('li.toctree-l4').addClass('current'); 119 | } 120 | catch (err) { 121 | console.log("Error expanding nav for anchor", err); 122 | } 123 | } 124 | }; 125 | 126 | nav.onScroll = function () { 127 | this.winScroll = false; 128 | var newWinPosition = this.win.scrollTop(), 129 | winBottom = newWinPosition + this.winHeight, 130 | navPosition = this.navBar.scrollTop(), 131 | newNavPosition = navPosition + (newWinPosition - this.winPosition); 132 | if (newWinPosition < 0 || winBottom > this.docHeight) { 133 | return; 134 | } 135 | this.navBar.scrollTop(newNavPosition); 136 | this.winPosition = newWinPosition; 137 | }; 138 | 139 | nav.onResize = function () { 140 | this.winResize = false; 141 | this.winHeight = this.win.height(); 142 | this.docHeight = $(document).height(); 143 | }; 144 | 145 | nav.hashChange = function () { 146 | this.linkScroll = true; 147 | this.win.one('hashchange', function () { 148 | this.linkScroll = false; 149 | }); 150 | }; 151 | 152 | nav.toggleCurrent = function (elem) { 153 | var parent_li = elem.closest('li'); 154 | parent_li.siblings('li.current').removeClass('current'); 155 | parent_li.siblings().find('li.current').removeClass('current'); 156 | parent_li.find('> ul li.current').removeClass('current'); 157 | parent_li.toggleClass('current'); 158 | } 159 | 160 | return nav; 161 | }; 162 | 163 | module.exports.ThemeNav = ThemeNav(); 164 | 165 | if (typeof(window) != 'undefined') { 166 | window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav }; 167 | } 168 | 169 | },{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]); 170 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = css/theme.css 4 | 5 | [options] 6 | typekit_id = hiw1hhg 7 | analytics_id = 8 | sticky_navigation = False 9 | logo_only = 10 | collapse_navigation = False 11 | display_version = True 12 | navigation_depth = 4 13 | prev_next_buttons_location = bottom 14 | canonical_url = 15 | -------------------------------------------------------------------------------- /docs/_themes/sphinx_rtd_theme/versions.html: -------------------------------------------------------------------------------- 1 | {% if READTHEDOCS %} 2 | {# Add rst-badge after rst-versions for small badge style. #} 3 |
4 | 5 | Read the Docs 6 | v: {{ current_version }} 7 | 8 | 9 |
10 |
11 |
{{ _('Versions') }}
12 | {% for slug, url in versions %} 13 |
{{ slug }}
14 | {% endfor %} 15 |
16 |
17 |
{{ _('Downloads') }}
18 | {% for type, url in downloads %} 19 |
{{ type }}
20 | {% endfor %} 21 |
22 |
23 |
{{ _('On Read the Docs') }}
24 |
25 | {{ _('Project Home') }} 26 |
27 |
28 | {{ _('Builds') }} 29 |
30 |
31 |
32 | {% trans %}Free document hosting provided by Read the Docs.{% endtrans %} 33 | 34 |
35 |
36 | {% endif %} 37 | 38 | -------------------------------------------------------------------------------- /docs/build.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | Build GOTCHA 3 | ============= 4 | 5 | This section describes how to build GOTCHA, and what 6 | :ref:`configure time options ` are available. 7 | 8 | There are two build options: 9 | 10 | * build GOTCHA with Spack, and 11 | * build GOTCHA with cmake 12 | 13 | ---------- 14 | 15 | ----------------------------------------- 16 | Build GOTCHA with Spack 17 | ----------------------------------------- 18 | 19 | 20 | One may install GOTCHA with Spack_. 21 | If you already have Spack, make sure you have the latest release. 22 | If you use a clone of the Spack develop branch, be sure to pull the latest changes. 23 | 24 | .. _build-label: 25 | 26 | Install Spack 27 | ************* 28 | .. code-block:: Bash 29 | 30 | $ git clone https://github.com/spack/spack 31 | $ # create a packages.yaml specific to your machine 32 | $ . spack/share/spack/setup-env.sh 33 | 34 | Use `Spack's shell support`_ to add Spack to your ``PATH`` and enable use of the 35 | ``spack`` command. 36 | 37 | Build and Install GOTCHA 38 | ************************* 39 | 40 | .. code-block:: Bash 41 | 42 | $ spack install gotcha 43 | $ spack load gotcha 44 | 45 | If the most recent changes on the development branch ('dev') of GOTCHA are 46 | desired, then do ``spack install gotcha@develop``. 47 | 48 | .. attention:: 49 | 50 | The initial install could take a while as Spack will install build 51 | dependencies (autoconf, automake, m4, libtool, and pkg-config) as well as 52 | any dependencies of dependencies (cmake, perl, etc.) if you don't already 53 | have these dependencies installed through Spack or haven't told Spack where 54 | they are locally installed on your system (i.e., through a custom 55 | packages.yaml_). 56 | Run ``spack spec -I gotcha`` before installing to see what Spack is going 57 | to do. 58 | 59 | ---------- 60 | 61 | ------------------------- 62 | Build GOTCHA with CMake 63 | ------------------------- 64 | 65 | Download the latest GOTCHA release from the Releases_ page or clone the develop 66 | branch ('develop') from the GOTCHA repository 67 | `https://github.com/LLNL/GOTCHA `_. 68 | 69 | 70 | .. code-block:: Bash 71 | 72 | cmake . -B build -DCMAKE_INSTALL_PREFIX= 73 | cmake --build build 74 | cmake --install build 75 | 76 | ----------- 77 | 78 | .. explicit external hyperlink targets 79 | 80 | .. _Releases: https://github.com/LLNL/GOTCHA/releases 81 | .. _Spack: https://github.com/spack/spack 82 | .. _Spack's shell support: https://spack.readthedocs.io/en/latest/getting_started.html#add-spack-to-the-shell 83 | .. _packages.yaml: https://spack.readthedocs.io/en/latest/build_settings.html#external-packages 84 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/stable/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'Gotcha' 23 | copyright = u'2018, Lawrence Livermore National Security, LLC' 24 | author = u'Hariharan Devarajan, David Poliakoff, Matt Legendre' 25 | 26 | # The short X.Y version 27 | version = u'1.0' 28 | # The full version, including alpha/beta/rc tags 29 | release = u'1.0.8' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | ] 43 | 44 | # Add any paths that contain templates here, relative to this directory. 45 | templates_path = ['_templates'] 46 | 47 | # The suffix(es) of source filenames. 48 | # You can specify multiple suffix as a list of string: 49 | # 50 | # source_suffix = ['.rst', '.md'] 51 | source_suffix = '.rst' 52 | 53 | # The master toctree document. 54 | master_doc = 'index' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | # 59 | # This is also used if you do content translation via gettext catalogs. 60 | # Usually you set "language" from the command line for these cases. 61 | language = 'en' 62 | 63 | # List of patterns, relative to source directory, that match files and 64 | # directories to ignore when looking for source files. 65 | # This pattern also affects html_static_path and html_extra_path . 66 | exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] 67 | 68 | # The name of the Pygments (syntax highlighting) style to use. 69 | pygments_style = 'sphinx' 70 | 71 | 72 | # -- Options for HTML output ------------------------------------------------- 73 | 74 | # The theme to use for HTML and HTML Help pages. See the documentation for 75 | # a list of builtin themes. 76 | # 77 | html_theme = 'sphinx_rtd_theme' 78 | 79 | # Theme options are theme-specific and customize the look and feel of a theme 80 | # further. For a list of options available for each theme, see the 81 | # documentation. 82 | # 83 | html_theme_options = { 'logo_only' : True } 84 | 85 | # Add any paths that contain custom themes here, relative to this directory. 86 | html_theme_path = ["_themes"] 87 | 88 | # Add any paths that contain custom static files (such as style sheets) here, 89 | # relative to this directory. They are copied after the builtin static files, 90 | # so a file named "default.css" will overwrite the builtin "default.css". 91 | html_static_path = ['_static'] 92 | 93 | # The name of an image file (relative to this directory) to place at the top 94 | # of the sidebar. 95 | html_logo = 'images/gotcha-logo.png' 96 | 97 | # Custom sidebar templates, must be a dictionary that maps document names 98 | # to template names. 99 | # 100 | # The default sidebars (for documents that don't match any pattern) are 101 | # defined by theme itself. Builtin themes are using these templates by 102 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 103 | # 'searchbox.html']``. 104 | # 105 | # html_sidebars = {} 106 | 107 | # If true, `todo` and `todoList` produce output, else they produce nothing. 108 | todo_include_todos = False 109 | 110 | # -- Options for HTMLHelp output --------------------------------------------- 111 | 112 | # Output file base name for HTML help builder. 113 | htmlhelp_basename = 'Gotchadoc' 114 | 115 | 116 | # -- Options for LaTeX output ------------------------------------------------ 117 | 118 | latex_elements = { 119 | # The paper size ('letterpaper' or 'a4paper'). 120 | # 121 | # 'papersize': 'letterpaper', 122 | 123 | # The font size ('10pt', '11pt' or '12pt'). 124 | # 125 | # 'pointsize': '10pt', 126 | 127 | # Additional stuff for the LaTeX preamble. 128 | # 129 | # 'preamble': '', 130 | 131 | # Latex figure (float) alignment 132 | # 133 | # 'figure_align': 'htbp', 134 | } 135 | 136 | # Grouping the document tree into LaTeX files. List of tuples 137 | # (source start file, target name, title, 138 | # author, documentclass [howto, manual, or own class]). 139 | latex_documents = [ 140 | (master_doc, 'Gotcha.tex', u'Gotcha Documentation', 141 | author, 'manual'), 142 | ] 143 | 144 | # The name of an image file (relative to this directory) to place at the top of 145 | # the title page. 146 | latex_logo = 'images/gotcha-logo.png' 147 | 148 | 149 | # -- Options for manual page output ------------------------------------------ 150 | 151 | # One entry per manual page. List of tuples 152 | # (source start file, name, description, authors, manual section). 153 | man_pages = [ 154 | (master_doc, 'gotcha', u'Gotcha Documentation', 155 | [author], 1) 156 | ] 157 | 158 | 159 | # -- Options for Texinfo output ---------------------------------------------- 160 | 161 | # Grouping the document tree into Texinfo files. List of tuples 162 | # (source start file, target name, title, author, 163 | # dir menu entry, description, category) 164 | texinfo_documents = [ 165 | (master_doc, 'Gotcha', u'Gotcha Documentation', 166 | author, 'Gotcha', 'GOTCHA is a library for wrapping function calls in shared libraries.', 167 | 'Miscellaneous'), 168 | ] 169 | -------------------------------------------------------------------------------- /docs/definitions.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Definitions 3 | ================ 4 | 5 | This section defines some terms used throughout the document. 6 | 7 | GOT 8 | **** 9 | 10 | The Global Offset Table, or GOT, is a section of a computer program's (executables and shared libraries) memory used to enable computer program code compiled as an ELF file to run correctly, independent of the memory address where the program's code or data is loaded at runtime. 11 | More details can be read at `GOT Documentation`_. 12 | 13 | 14 | ELF 15 | **** 16 | 17 | In computing, the Executable and Linkable Format[2] (ELF, formerly named Extensible Linking Format), is a common standard file format for executable files, object code, shared libraries, and core dumps. 18 | 19 | 20 | LD_PRELOAD 21 | ********** 22 | 23 | LD_PRELOAD is a powerful and advanced feature in the Linux dynamic linker that allows users to preload shared object files into the address space of a process. 24 | Read more at `LD_PRELOAD Documentation`_. 25 | 26 | ABI-compatibility 27 | ***************** 28 | 29 | An application binary interface (ABI) is an interface between two binary program modules. An ABI defines how data structures or computational routines are accessed in machine code, which is a low-level, hardware-dependent format. 30 | 31 | .. explicit external hyperlink targets 32 | 33 | .. _`GOT Documentation`: https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_zSeries/x2251.html 34 | .. _`LD_PRELOAD Documentation`: https://man7.org/linux/man-pages/man8/ld.so.8.html 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/developer-guide.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/developer-guide.rst -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | **************** 2 | Example Programs 3 | **************** 4 | 5 | This example shows how to use gotcha to wrap the open and fopen libc 6 | calls. This example is self-contained, though in typical gotcha 7 | workflows the gotcha calls would be in a separate library from the 8 | application. 9 | 10 | The example logs the parameters and return result of every open and 11 | fopen call to stderr. 12 | 13 | .. code-block:: c 14 | :linenos: 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "gotcha/gotcha.h" 22 | 23 | typedef int (*open_fptr)(const char *pathname, int flags, mode_t mode); 24 | typedef FILE* (*fopen_fptr)(const char *pathname, const char *mode); 25 | 26 | static gotcha_wrappee_handle_t open_handle; 27 | static gotcha_wrappee_handle_t fopen_handle; 28 | 29 | static int open_wrapper(const char *pathname, int flags, mode_t mode) { 30 | open_fptr open_wrappee = (open_fptr) gotcha_get_wrappee(open_handle); 31 | int result = open_wrappee(pathname, flags, mode); 32 | fprintf(stderr, "open(%s, %d, %u) = %d\n", 33 | pathname, flags, (unsigned int) mode, result); 34 | return result; 35 | } 36 | 37 | static FILE *fopen_wrapper(const char *path, const char *mode) { 38 | fopen_fptr fopen_wrappee = (fopen_fptr) gotcha_get_wrappee(fopen_handle); 39 | FILE *result = fopen_wrappee(path, mode); 40 | fprintf(stderr, "fopen(%s, %s) = %p\n", 41 | path, mode, result); 42 | return result; 43 | } 44 | 45 | static gotcha_binding_t bindings[] = { 46 | { "open", open_wrapper, &open_handle }, 47 | { "fopen", fopen_wrapper, &fopen_handle } 48 | }; 49 | 50 | int main(int argc, char *argv[]) { 51 | gotcha_wrap(bindings, 2, "demotool"); 52 | 53 | open("/dev/null", O_RDONLY); 54 | open("/dev/null", O_WRONLY | O_CREAT | O_EXCL); 55 | fopen("/dev/random", "r"); 56 | fopen("/does/not/exist", "w"); 57 | 58 | return 0; 59 | } 60 | 61 | The fundamental data structure in the Gotcha API is the gotcha_binding_t 62 | table, which is shown in lines 29-32. This table states that calls 63 | to open should be rerouted to call open_wrapper, and similarly 64 | for fopen and fopen_wrapper. The original open and fopen functions will 65 | still be accessible via the handles open_handle and fopen_handle. 66 | 67 | The binding table is passed to Gotcha on line 36, which specifies there 68 | are two entries in the table and that these are part of the “demotool” 69 | tool. The open_handle and fopen_handle variables are updated by this 70 | call to gotcha_wrap and can now be used to look up function pointers to 71 | the original open and fopen calls. 72 | 73 | The subsequent callsites to open and fopen on lines 37-40 are redirected 74 | to respectively call open_wrapper and fopen_wrapper on lines 14-20 and 75 | 22-27. Each of these functions looks up the original open and fopen 76 | functions using the gotcha_get_wrappee API call and the open_handle and 77 | fopen_handle on lines 15 and 23. 78 | 79 | The wrappers call then call the underlying functions open and fopen 80 | functions on lines 16 and 24. The print the parameters and results of 81 | these calls on lines 17 and 25 and return. 82 | 83 | Note that this example skips proper error handling for brevity. The call 84 | to gotcha_wrap could have failed to find instances of fopen and open in 85 | the process, which would have led to an error return. The calls to 86 | fprintf on lines 17 and 25 are stomping on the value of errno, which 87 | could be set in the open and fopen calls on lines 16 and 24. 88 | -------------------------------------------------------------------------------- /docs/images/gotcha-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/GOTCHA/7edbeb580747cf2244296ab34416de771918bb56/docs/images/gotcha-logo.png -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. gotcha documentation master file, created by 2 | sphinx-quickstart on Sun Nov 26 20:15:18 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | =========================================================================== 7 | GOTCHA: GOTCHA is a library for wrapping function calls in shared libraries 8 | =========================================================================== 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | :caption: User Guide 13 | 14 | overview 15 | definitions 16 | limitations 17 | build 18 | api 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | :caption: Reference 23 | 24 | examples 25 | 26 | .. toctree:: 27 | :maxdepth: 2 28 | :caption: Contributing 29 | 30 | developer-guide 31 | style-guides 32 | testing 33 | 34 | ================== 35 | Indices and tables 36 | ================== 37 | 38 | * :ref:`genindex` 39 | * :ref:`modindex` 40 | * :ref:`search` 41 | 42 | -------------------------------------------------------------------------------- /docs/limitations.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Limitations 3 | =========================== 4 | 5 | ------------------- 6 | General Limitations 7 | ------------------- 8 | 9 | Operating system support 10 | ************************* 11 | 12 | As the ELF is the file format used for .o object files, binaries, shared libraries and core dumps in Linux. 13 | We currently only support Linux OS. 14 | 15 | Intra and Intra-library calls 16 | ***************************** 17 | 18 | Gotcha works by rewriting the Global Offset Table (GOT) that links inter-library callsites and variable references to their targets. 19 | Because of this Gotcha cannot wrap intra-library calls (such as a call to a static function in C) or calls in statically-linked binaries. 20 | Binary rewriting technology such as DyninstAPI_ is more appropriate for these use cases. 21 | Additionally, the function pointer wrapping feature with GOTCHA only applies to function pointers created after wrapping functions. 22 | The function pointers created before wrapping would not be wrapped by gotcha. 23 | 24 | .. _DyninstAPI: https://github.com/dyninst/dyninst 25 | -------------------------------------------------------------------------------- /docs/overview.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Overview 3 | ======== 4 | 5 | Gotcha is an API that provides function wrapping, interposing a wrapper 6 | function between a function and its callsites. Many tools rely on function wrapping 7 | as a fundamental building block. For example, a performance analysis 8 | tool which wants to measure time an application spends in IO might put 9 | wrappers around "read()" and "write()" which trigger stopwatches. 10 | 11 | Tools traditionally implemented function wrapping with the LD_PRELOAD 12 | environment variable on glibc-based systems. This environment variable 13 | allowed the tool to inject a tool library into the target application. 14 | Any functions that the tool library exports, such as a "read()" or 15 | "write()" function, will intercept calls to the matching function names 16 | from the original application. While powerful, the LD_PRELOAD approach 17 | had several limitations: 18 | 19 | - Tool libraries can have challenges matching ABI-compatibility with 20 | the application. 21 | 22 | - Multiple tools cannot wrap the same function. 23 | 24 | - The set of wrapped functions are determined at tool build-time and 25 | cannot be changed in response to application behavior. 26 | 27 | Gotcha addresses these limitations by providing an API for function 28 | wrapping. Tool libraries make wrapping requests to Gotcha that say, for 29 | example, “wrap all calls to the read() function with my tool_read() 30 | function, and give me a function pointer to the original read().” 31 | Gotcha’s API allows tool wrapping decisions to be made at runtime, and 32 | it handles cases of multiple tools wrapping the same function. It does 33 | not, however, provide any new mechanisms for injecting the tool library 34 | into an application. Gotcha-based tools should be added to the 35 | application at link-time or injected with LD_PRELOAD. 36 | 37 | Gotcha works by rewriting the Global Offset Table (GOT) that links 38 | inter-library callsites and variable references to their targets. 39 | Because of this Gotcha cannot wrap intra-library calls (such as a call 40 | to a static function in C) or calls in statically-linked binaries. 41 | Binary rewriting technology such as DyninstAPI_ is more appropriate for these use 42 | cases. 43 | 44 | .. _DyninstAPI: https://github.com/dyninst/dyninst -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx<7.0.0 2 | sphinx-rtd-theme -------------------------------------------------------------------------------- /docs/style-guides.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | Style Guides 3 | ************ 4 | 5 | Coding Conventions 6 | ================== 7 | 8 | GOTCHA follows the `Google coding style 9 | `_. Please run 10 | ``git clang-format --diff HEAD~1 -q`` to check your patch for style problems before submitting it 11 | for review. 12 | 13 | Styling Code 14 | ------------ 15 | 16 | The clang-format tool can be used to apply much of the required code styling used in 17 | the project. 18 | 19 | .. code-block:: Bash 20 | :caption: To apply style to the source file foo.c: 21 | 22 | clang-format --style=Google --Werror foo.c 23 | 24 | The `.clang-format file 25 | `_ specifies 26 | the options used for this project. For a full list of available clang-format options, 27 | see https://clang.llvm.org/docs/ClangFormat.html. 28 | 29 | .. _style-check-label: 30 | 31 | Verifying Style Checks 32 | ---------------------- 33 | 34 | To check that uncommitted changes meet the coding style, use the following 35 | command: 36 | 37 | .. code-block:: Bash 38 | 39 | git clang-format --diff HEAD~1 -q 40 | 41 | .. tip:: 42 | 43 | This command will only check specific changes and additions to files that 44 | are already tracked by git. Run the command ``git add -N 45 | [...]`` first in order to style check new files as well. 46 | 47 | ------------ 48 | 49 | .. _commit-message-label: 50 | 51 | Commit Message Format 52 | ===================== 53 | 54 | Commit messages for new changes must meet the following guidelines: 55 | 56 | - In 50 characters or less, provide a summary of the change as the first line 57 | in the commit message. 58 | - A body which provides a description of the change. If necessary, please 59 | summarize important information such as why the proposed approach was chosen 60 | or a brief description of the bug you are resolving. Each line of the body 61 | must be 72 characters or less. 62 | 63 | An example commit message for new changes is provided below. 64 | 65 | .. code-block:: none 66 | 67 | Capitalized, short (50 chars or less) summary 68 | 69 | More detailed explanatory text, if necessary. Wrap it to about 72 70 | characters or so. In some contexts, the first line is treated as the 71 | subject of an email and the rest of the text as the body. The blank 72 | line separating the summary from the body is critical (unless you omit 73 | the body entirely); tools like rebase can get confused if you run the 74 | two together. 75 | 76 | Write your commit message in the imperative: "Fix bug" and not "Fixed bug" 77 | or "Fixes bug." This convention matches up with commit messages generated 78 | by commands like git merge and git revert. 79 | 80 | Further paragraphs come after blank lines. 81 | 82 | - Bullet points are okay 83 | 84 | - Typically a hyphen or asterisk is used for the bullet, followed by a 85 | single space, with blank lines in between, but conventions vary here 86 | 87 | - Use a hanging indent 88 | -------------------------------------------------------------------------------- /docs/testing.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | Testing Guide 3 | ============= 4 | 5 | We can never have enough testing. Any additional tests you can write are always 6 | greatly appreciated. 7 | 8 | ---------- 9 | Unit Tests 10 | ---------- 11 | 12 | Testing new core features within GOTCHA should be implemented in the ``test/unit/gotcha_unit_tests.c`` using the check framework as defined in ``_. 13 | 14 | 15 | Create a new test 16 | ^^^^^^^^^^^^^^^^^ 17 | We can create a new test using ``START_TEST`` and ``END_TEST`` macros. 18 | 19 | .. code-block:: c 20 | 21 | START_TEST(sample_test){ 22 | } 23 | END_TEST 24 | 25 | Create a new suite 26 | ^^^^^^^^^^^^^^^^^^ 27 | These new tests can be added to new suite with code similar to the following. 28 | To add to existing suite, we need use ``tcase_add_test`` api to add the test function to the suite. 29 | 30 | .. code-block:: c 31 | 32 | Suite* gotcha_sample_suite(){ 33 | Suite* s = suite_create("Sample"); 34 | TCase* sample_case = configured_case_create("Basic tests"); 35 | tcase_add_test(sample_case, sample_test); 36 | suite_add_tcase(s, sample_case); 37 | return s; 38 | } 39 | 40 | Adding suite to runner 41 | ^^^^^^^^^^^^^^^^^^^^^^ 42 | 43 | Within the main function of the ``test/unit/gotcha_unit_tests.c``, the gotcha_sample_suite can be added as follows. 44 | 45 | .. code-block:: c 46 | 47 | Suite* sample_suite = gotcha_sample_suite(); 48 | SRunner* sample_runner = srunner_create(sample_suite); 49 | srunner_run_all(sample_suite, CK_NORMAL); 50 | num_fails += srunner_ntests_failed(sample_suite); 51 | 52 | 53 | ------------------------------------- 54 | Testing tool specific usage of GOTCHA 55 | ------------------------------------- 56 | 57 | We should use custom test cases where we are testing the API for GOTCHA for specific features such as filtering libraries, main function bindings, etc. 58 | These test cases can be stored within the ``test`` folder. Look at existing examples such as ``test/stack`` and ``test/dlopen`` to understand how we can implement these tests. 59 | 60 | Once you add a self containing test case within ``test``, we can add it to the ``test/CMakeLists.txt``. 61 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install(DIRECTORY gotcha DESTINATION include FILES_MATCHING PATTERN *.h) 2 | -------------------------------------------------------------------------------- /include/gotcha/gotcha.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | /*! 17 | ****************************************************************************** 18 | * 19 | * \file gotcha.h 20 | * 21 | * \brief Header file containing the external gotcha interface 22 | * 23 | * The intended use pattern is as follows 24 | * 25 | * TODO ON-INTERFACE-SOLID: document the 26 | *interface usage 27 | * 28 | ****************************************************************************** 29 | */ 30 | #ifndef GOTCHA_H 31 | #define GOTCHA_H 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #if defined(__cplusplus) 38 | extern "C" { 39 | #endif 40 | 41 | /*! 42 | ****************************************************************************** 43 | * \def GOTCHA_MAKE_FUNCTION_PTR(name, ret_type, ...) 44 | * \brief Makes a function pointer with a given name, return type, and 45 | * parameters 46 | * \param name The name of the function you want to get a pointer to 47 | * \param ret_type The return type of the function you want a pointer to 48 | * \param ... A comma separated list of the types of the parameters 49 | * to the function you're getting a pointer to 50 | ****************************************************************************** 51 | */ 52 | 53 | #define GOTCHA_MAKE_FUNCTION_PTR(name, ret_type, ...) \ 54 | ret_type (*name)(__VA_ARGS__) 55 | 56 | #define GOTCHA_EXPORT __attribute__((__visibility__("default"))) 57 | 58 | /*! 59 | ****************************************************************************** 60 | * 61 | * \fn enum gotcha_error_t gotcha_wrap(struct gotcha_binding_t* bindings, 62 | * void** wrappers, void*** originals, 63 | * int num_actions); 64 | * 65 | * \brief Makes GOTCHA wrap the functions picked in gotcha_prepare_symbols 66 | * 67 | * \param bindings A list of bindings to wrap 68 | * \param num_actions The number of items in the bindings table 69 | * \param tool_name A name you use to represent your tool when 70 | * stacking multiple tools (currently unused). 71 | * 72 | ****************************************************************************** 73 | */ 74 | 75 | GOTCHA_EXPORT enum gotcha_error_t gotcha_wrap(struct gotcha_binding_t *bindings, 76 | int num_actions, 77 | const char *tool_name); 78 | 79 | /*! 80 | ****************************************************************************** 81 | * 82 | * \fn enum gotcha_error_t gotcha_set_priority(const char *tool_name, 83 | * int value); 84 | * 85 | * \brief Set the tool priority, which controls how multiple tools stack 86 | * wrappings over the same functions. 87 | * 88 | * \param tool_name The tool name to set the priority of 89 | * \param priority The new priority value for the tool. Lower values 90 | * are called innermost. 91 | * 92 | ****************************************************************************** 93 | */ 94 | GOTCHA_EXPORT enum gotcha_error_t gotcha_set_priority(const char *tool_name, 95 | int priority); 96 | 97 | /*! 98 | ****************************************************************************** 99 | * 100 | * \fn enum gotcha_error_t gotcha_get_priority(const char *tool_name, 101 | * int *value); 102 | * 103 | * \brief Gets the tool priority, which controls how multiple tools stack 104 | * wrappings over the same functions. 105 | * 106 | * \param tool_name The tool name to get the priority of 107 | * \param num_actions Output parameters with the priority for the tool. 108 | * 109 | ****************************************************************************** 110 | */ 111 | GOTCHA_EXPORT enum gotcha_error_t gotcha_get_priority(const char *tool_name, 112 | int *priority); 113 | 114 | /*! 115 | ****************************************************************************** 116 | * 117 | * \fn enum void* gotcha_get_wrappee(gotcha_wrappee_handle_t) 118 | * 119 | * \brief Given a GOTCHA wrapper's handle, returns the wrapped function for it 120 | *to call 121 | * 122 | * \param handle The wrappee handle to return the function pointer for 123 | * 124 | ****************************************************************************** 125 | */ 126 | GOTCHA_EXPORT void *gotcha_get_wrappee(gotcha_wrappee_handle_t handle); 127 | 128 | GOTCHA_EXPORT void gotcha_filter_libraries_by_name(const char *nameFilter); 129 | GOTCHA_EXPORT void gotcha_only_filter_last(); 130 | GOTCHA_EXPORT void gotcha_set_library_filter_func( 131 | int (*new_func)(struct link_map *)); 132 | GOTCHA_EXPORT void gotcha_restore_library_filter_func(); 133 | 134 | #if defined(__cplusplus) 135 | } 136 | #endif 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /include/gotcha/gotcha_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | /*! 16 | ****************************************************************************** 17 | * 18 | * \file gotcha_types.h 19 | * 20 | * \brief Header file containing the internal gotcha types 21 | * 22 | ****************************************************************************** 23 | */ 24 | #ifndef GOTCHA_TYPES_H 25 | #define GOTCHA_TYPES_H 26 | 27 | #if defined(__cplusplus) 28 | extern "C" { 29 | #endif 30 | 31 | typedef void *gotcha_wrappee_handle_t; 32 | 33 | /*! 34 | * The representation of a Gotcha action 35 | * as it passes through the pipeline 36 | */ 37 | typedef struct gotcha_binding_t { 38 | const char *name; //!< The name of the function being wrapped 39 | void *wrapper_pointer; //!< A pointer to the wrapper function 40 | gotcha_wrappee_handle_t 41 | *function_handle; //!< A pointer to the function being wrapped 42 | } gotcha_binding_t; 43 | 44 | /*! 45 | * The representation of an error (or success) of a Gotcha action 46 | */ 47 | typedef enum gotcha_error_t { 48 | GOTCHA_SUCCESS = 0, //!< The call succeeded 49 | GOTCHA_FUNCTION_NOT_FOUND, //!< The call looked up a function which could not 50 | //!< be found 51 | GOTCHA_INTERNAL, //!< Internal gotcha error 52 | GOTCHA_INVALID_TOOL //!< Invalid tool name 53 | } gotcha_error_t; 54 | 55 | #if defined(__cplusplus) 56 | } 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(GNUInstallDirs) 2 | set(GOTCHA_SOURCES 3 | gotcha_utils.c 4 | gotcha.c 5 | gotcha_auxv.c 6 | libc_wrappers.c 7 | elf_ops.c 8 | hash.c 9 | tool.c 10 | library_filters.c 11 | gotcha_dl.c 12 | translations.c 13 | ) 14 | 15 | add_library(gotcha SHARED ${GOTCHA_SOURCES}) 16 | 17 | 18 | set_target_properties(gotcha PROPERTIES SOVERSION ${LIBTOOL_INTERFACE}) 19 | set_target_properties(gotcha PROPERTIES VERSION "${LIBTOOL_INTERFACE}.${LIBTOOL_REVISION}.${LIBTOOL_AGE}") 20 | set_target_properties(gotcha PROPERTIES COMPILE_FLAGS "-fvisibility=${DEFAULT_SYMBOL_VISIBILITY}") 21 | if (GOTCHA_ENABLE_WARNING_ERROR) 22 | set_target_properties(gotcha PROPERTIES COMPILE_FLAGS "-Wall -Werror") 23 | endif () 24 | set_target_properties(gotcha PROPERTIES LINK_FLAGS "-fvisibility=${DEFAULT_SYMBOL_VISIBILITY}") 25 | target_include_directories(gotcha PUBLIC 26 | $ 27 | $) 28 | if (GOTCHA_ENABLE_TESTS) 29 | add_library(gotcha_no_libc SHARED ${GOTCHA_SOURCES}) 30 | set_target_properties(gotcha_no_libc PROPERTIES SOVERSION ${LIBTOOL_INTERFACE}) 31 | set_target_properties(gotcha_no_libc PROPERTIES VERSION "${LIBTOOL_INTERFACE}.${LIBTOOL_REVISION}.${LIBTOOL_AGE}") 32 | set_target_properties(gotcha_no_libc PROPERTIES COMPILE_DEFINITIONS "FORCE_NO_LIBC") 33 | set_target_properties(gotcha_no_libc PROPERTIES COMPILE_FLAGS "-fvisibility=${DEFAULT_SYMBOL_VISIBILITY}") 34 | set_target_properties(gotcha_no_libc PROPERTIES LINK_FLAGS "-fvisibility=${DEFAULT_SYMBOL_VISIBILITY}") 35 | endif () 36 | 37 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 38 | 39 | install(TARGETS gotcha EXPORT gotcha-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}) 40 | install(EXPORT gotcha-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/gotcha) 41 | 42 | add_subdirectory(example) 43 | -------------------------------------------------------------------------------- /src/elf_ops.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "elf_ops.h" 17 | 18 | #include 19 | 20 | #include "libc_wrappers.h" 21 | struct gnu_hash_header { 22 | uint32_t nbuckets; //!< The number of buckets to hash symbols into 23 | uint32_t symndx; //!< Index of the first symbol accessible via hashtable in 24 | //!< the symbol table 25 | uint32_t maskwords; //!< Number of words in the hash table's bloom filter 26 | uint32_t shift2; //!< The bloom filter's shift count 27 | }; 28 | 29 | static uint32_t gnu_hash_func(const char *str) { 30 | uint32_t hash = 5381; 31 | for (; *str != '\0'; str++) { 32 | hash = hash * 33 + *str; 33 | } 34 | return hash; 35 | } 36 | 37 | /* Symbol versioning 38 | * 39 | * https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA.junk/symversion.html 40 | * 41 | * versym[symidx] does only provides an index into the ElfW(Verdef) array 42 | * (DT_VERDEF/SHT_GNU_verdef) and is not the version itself, but SHT_GNU_verdef 43 | * is sorted in ascending order and the entries have a parent relation, thus a 44 | * higher index should always be a higher version. As we only search for the 45 | * latest symbol/highest version it is sufficient to compare the index. 46 | */ 47 | 48 | signed long lookup_gnu_hash_symbol(const char *name, ElfW(Sym) * syms, 49 | ElfW(Half) * versym, char *symnames, 50 | void *sheader) { 51 | uint32_t *buckets = NULL, *vals = NULL; 52 | uint32_t hash_val = 0; 53 | uint32_t cur_sym = 0, cur_sym_hashval = 0; 54 | signed long latest_sym = -1; 55 | ElfW(Half) latest_sym_ver = 0; 56 | struct gnu_hash_header *header = (struct gnu_hash_header *)(sheader); 57 | 58 | buckets = (uint32_t *)(((unsigned char *)(header + 1)) + 59 | (header->maskwords * sizeof(ElfW(Addr)))); 60 | vals = buckets + header->nbuckets; 61 | 62 | hash_val = gnu_hash_func(name); 63 | cur_sym = buckets[hash_val % header->nbuckets]; 64 | if (cur_sym == 0) { 65 | return -1; 66 | } 67 | 68 | hash_val &= ~1; 69 | for (;;) { 70 | cur_sym_hashval = vals[cur_sym - header->symndx]; 71 | if (((cur_sym_hashval & ~1) == hash_val) && 72 | (gotcha_strcmp(name, symnames + syms[cur_sym].st_name) == 0)) { 73 | if (!versym) { 74 | return (signed long)cur_sym; 75 | } 76 | 77 | if ((versym[cur_sym] & 0x7fff) > latest_sym_ver) { 78 | latest_sym = (signed long)cur_sym; 79 | latest_sym_ver = versym[cur_sym] & 0x7fff; 80 | } 81 | } 82 | if (cur_sym_hashval & 1) { 83 | break; 84 | } 85 | cur_sym++; 86 | } 87 | 88 | return latest_sym; 89 | } 90 | 91 | static unsigned long elf_hash(const unsigned char *name) { 92 | unsigned int h = 0, g = 0; 93 | while (*name != '\0') { 94 | h = (h << 4) + *name++; 95 | if ((g = h & 0xf0000000)) { 96 | h ^= g >> 24; 97 | } 98 | h &= ~g; 99 | } 100 | return h; 101 | } 102 | 103 | signed long lookup_elf_hash_symbol(const char *name, ElfW(Sym) * syms, 104 | ElfW(Half) * versym, char *symnames, 105 | ElfW(Word) * header) { 106 | ElfW(Word) *nbucket = header + 0; 107 | ElfW(Word) *buckets = header + 2; 108 | ElfW(Word) *chains = buckets + *nbucket; 109 | signed long latest_sym = -1; 110 | ElfW(Half) latest_sym_ver = 0; 111 | 112 | unsigned int x = elf_hash((const unsigned char *)name); 113 | signed long y = (signed long)buckets[x % *nbucket]; 114 | while (y != STN_UNDEF) { 115 | if (gotcha_strcmp(name, symnames + syms[y].st_name) == 0) { 116 | if (!versym) { 117 | // in general all libs would have version but it is a guard condition. 118 | return y; // GCOVR_EXCL_LINE 119 | } 120 | 121 | if ((versym[y] & 0x7fff) > latest_sym_ver) { 122 | latest_sym = y; 123 | latest_sym_ver = versym[y] & 0x7fff; 124 | } 125 | } 126 | y = chains[y]; 127 | } 128 | 129 | return latest_sym; 130 | } 131 | -------------------------------------------------------------------------------- /src/example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(autotee) 2 | add_subdirectory(minimal) 3 | -------------------------------------------------------------------------------- /src/example/autotee/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(autotee SHARED autotee.c) 2 | add_executable(autotee_test test_autotee.c) 3 | target_link_libraries(autotee gotcha) 4 | target_link_libraries(autotee_test autotee) 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/example/autotee/autotee.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | /** 17 | * autotee - 18 | * Using gotcha, wrap the major IO writing routines with functions that 19 | * "tee" any stdout output to another file. Init by calling 20 | * init_autotee(filename) 21 | * finish by calling: 22 | * close_autotee() 23 | * 24 | * Note, this is a demonstration program for gotcha and does not handle 25 | * cases like stdout's file descriptor being dup'd or more esoteric 26 | * IO routines. 27 | **/ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "gotcha/gotcha.h" 35 | #include "gotcha/gotcha_types.h" 36 | 37 | static int tee_fd = -1; 38 | static FILE *tee_FILE = NULL; 39 | 40 | static int printf_wrapper(const char *format, ...); 41 | static int fprintf_wrapper(FILE *stream, const char *format, ...); 42 | static int vfprintf_wrapper(FILE *stream, const char *str, va_list args); 43 | static int vprintf_wrapper(const char *str, va_list args); 44 | static ssize_t write_wrapper(int fd, const void *buffer, size_t size); 45 | static int puts_wrapper(const char *str); 46 | static int fputs_wrapper(const char *str, FILE *f); 47 | static int fwrite_wrapper(const void *ptr, size_t size, size_t nmemb, 48 | FILE *stream); 49 | 50 | static gotcha_wrappee_handle_t orig_printf_handle; 51 | static gotcha_wrappee_handle_t orig_fprintf_handle; 52 | static gotcha_wrappee_handle_t orig_vfprintf_handle; 53 | static gotcha_wrappee_handle_t orig_vprintf_handle; 54 | static gotcha_wrappee_handle_t orig_write_handle; 55 | static gotcha_wrappee_handle_t orig_puts_handle; 56 | static gotcha_wrappee_handle_t orig_fputs_handle; 57 | static gotcha_wrappee_handle_t orig_fwrite_handle; 58 | 59 | #define NUM_IOFUNCS 8 60 | struct gotcha_binding_t iofuncs[] = { 61 | {"printf", printf_wrapper, &orig_printf_handle}, 62 | {"fprintf", fprintf_wrapper, &orig_fprintf_handle}, 63 | {"vfprintf", vfprintf_wrapper, &orig_vfprintf_handle}, 64 | {"vprintf", vprintf_wrapper, &orig_vprintf_handle}, 65 | {"write", write_wrapper, &orig_write_handle}, 66 | {"puts", puts_wrapper, &orig_puts_handle}, 67 | {"fputs", fputs_wrapper, &orig_fputs_handle}, 68 | {"fwrite", fwrite_wrapper, &orig_fwrite_handle}}; 69 | 70 | int init_autotee(const char *teefile) { 71 | enum gotcha_error_t result; 72 | gotcha_set_priority("testing/whether/this/works", 1); 73 | tee_FILE = fopen(teefile, "w"); 74 | if (!tee_FILE) { 75 | perror("Failed to open tee file"); 76 | return -1; 77 | } 78 | tee_fd = fileno(tee_FILE); 79 | 80 | result = gotcha_wrap(iofuncs, NUM_IOFUNCS, "testing/whether"); 81 | if (result != GOTCHA_SUCCESS) { 82 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 83 | return -1; 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | int close_autotee() { 90 | if (tee_FILE) { 91 | fclose(tee_FILE); 92 | tee_fd = -1; 93 | } 94 | return 0; 95 | } 96 | 97 | static int printf_wrapper(const char *format, ...) { 98 | typeof(&vfprintf) orig_vfprintf = gotcha_get_wrappee(orig_vfprintf_handle); 99 | typeof(&vprintf) orig_vprintf = gotcha_get_wrappee(orig_vprintf_handle); 100 | int result; 101 | va_list args, args2; 102 | va_start(args, format); 103 | 104 | if (tee_FILE) { 105 | va_copy(args2, args); 106 | orig_vfprintf(tee_FILE, format, args2); 107 | va_end(args2); 108 | } 109 | 110 | result = orig_vprintf(format, args); 111 | va_end(args); 112 | 113 | return result; 114 | } 115 | 116 | static int fprintf_wrapper(FILE *stream, const char *format, ...) { 117 | typeof(&vfprintf) orig_vfprintf = gotcha_get_wrappee(orig_vfprintf_handle); 118 | int result; 119 | va_list args, args2; 120 | va_start(args, format); 121 | 122 | if (stream != stdout) { 123 | result = orig_vfprintf(stream, format, args); 124 | } else { 125 | if (tee_FILE) { 126 | va_copy(args2, args); 127 | orig_vfprintf(tee_FILE, format, args2); 128 | va_end(args2); 129 | } 130 | result = orig_vfprintf(stdout, format, args); 131 | } 132 | 133 | va_end(args); 134 | return result; 135 | } 136 | 137 | static int vfprintf_wrapper(FILE *stream, const char *str, va_list args) { 138 | typeof(&vfprintf) orig_vfprintf = gotcha_get_wrappee(orig_vfprintf_handle); 139 | va_list args2; 140 | if (stream != stdout) { 141 | return orig_vfprintf(stream, str, args); 142 | } 143 | if (tee_FILE) { 144 | va_copy(args2, args); 145 | orig_vfprintf(tee_FILE, str, args2); 146 | va_end(args2); 147 | } 148 | return orig_vfprintf(stream, str, args); 149 | } 150 | 151 | static int vprintf_wrapper(const char *str, va_list args) { 152 | typeof(&vfprintf) orig_vfprintf = gotcha_get_wrappee(orig_vfprintf_handle); 153 | typeof(&vprintf) orig_vprintf = gotcha_get_wrappee(orig_vprintf_handle); 154 | va_list args2; 155 | if (tee_FILE) { 156 | va_copy(args2, args); 157 | orig_vfprintf(tee_FILE, str, args2); 158 | va_end(args2); 159 | } 160 | return orig_vprintf(str, args); 161 | } 162 | 163 | static ssize_t write_wrapper(int fd, const void *buffer, size_t size) { 164 | typeof(&write) orig_write = gotcha_get_wrappee(orig_write_handle); 165 | if (fd != 1) return orig_write(fd, buffer, size); 166 | 167 | if (tee_fd != -1) orig_write(tee_fd, buffer, size); 168 | return orig_write(fd, buffer, size); 169 | } 170 | 171 | static int puts_wrapper(const char *str) { 172 | typeof(&fputs) orig_fputs = gotcha_get_wrappee(orig_fputs_handle); 173 | typeof(&puts) orig_puts = gotcha_get_wrappee(orig_puts_handle); 174 | if (tee_FILE) { 175 | orig_fputs(str, tee_FILE); 176 | orig_fputs("\n", tee_FILE); 177 | } 178 | return orig_puts(str); 179 | } 180 | 181 | static int fputs_wrapper(const char *str, FILE *f) { 182 | typeof(&fputs) orig_fputs = gotcha_get_wrappee(orig_fputs_handle); 183 | if (f != stdout) return orig_fputs(str, f); 184 | if (tee_FILE) orig_fputs(str, tee_FILE); 185 | return orig_fputs(str, f); 186 | } 187 | 188 | static int fwrite_wrapper(const void *ptr, size_t size, size_t nmemb, 189 | FILE *stream) { 190 | typeof(&fwrite) orig_fwrite = gotcha_get_wrappee(orig_fwrite_handle); 191 | if (stream != stdout) return orig_fwrite(ptr, size, nmemb, stream); 192 | if (tee_FILE) orig_fwrite(ptr, size, nmemb, tee_FILE); 193 | return orig_fwrite(ptr, size, nmemb, stream); 194 | } 195 | -------------------------------------------------------------------------------- /src/example/autotee/test_autotee.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | extern int init_autotee(char *filename); 20 | extern int close_autotee(); 21 | 22 | #define OUTPUT_FILE "tee.out" 23 | 24 | int main() { 25 | int result; 26 | 27 | printf("Every stdout print after this line should also appear in %s:\n", 28 | OUTPUT_FILE); 29 | 30 | result = init_autotee(OUTPUT_FILE); 31 | if (result != 0) return -1; 32 | 33 | printf("First line\n"); 34 | printf("Second %s\n", "line"); 35 | fprintf(stdout, "Third line\n"); 36 | fprintf(stdout, "%s line\n", "Forth"); 37 | puts("Fifth line"); 38 | fputs("Sixth ", stdout); 39 | fputs("line\n", stdout); 40 | fwrite("Seventh line\n", 1, strlen("Seventh line\n"), stdout); 41 | fprintf(stderr, "Eighth line is stderr and should not appear in in %s\n", 42 | OUTPUT_FILE); 43 | close_autotee(); 44 | printf("Ninth line is after close and should not appear in %s\n", 45 | OUTPUT_FILE); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /src/example/minimal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(wrap_me SHARED sampleLib.c) 2 | add_executable(symb_look symbolLookup.c) 3 | target_link_libraries(wrap_me gotcha) 4 | target_link_libraries(symb_look wrap_me gotcha) 5 | 6 | -------------------------------------------------------------------------------- /src/example/minimal/sampleLib.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "sampleLib.h" 17 | 18 | #include 19 | 20 | // We need a place to store the pointer to the function we've wrapped 21 | gotcha_wrappee_handle_t origRetX_handle; 22 | 23 | /** 24 | * We need to express our desired wrapping behavior to 25 | * GOTCHA. For that we need three things: 26 | * 27 | * 1) The name of a symbol to wrap 28 | * 2) The function we want to wrap it with 29 | * 3) Some place to store the original function, if we wish 30 | * to call it 31 | * 32 | * This variable bindings gets filled out with a list of three 33 | * element structs containing those things. 34 | * 35 | * Note that the place to store the original function is passed 36 | * by reference, this is required for us to be able to change it 37 | */ 38 | struct gotcha_binding_t bindings[] = {{"retX", dogRetX, &origRetX_handle}}; 39 | 40 | // This is like a tool library's initialization function 41 | int sample_init() { 42 | gotcha_wrap(bindings, 1, "gotcha_internal_sample_tool"); 43 | return 0; 44 | } 45 | 46 | /** 47 | * In our example, this is the function we're wrapping. 48 | * For convenience, it's in the same library, but this 49 | * isn't a requirement imposed by GOTCHA 50 | */ 51 | int retX(int x) { return x; } 52 | 53 | /** 54 | * This is our wrapper function. All GOTCHA wrappers *must* 55 | * reference dogs somewhere in the code. I didn't write the 56 | * rules (yes I did) 57 | */ 58 | int dogRetX(int x) { 59 | typeof(&dogRetX) origRetX = gotcha_get_wrappee(origRetX_handle); 60 | printf("SO I FOR ONE THINK DOGS SHOULD RETURN %i\n", x); 61 | return origRetX ? origRetX(x) + 1 : 0; 62 | } 63 | -------------------------------------------------------------------------------- /src/example/minimal/sampleLib.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef SAMPLE_LIB_H 16 | #define SAMPLE_LIB_H 17 | #include "gotcha/gotcha.h" 18 | int sample_init(); 19 | int retX(int x); 20 | int dogRetX(int x); 21 | void *dog_malloc(int size); 22 | void *mylloc(int size); 23 | #endif 24 | -------------------------------------------------------------------------------- /src/example/minimal/symbolLookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "sampleLib.h" 24 | 25 | void dbg() {} 26 | int main() { 27 | sample_init(); 28 | int check_val = retX(9); 29 | assert(check_val == 10); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/gotcha_auxv.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #ifndef GOTCHA_AUXV_H 17 | #define GOTCHA_AUXV_H 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | int is_vdso(const struct link_map *map); 31 | unsigned int get_auxv_pagesize(); 32 | 33 | // Do not use, exposed only for unit testing 34 | int parse_auxv_contents(); 35 | struct link_map *get_vdso_from_auxv(); 36 | struct link_map *get_vdso_from_aliases(); 37 | struct link_map *get_vdso_from_maps(); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/gotcha_dl.h: -------------------------------------------------------------------------------- 1 | #ifndef GOTCHA_DL_H 2 | #define GOTCHA_DL_H 3 | 4 | #include "hash.h" 5 | #include "tool.h" 6 | 7 | void handle_libdl(); 8 | extern void update_all_library_gots(hash_table_t *bindings); 9 | extern long lookup_exported_symbol(const char *name, const struct link_map *lib, 10 | void **symbol); 11 | extern int prepare_symbol(struct internal_binding_t *binding); 12 | extern void **getInternalBindingAddressPointer(struct internal_binding_t **in); 13 | 14 | extern gotcha_wrappee_handle_t orig_dlopen_handle; 15 | extern gotcha_wrappee_handle_t orig_dlsym_handle; 16 | 17 | extern struct gotcha_binding_t dl_binds[]; 18 | #endif 19 | -------------------------------------------------------------------------------- /src/gotcha_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "gotcha_utils.h" 17 | 18 | #include 19 | 20 | #include "elf_ops.h" 21 | #include "gotcha/gotcha.h" 22 | #include "gotcha_dl.h" 23 | #include "hash.h" 24 | #include "libc_wrappers.h" 25 | #include "tool.h" 26 | 27 | int debug_level; 28 | static void debug_init() { 29 | static int debug_initialized = 0; 30 | 31 | char *debug_str = NULL; 32 | if (debug_initialized) { 33 | return; // GCOVR_EXCL_LINE 34 | } 35 | debug_initialized = 1; 36 | 37 | debug_str = gotcha_getenv(GOTCHA_DEBUG_ENV); 38 | if (!debug_str) { 39 | return; 40 | } 41 | 42 | debug_level = gotcha_atoi(debug_str); 43 | if (debug_level <= 0) debug_level = 1; // GCOVR_EXCL_LINE 44 | 45 | debug_printf(0, "Gotcha debug initialized at level %d\n", debug_level); 46 | } 47 | 48 | hash_table_t function_hash_table; 49 | hash_table_t notfound_binding_table; 50 | 51 | static hash_table_t library_table = EMPTY_HASH_TABLE; 52 | static library_t *library_list = NULL; 53 | unsigned int current_generation = 0; 54 | 55 | static hash_hashvalue_t link_map_hash(struct link_map *map) { 56 | hash_hashvalue_t hashval = (hash_hashvalue_t)((unsigned long)map); 57 | hashval ^= strhash(LIB_NAME(map)); 58 | return hashval; 59 | } 60 | 61 | static int link_map_cmp(struct link_map *a, struct link_map *b) { 62 | return ((unsigned long)a) < ((unsigned long)b); 63 | } 64 | 65 | static void setup_hash_tables() { 66 | create_hashtable(&library_table, 128, (hash_func_t)link_map_hash, 67 | (hash_cmp_t)link_map_cmp); 68 | create_hashtable(&function_hash_table, 4096, (hash_func_t)strhash, 69 | (hash_cmp_t)gotcha_strcmp); 70 | create_hashtable(¬found_binding_table, 128, (hash_func_t)strhash, 71 | (hash_cmp_t)gotcha_strcmp); 72 | } 73 | 74 | struct library_t *get_library(struct link_map *map) { 75 | library_t *lib = NULL; 76 | int result = 0; 77 | result = 78 | lookup_hashtable(&library_table, (hash_key_t)map, (hash_data_t *)&lib); 79 | if (result == -1) return NULL; 80 | return lib; 81 | } 82 | 83 | struct library_t *add_library(struct link_map *map) { 84 | library_t *newlib = gotcha_malloc(sizeof(library_t)); 85 | newlib->map = map; 86 | newlib->flags = 0; 87 | newlib->generation = 0; 88 | newlib->next = library_list; 89 | newlib->prev = NULL; 90 | if (library_list) library_list->prev = newlib; 91 | library_list = newlib; 92 | addto_hashtable(&library_table, (hash_key_t)map, (hash_data_t)newlib); 93 | return newlib; 94 | } 95 | 96 | void remove_library(struct link_map *map) { 97 | library_t *lib = get_library(map); 98 | if (!lib) return; 99 | if (lib->prev) lib->prev->next = lib->next; 100 | if (lib->next) lib->next->prev = lib->prev; 101 | if (lib == library_list) library_list = library_list->next; 102 | removefrom_hashtable(&library_table, (hash_key_t)map); 103 | memset(lib, 0, sizeof(library_t)); 104 | gotcha_free(lib); 105 | } 106 | 107 | void gotcha_init() { 108 | static int gotcha_initialized = 0; 109 | if (gotcha_initialized) { 110 | return; 111 | } 112 | gotcha_initialized = 1; 113 | debug_init(); 114 | setup_hash_tables(); 115 | handle_libdl(); 116 | } 117 | -------------------------------------------------------------------------------- /src/gotcha_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | /*! 17 | ****************************************************************************** 18 | * 19 | * \file gotcha_utils.h 20 | * 21 | * \brief Header file containing the internal gotcha mechanisms 22 | * for manipulating the running process to redirect calls 23 | * 24 | ****************************************************************************** 25 | */ 26 | #ifndef GOTCHA_UTILS_H 27 | #define GOTCHA_UTILS_H 28 | #include 29 | 30 | #include "gotcha/gotcha_types.h" 31 | #include "hash.h" 32 | // TODO: remove these includes 33 | #include 34 | #include 35 | #include 36 | // END TODO 37 | #include 38 | #include 39 | #include 40 | 41 | #define KNOWN_UNUSED __attribute__((unused)) 42 | 43 | #define GOTCHA_DEBUG_ENV "GOTCHA_DEBUG" 44 | extern int debug_level; 45 | void gotcha_init(); 46 | extern hash_table_t function_hash_table; 47 | extern hash_table_t notfound_binding_table; 48 | #define debug_bare_printf(lvl, format, ...) \ 49 | do { \ 50 | if (debug_level >= lvl) { \ 51 | gotcha_dbg_printf(format, ##__VA_ARGS__); \ 52 | } \ 53 | } while (0); 54 | 55 | #define SHORT_FILE__ ((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1) 56 | 57 | #define debug_printf(lvl, format, ...) \ 58 | do { \ 59 | if (debug_level >= lvl) { \ 60 | gotcha_dbg_printf("[%d/%d][%s:%u] - " format, gotcha_gettid(), \ 61 | gotcha_getpid(), SHORT_FILE__, __LINE__, \ 62 | ##__VA_ARGS__); \ 63 | } \ 64 | } while (0); 65 | 66 | #define error_printf(format, ...) \ 67 | do { \ 68 | if (debug_level) { \ 69 | gotcha_dbg_printf("ERROR [%d/%d][%s:%u] - " format, gotcha_gettid(), \ 70 | gotcha_getpid(), SHORT_FILE__, __LINE__, \ 71 | ##__VA_ARGS__); \ 72 | } \ 73 | } while (0); 74 | 75 | #define LIB_NAME(X) \ 76 | (!X->l_name ? "[NULL]" : (!*X->l_name ? "[EMPTY]" : X->l_name)) 77 | 78 | /*! 79 | ****************************************************************************** 80 | * \def R_SYM(X) 81 | * \brief Returns an ELF symbol which is correct for the current architecture 82 | * \param X The value you wish to cast to Symbol type 83 | ****************************************************************************** 84 | */ 85 | #if __WORDSIZE == 64 86 | #define R_SYM(X) ELF64_R_SYM(X) 87 | #else 88 | #define R_SYM(X) ELF32_R_SYM(X) 89 | #endif 90 | 91 | /*! 92 | ****************************************************************************** 93 | * \def BOUNDARY_BEFORE(ptr,pagesize) 94 | * \brief Returns the address on page boundary before the given pointer 95 | * \param ptr The address you wish to get the page boundary before 96 | * \param pagesize The page size you wish to align to 97 | ****************************************************************************** 98 | */ 99 | #define BOUNDARY_BEFORE(ptr, pagesize) \ 100 | (ElfW(Addr))(((ElfW(Addr))ptr) & (-pagesize)) 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(HASH_H_) 17 | #define HASH_H_ 18 | 19 | #include 20 | #include 21 | 22 | typedef void *hash_key_t; 23 | typedef void *hash_data_t; 24 | typedef int hash_hashvalue_t; 25 | typedef hash_hashvalue_t (*hash_func_t)(hash_data_t data); 26 | typedef int (*hash_cmp_t)(hash_key_t a, hash_key_t b); 27 | 28 | struct hash_entry_t; 29 | 30 | typedef struct { 31 | size_t table_size; 32 | size_t entry_count; 33 | hash_func_t hashfunc; 34 | hash_cmp_t keycmp; 35 | struct hash_entry_t *table; 36 | struct hash_entry_t *head; 37 | } hash_table_t; 38 | #define EMPTY_HASH_TABLE \ 39 | {0, 0, NULL, NULL, NULL, NULL} 40 | 41 | int create_hashtable(hash_table_t *table, size_t initial_size, hash_func_t func, 42 | hash_cmp_t keycmp); 43 | int grow_hashtable(hash_table_t *table, size_t new_size); 44 | int destroy_hashtable(hash_table_t *table); 45 | 46 | int lookup_hashtable(hash_table_t *table, hash_key_t key, hash_data_t *data); 47 | int addto_hashtable(hash_table_t *table, hash_key_t key, hash_data_t data); 48 | int removefrom_hashtable(hash_table_t *table, hash_key_t key); 49 | int foreach_hash_entry(hash_table_t *table, void *opaque, 50 | int (*cb)(hash_key_t key, hash_data_t data, 51 | void *opaque)); 52 | 53 | hash_hashvalue_t strhash(const char *str); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/libc_wrappers.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(LIBC_WRAPPERS_H_) 17 | #define LIBC_WRAPPERS_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #ifndef FORCE_NO_LIBC 27 | #define GOTCHA_USE_LIBC 28 | #endif 29 | 30 | #if defined(GOTCHA_USE_LIBC) && !defined(BUILDING_LIBC_WRAPPERS) 31 | 32 | #define gotcha_malloc malloc 33 | #define gotcha_realloc realloc 34 | #define gotcha_free free 35 | #define gotcha_memcpy memcpy 36 | #define gotcha_strncmp strncmp 37 | #define gotcha_strstr strstr 38 | #define gotcha_assert assert 39 | #define gotcha_strcmp strcmp 40 | #define gotcha_getenv getenv 41 | #define gotcha_getpid getpid 42 | #define gotcha_getpagesize getpagesize 43 | #define gotcha_open open 44 | #define gotcha_mmap mmap 45 | #define gotcha_atoi atoi 46 | #define gotcha_close close 47 | #define gotcha_mprotect mprotect 48 | #define gotcha_read read 49 | #define gotcha_memset memset 50 | #define gotcha_write write 51 | #define gotcha_strlen strlen 52 | #define gotcha_strnlen strnlen 53 | #define gotcha_strtok strtok 54 | #define gotcha_strncat strncat 55 | #define gotcha_dbg_printf(A, ...) fprintf(stderr, A, ##__VA_ARGS__) 56 | pid_t gotcha_gettid(); // No libc gettid, always use gotcha version 57 | 58 | #else 59 | 60 | void *gotcha_malloc(size_t size); 61 | void *gotcha_realloc(void *buffer, size_t size); 62 | void gotcha_free(void *free_me); 63 | void gotcha_memcpy(void *dest, void *src, size_t size); 64 | int gotcha_strncmp(const char *in_one, const char *in_two, int max_length); 65 | char *gotcha_strstr(const char *searchIn, const char *searchFor); 66 | int gotcha_strcmp(const char *in_one, const char *in_two); 67 | char *gotcha_getenv(const char *env); 68 | pid_t gotcha_getpid(); 69 | pid_t gotcha_gettid(); 70 | unsigned int gotcha_getpagesize(); 71 | int gotcha_open(const char *pathname, int flags, ...); 72 | void *gotcha_mmap(void *addr, size_t length, int prot, int flags, int fd, 73 | off_t offset); 74 | int gotcha_atoi(const char *nptr); 75 | int gotcha_close(int fd); 76 | int gotcha_mprotect(void *addr, size_t len, int prot); 77 | ssize_t gotcha_read(int fd, void *buf, size_t count); 78 | ssize_t gotcha_write(int fd, const void *buf, size_t count); 79 | void gotcha_assert_fail(const char *s, const char *file, unsigned int line, 80 | const char *function); 81 | void *gotcha_memset(void *s, int c, size_t n); 82 | size_t gotcha_strlen(const char *str); 83 | size_t gotcha_strnlen(const char *str, size_t max_length); 84 | char *gotcha_strncat(char *dest, const char *src, size_t n); 85 | char *gotcha_strtok(char *dest, const char *src, size_t n); 86 | 87 | #define gotcha_dbg_printf(FORMAT, ...) \ 88 | gotcha_int_printf(2, FORMAT, ##__VA_ARGS__) 89 | 90 | #define gotcha_assert(A) \ 91 | do { \ 92 | if (!(A)) gotcha_assert_fail("" #A, __FILE__, __LINE__, __func__); \ 93 | } while (0); 94 | 95 | #endif 96 | 97 | int gotcha_int_printf(int fd, const char *format, ...); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/library_filters.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "library_filters.h" 16 | 17 | #include "gotcha/gotcha.h" 18 | #include "libc_wrappers.h" 19 | 20 | static const char *filter; 21 | int (*libraryFilterFunc)(struct link_map *) = alwaysTrue; 22 | 23 | int alwaysTrue(struct link_map *candidate KNOWN_UNUSED) { return 1; } 24 | 25 | int trueIfNameMatches(struct link_map *target) { 26 | int match = 27 | (filter) && (target) && (gotcha_strstr(target->l_name, filter) != 0); 28 | return match; 29 | } 30 | int trueIfLast(struct link_map *target) { 31 | int ret = (target->l_next) ? 0 : 1; 32 | return ret; 33 | } 34 | void gotcha_only_filter_last() { gotcha_set_library_filter_func(trueIfLast); } 35 | void gotcha_set_library_filter_func(int (*new_func)(struct link_map *)) { 36 | libraryFilterFunc = new_func; 37 | } 38 | void gotcha_restore_library_filter_func() { 39 | gotcha_set_library_filter_func(alwaysTrue); 40 | } 41 | 42 | void gotcha_filter_libraries_by_name(const char *nameFilter) { 43 | filter = nameFilter; 44 | gotcha_set_library_filter_func(trueIfNameMatches); 45 | } 46 | -------------------------------------------------------------------------------- /src/library_filters.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | // TODO: Determine whether this interface should stay on in this form 17 | 18 | #ifndef GOTCHA_LIBRARY_FILTERS_H 19 | #define GOTCHA_LIBRARY_FILTERS_H 20 | #include 21 | 22 | #include "gotcha_utils.h" 23 | 24 | int alwaysTrue(struct link_map *candidate KNOWN_UNUSED); 25 | extern int (*libraryFilterFunc)(struct link_map *); 26 | 27 | int trueIfNameMatches(struct link_map *target); 28 | int trueIfLast(struct link_map *target); 29 | #endif 30 | -------------------------------------------------------------------------------- /src/tool.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(TOOL_H_) 17 | #define TOOL_H_ 18 | 19 | #include "gotcha/gotcha.h" 20 | #include "gotcha/gotcha_types.h" 21 | #include "hash.h" 22 | 23 | struct tool_t; 24 | 25 | #define UNSET_PRIORITY (-1) 26 | 27 | enum gotcha_config_key_t { GOTCHA_PRIORITY }; 28 | 29 | /** 30 | * A structure representing how a given tool's bindings are configured 31 | */ 32 | struct gotcha_configuration_t { 33 | int priority; 34 | }; 35 | #define EMPTY_CONFIGURATION \ 36 | {0} 37 | 38 | /** 39 | * A per-library structure 40 | **/ 41 | #define LIB_GOT_MARKED_WRITEABLE (1 << 0) 42 | #define LIB_PRESENT (1 << 1) 43 | typedef struct library_t { 44 | struct link_map *map; 45 | struct library_t *next; 46 | struct library_t *prev; 47 | unsigned int generation; 48 | int flags; 49 | } library_t; 50 | struct library_t *get_library(struct link_map *map); 51 | struct library_t *add_library(struct link_map *map); 52 | void remove_library(struct link_map *map); 53 | extern unsigned int current_generation; 54 | 55 | /** 56 | * The internal structure that matches the external gotcha_binding_t. 57 | * In addition to the data specified in the gotcha_binding_t, we add: 58 | * - a linked-list pointer to the next binding table for this tool 59 | * - a linked-list pointer to the next binding table 60 | **/ 61 | typedef struct binding_t { 62 | struct tool_t *tool; 63 | struct internal_binding_t *internal_bindings; 64 | int internal_bindings_size; 65 | hash_table_t binding_hash; 66 | struct binding_t *next_tool_binding; 67 | struct binding_t *next_binding; 68 | } binding_t; 69 | 70 | /** 71 | * A structure for representing tools. Once we support stacking multiple 72 | * tools this will become more important. 73 | **/ 74 | typedef struct tool_t { 75 | const char *tool_name; 76 | binding_t *binding; 77 | struct tool_t *next_tool; 78 | struct gotcha_configuration_t config; 79 | hash_table_t child_tools; 80 | struct tool_t *parent_tool; 81 | } tool_t; 82 | 83 | struct internal_binding_t { 84 | struct binding_t *associated_binding_table; 85 | struct gotcha_binding_t *user_binding; 86 | struct internal_binding_t *next_binding; 87 | void *wrappee_pointer; 88 | }; 89 | 90 | tool_t *create_tool(const char *tool_name); 91 | tool_t *get_tool(const char *tool_name); 92 | tool_t *get_tool_list(); 93 | void reorder_tool(tool_t *new_tool); 94 | void remove_tool_from_list(struct tool_t *target); 95 | void print_tools(); 96 | 97 | binding_t *add_binding_to_tool(tool_t *tool, 98 | struct gotcha_binding_t *user_binding, 99 | int user_binding_size); 100 | binding_t *get_bindings(); 101 | binding_t *get_tool_bindings(tool_t *tool); 102 | 103 | struct gotcha_configuration_t get_default_configuration(); 104 | enum gotcha_error_t get_configuration_value(const char *tool_name, 105 | enum gotcha_config_key_t key, 106 | void *location_to_store_result); 107 | int get_priority(tool_t *tool); 108 | int tool_equal(tool_t *tool_1, tool_t *tool_2); 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/translations.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "translations.h" 16 | 17 | #include 18 | 19 | #include "gotcha_utils.h" 20 | 21 | int main_wrapped = 0; 22 | gotcha_wrappee_handle_t gotcha_internal_libc_main_wrappee_handle = NULL; 23 | gotcha_wrappee_handle_t gotcha_internal_main_wrappee_handle = NULL; 24 | /** 25 | * This function is excluded from coverage as this is only required for our 26 | * wrapper to call main. 27 | */ 28 | // GCOV_EXCL_START 29 | int gotcha_internal_main(int argc, char **argv, char **envp) { 30 | main_t underlying_main = 31 | gotcha_get_wrappee(gotcha_internal_main_wrappee_handle); 32 | return underlying_main(argc, argv, envp); 33 | } 34 | // GCOV_EXCL_STOP 35 | int gotcha_internal_libc_start_main(int (*main_arg)(int, char **, char **) 36 | KNOWN_UNUSED, 37 | int argc, char **argv, void (*init)(), 38 | void (*fini)(), void (*rtld_fini)(), 39 | void *stack_end) { 40 | libc_start_main_t underlying_libc_main = 41 | gotcha_get_wrappee(gotcha_internal_libc_main_wrappee_handle); 42 | main_t underlying_main = 43 | gotcha_get_wrappee(gotcha_internal_main_wrappee_handle); 44 | return underlying_libc_main(underlying_main, argc, argv, init, fini, 45 | rtld_fini, stack_end); 46 | } 47 | 48 | struct gotcha_binding_t libc_main_wrappers[] = { 49 | {"__libc_start_main", gotcha_internal_libc_start_main, 50 | &gotcha_internal_libc_main_wrappee_handle}}; 51 | struct gotcha_binding_t main_wrappers[] = { 52 | {"main", gotcha_internal_main, &gotcha_internal_main_wrappee_handle}}; 53 | -------------------------------------------------------------------------------- /src/translations.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | /** 16 | * This file contains utilities for cases where users say something (wrap main) 17 | * that doesn't work, but can be translated to something that does work 18 | */ 19 | #ifndef GOTCHA_SRC_TRANSLATIONS_H 20 | #define GOTCHA_SRC_TRANSLATIONS_H 21 | #include 22 | 23 | /** "int main" wrapping handling */ 24 | typedef int (*libc_start_main_t)(int (*)(int, char **, char **), int, char **, 25 | void (*)(), void (*)(), void (*)(), void *); 26 | typedef int (*main_t)(int argc, char **argv, char **envp); 27 | 28 | extern int main_wrapped; 29 | extern gotcha_wrappee_handle_t gotcha_internal_libc_main_wrappee_handle; 30 | extern gotcha_wrappee_handle_t gotcha_internal_main_wrappee_handle; 31 | 32 | int gotcha_internal_main(int argc, char **argv, char **envp); 33 | int gotcha_internal_libc_start_main(int (*)(int, char **, char **), int, 34 | char **, void (*)(), void (*)(), void (*)(), 35 | void *); 36 | 37 | extern struct gotcha_binding_t libc_main_wrappers[]; 38 | extern struct gotcha_binding_t main_wrappers[]; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(unit) 3 | add_subdirectory(dlopen) 4 | add_subdirectory(stack) 5 | add_subdirectory(priority) 6 | add_subdirectory(ppc_stress_multi_module) 7 | if (COMPILER_SUPPORTS_CXX11) 8 | add_subdirectory(hammer) 9 | endif () 10 | add_subdirectory(rogot) 11 | add_subdirectory(filter) 12 | # add_subdirectory(wrap_main) 13 | # add_subdirectory(multi_agent_dlopen) 14 | add_subdirectory(symver) 15 | add_subdirectory(function_ptr) 16 | add_subdirectory(dispatcher) 17 | -------------------------------------------------------------------------------- /test/dispatcher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(impl SHARED libimpl.c) 2 | add_library(dispatcher SHARED libdispatcher.c) 3 | target_link_libraries(dispatcher -ldl -lpthread) 4 | add_executable(test_dispatcher main.c) 5 | target_link_libraries(test_dispatcher gotcha dispatcher) 6 | gotcha_add_test(dispatcher_test test_dispatcher) 7 | set_property(TEST dispatcher_test APPEND PROPERTY ENVIRONMENT "GOTCHA_DEBUG=3") 8 | set_property(TEST dispatcher_test APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}") 9 | -------------------------------------------------------------------------------- /test/dispatcher/libdispatcher.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #define _GNU_SOURCE 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | int foo(void); 23 | int bar(void); 24 | 25 | static void* impl_lib; 26 | static int (*impl_foo)(void); 27 | static int (*impl_bar)(void); 28 | 29 | static pthread_once_t init_once = PTHREAD_ONCE_INIT; 30 | void dispatch_init(void) { 31 | fprintf(stderr, "Ed dispatch_init()\n"); 32 | 33 | impl_lib = dlopen("libimpl.so", RTLD_NOW); 34 | assert(impl_lib); 35 | impl_foo = dlsym(impl_lib, "foo"); 36 | assert(impl_foo); 37 | impl_bar = dlsym(impl_lib, "bar"); 38 | assert(impl_bar); 39 | 40 | int ret = impl_bar(); 41 | 42 | fprintf(stderr, "Ld dispatch_init() = %d\n", ret); 43 | } 44 | 45 | int foo(void) { 46 | fprintf(stderr, "Ed foo()\n"); 47 | 48 | pthread_once(&init_once, dispatch_init); 49 | 50 | int ret = impl_bar() + impl_foo(); 51 | 52 | fprintf(stderr, "Ld foo()\n"); 53 | 54 | return ret; 55 | } 56 | 57 | int bar(void) { 58 | fprintf(stderr, "Ed bar()\n"); 59 | 60 | pthread_once(&init_once, dispatch_init); 61 | 62 | int ret = impl_bar(); 63 | 64 | fprintf(stderr, "Ld bar()\n"); 65 | 66 | return ret; 67 | } 68 | -------------------------------------------------------------------------------- /test/dispatcher/libimpl.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #define _GNU_SOURCE 17 | #include 18 | 19 | int foo(void) { 20 | fprintf(stderr, "Ei foo()\n"); 21 | fprintf(stderr, "Li foo()\n"); 22 | 23 | return 42; 24 | } 25 | 26 | int bar(void) { 27 | fprintf(stderr, "Ei bar()\n"); 28 | fprintf(stderr, "Li bar()\n"); 29 | 30 | return 23; 31 | } 32 | -------------------------------------------------------------------------------- /test/dispatcher/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #define _GNU_SOURCE 17 | #include 18 | #include 19 | 20 | int foo(void); 21 | int bar(void); 22 | 23 | static gotcha_wrappee_handle_t handle_foo; 24 | static gotcha_wrappee_handle_t handle_bar; 25 | 26 | static int do_foo(void) { 27 | fprintf(stderr, "Ew foo()\n"); 28 | 29 | typeof(&do_foo) orig_foo = gotcha_get_wrappee(handle_foo); 30 | int ret = orig_foo(); 31 | 32 | fprintf(stderr, "Lw foo() = %d\n", ret); 33 | 34 | return ret; 35 | } 36 | 37 | static int do_bar(void) { 38 | fprintf(stderr, "Ew bar()\n"); 39 | 40 | typeof(&do_bar) orig_bar = gotcha_get_wrappee(handle_bar); 41 | int ret = orig_bar(); 42 | 43 | fprintf(stderr, "Lw bar() = %d\n", ret); 44 | 45 | return ret; 46 | } 47 | 48 | static struct gotcha_binding_t bindings[] = { 49 | {"foo", do_foo, &handle_foo}, 50 | {"bar", do_bar, &handle_bar}, 51 | }; 52 | 53 | int main(int ac, char *av[]) { 54 | gotcha_wrap(bindings, 2, "test"); 55 | printf("%d\n", foo()); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /test/dlopen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(num SHARED num.c) 2 | add_library(num2 SHARED num2.c) 3 | add_executable(test_dlopen test_dlopen.c) 4 | set_target_properties(test_dlopen 5 | PROPERTIES COMPILE_FLAGS "-DLIB_NAME_RAW=\"\"${CMAKE_CURRENT_BINARY_DIR}/libnum.so\"\" -DLIB2_NAME_RAW=\"\"${CMAKE_CURRENT_BINARY_DIR}/libnum2.so\"\"" 6 | ) 7 | target_link_libraries(test_dlopen gotcha dl) 8 | add_dependencies(test_dlopen num num2) 9 | gotcha_add_test(dlopen_test test_dlopen) 10 | environment_add(dlopen_test TEST "GOTCHA_DEBUG=3 LIBNUM_DIR=${CMAKE_CURRENT_BINARY_DIR}") 11 | set_tests_properties(dlopen_test PROPERTIES 12 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 13 | ) 14 | -------------------------------------------------------------------------------- /test/dlopen/num.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | int return_five() { return 4; } 17 | 18 | int return_four() { 19 | /* Intentional bug, gotcha wrapping will correct this to return 4 */ 20 | return 3; 21 | } 22 | 23 | int test_return_five() { return return_five(); } 24 | -------------------------------------------------------------------------------- /test/dlopen/num2.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | int return_four() { return 6; } 17 | 18 | int return_six() { 19 | /* Intentional bug, gotcha wrapping will correct this to return 6 */ 20 | return 7; 21 | } 22 | -------------------------------------------------------------------------------- /test/dlopen/test_dlopen.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #define _GNU_SOURCE 17 | #include 18 | #include 19 | 20 | #include "gotcha/gotcha.h" 21 | 22 | #define Q(x) #x 23 | #define QUOTE(x) Q(x) 24 | 25 | #ifndef LIB_NAME_RAW 26 | #define LIB_NAME_RAW libnum.so 27 | #endif 28 | #ifndef LIB2_NAME_RAW 29 | #define LIB2_NAME_RAW libnum2.so 30 | #endif 31 | 32 | #define LIB_NAME QUOTE(LIB_NAME_RAW) 33 | #define LIB2_NAME QUOTE(LIB2_NAME_RAW) 34 | int correct_return_four() { return 4; } 35 | int correct_return_five() { return 5; } 36 | int correct_return_six() { return 6; } 37 | 38 | int return_five() { 39 | /* Intentional bug, gotcha will correct this to return 5*/ 40 | return 3; 41 | } 42 | 43 | static gotcha_wrappee_handle_t buggy_return_four; 44 | static gotcha_wrappee_handle_t buggy_return_five; 45 | static gotcha_wrappee_handle_t buggy_return_six; 46 | 47 | struct gotcha_binding_t funcs[] = { 48 | {"return_four", correct_return_four, &buggy_return_four}, 49 | {"return_five", correct_return_five, &buggy_return_five}, 50 | {"return_six", correct_return_six, &buggy_return_six}}; 51 | 52 | int main() { 53 | void *libnum; 54 | void *libnum2; 55 | int (*retfour)(void); 56 | int (*retsix)(void); 57 | int (*test_retfive)(void); 58 | int (*retdummy)(void); 59 | int had_error = 0; 60 | int result; 61 | /* We wrap the functions before they are loaded */ 62 | result = gotcha_wrap(funcs, 3, "dlopen_test"); 63 | if (result != GOTCHA_FUNCTION_NOT_FOUND) { 64 | fprintf(stderr, 65 | "GOTCHA should have failed to find a function, but found it\n"); 66 | return -1; 67 | } 68 | /* Load the first libnum.so */ 69 | libnum = dlopen(LIB_NAME, RTLD_NOW); 70 | if (!libnum) { 71 | fprintf(stderr, "ERROR: Test failed to dlopen libnum.so with %s\n", 72 | dlerror()); 73 | return -1; 74 | } 75 | 76 | /* Check if return_four is wrapped from libnum.so */ 77 | retfour = (int (*)(void))dlsym(libnum, "return_four"); 78 | if (retfour == NULL || retfour() != 4) { 79 | fprintf(stderr, 80 | "ERROR: dlsym returned original function, not wrapped from " 81 | "libnum.so\n"); 82 | had_error = -1; 83 | } 84 | 85 | /* Test 2: Does a call in a dlopen'd library get rerouted by gotcha */ 86 | test_retfive = (int (*)(void))dlsym(libnum, "test_return_five"); 87 | if (test_retfive() != 5) { 88 | fprintf(stderr, 89 | "ERROR1: call to return_five in libnum.so was not wrapped " 90 | "by correct_return_five\n"); 91 | had_error = -1; 92 | } 93 | 94 | /* Load libnum2.so */ 95 | libnum2 = dlopen(LIB2_NAME, RTLD_NOW); 96 | if (!libnum) { 97 | fprintf(stderr, "ERROR: Test failed to dlopen libnum2.so\n"); 98 | return -1; 99 | } 100 | 101 | /* Check if return_six is wrapped from libnum2.so */ 102 | retsix = (int (*)(void))dlsym(libnum2, "return_six"); 103 | if (retsix == NULL || retsix() != 6) { 104 | fprintf(stderr, 105 | "ERROR: dlsym returned original function, not wrapped from " 106 | "libnum2.so\n"); 107 | had_error = -1; 108 | } 109 | 110 | /* Check RTLD_DEFAULT */ 111 | /* Does the dlsym implementation find the first occurrence of the 112 | * symbol */ 113 | retfour = (int (*)(void))dlsym(RTLD_DEFAULT, "return_four"); 114 | if (retfour == NULL || retfour() != 4) { 115 | fprintf(stderr, 116 | "ERROR: call to return_four should be found in " 117 | "RTLD_DEFAULT from libnum.so and return 4\n"); 118 | had_error = -1; 119 | } 120 | test_retfive = (int (*)(void))dlsym(RTLD_DEFAULT, "test_return_five"); 121 | if (test_retfive != NULL) { 122 | fprintf(stderr, 123 | "ERROR2: call to return_five in libnum.so was not wrapped " 124 | "by correct_return_five\n"); 125 | had_error = -1; 126 | } 127 | 128 | retsix = (int (*)(void))dlsym(RTLD_DEFAULT, "return_six"); 129 | if (retsix == NULL || retsix() != 6) { 130 | fprintf(stderr, 131 | "ERROR3: call to return_five in libnum2.so was not wrapped " 132 | "by correct_return_five\n"); 133 | had_error = -1; 134 | } 135 | 136 | retdummy = (int (*)(void))dlsym(RTLD_DEFAULT, "return_dummy"); 137 | if (retdummy != NULL) { 138 | fprintf( 139 | stderr, 140 | "ERROR: call to return_dummy should not be found in RTLD_DEFAULT\n"); 141 | had_error = -1; 142 | } 143 | 144 | /* Test RTLD_NEXT */ 145 | /* Does the dlsym implementation find the second occurrence of the 146 | * symbol */ 147 | test_retfive = (int (*)(void))dlsym(RTLD_NEXT, "test_return_five"); 148 | if (test_retfive == NULL) { 149 | fprintf(stderr, 150 | "ERROR: call to test_return_five should not be found in " 151 | "RTLD_NEXT from libnum2.so\n"); 152 | had_error = -1; 153 | } 154 | retdummy = (int (*)(void))dlsym(RTLD_NEXT, "return_dummy"); 155 | if (retdummy != NULL) { 156 | fprintf(stderr, 157 | "ERROR: call to return_dummy should not be found in RTLD_NEXT\n"); 158 | had_error = -1; 159 | } 160 | return had_error; 161 | } 162 | -------------------------------------------------------------------------------- /test/filter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(num3 SHARED num.c num.h) 2 | add_executable(test_filter test_filter.c) 3 | target_link_libraries(test_filter gotcha dl num3) 4 | add_dependencies(test_filter num) 5 | gotcha_add_test(filter_test test_filter) 6 | environment_add(filter_test TEST "GOTCHA_DEBUG=3") 7 | -------------------------------------------------------------------------------- /test/filter/num.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | int return_four() { return 4; } 16 | 17 | int return_five() { return 5; } 18 | int return_six() { return 6; } 19 | -------------------------------------------------------------------------------- /test/filter/num.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by haridev on 7/12/23. 3 | // 4 | 5 | #ifndef GOTCHA_NUM_H 6 | #define GOTCHA_NUM_H 7 | extern int return_four(); 8 | extern int return_five(); 9 | extern int return_six(); 10 | #endif // GOTCHA_NUM_H 11 | -------------------------------------------------------------------------------- /test/filter/test_filter.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #define _GNU_SOURCE 17 | #include 18 | #include 19 | 20 | #include "gotcha/gotcha.h" 21 | #include "num.h" 22 | 23 | int wrong_return_four() { return 5; } 24 | int wrong_return_five() { return 4; } 25 | int wrong_return_six() { return 3; } 26 | static gotcha_wrappee_handle_t buggy_return_four; 27 | static gotcha_wrappee_handle_t buggy_return_five; 28 | static gotcha_wrappee_handle_t buggy_return_six; 29 | struct gotcha_binding_t func_four[] = { 30 | {"return_four", wrong_return_four, &buggy_return_four}}; 31 | struct gotcha_binding_t func_five[] = { 32 | {"return_five", wrong_return_five, &buggy_return_five}}; 33 | struct gotcha_binding_t func_six[] = { 34 | {"return_six", wrong_return_six, &buggy_return_six}}; 35 | 36 | int main() { 37 | int result; 38 | int had_error = 0; 39 | result = gotcha_wrap(func_four, 1, "test_filter_four"); 40 | if (result == GOTCHA_FUNCTION_NOT_FOUND) { 41 | fprintf(stderr, "GOTCHA should find a function, but found it\n"); 42 | return -1; 43 | } 44 | result = return_four(); 45 | if (result != 5) { 46 | fprintf(stderr, "ERROR: wrapper function should return 5\n"); 47 | had_error = -1; 48 | } 49 | gotcha_filter_libraries_by_name("libnum3.so"); 50 | result = gotcha_wrap(func_five, 1, "test_filter_five"); 51 | if (result == GOTCHA_FUNCTION_NOT_FOUND) { 52 | fprintf(stderr, "GOTCHA should find a function, but found it\n"); 53 | return -1; 54 | } 55 | result = return_five(); 56 | if (result != 5) { 57 | fprintf(stderr, 58 | "ERROR: library function should return 5. no wrapping for exec\n"); 59 | had_error = -1; 60 | } 61 | gotcha_only_filter_last(); 62 | result = gotcha_wrap(func_six, 1, "test_filter_six"); 63 | if (result == GOTCHA_FUNCTION_NOT_FOUND) { 64 | fprintf(stderr, "GOTCHA should find a function, but found it\n"); 65 | return -1; 66 | } 67 | result = return_six(); 68 | if (result != 6) { 69 | fprintf(stderr, 70 | "ERROR: library function should return 6 no wrapping for exec\n"); 71 | had_error = -1; 72 | } 73 | gotcha_restore_library_filter_func(); 74 | gotcha_wrap(func_six, 1, NULL); 75 | return had_error; 76 | } 77 | -------------------------------------------------------------------------------- /test/function_ptr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(fnnum SHARED num.c) 2 | add_executable(test_fp test_function_ptr.c) 3 | target_link_libraries(test_fp gotcha fnnum) 4 | gotcha_add_test(fp_test test_fp) 5 | environment_add(fp_test TEST "GOTCHA_DEBUG=3") -------------------------------------------------------------------------------- /test/function_ptr/num.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "num.h" 16 | int return_four() { return 3; } 17 | -------------------------------------------------------------------------------- /test/function_ptr/num.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by haridev on 7/27/23. 3 | // 4 | 5 | #ifndef GOTCHA_NUM_H 6 | #define GOTCHA_NUM_H 7 | int return_four(); 8 | #endif // GOTCHA_NUM_H 9 | -------------------------------------------------------------------------------- /test/function_ptr/test_function_ptr.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by haridev on 7/27/23. 3 | // 4 | #include 5 | #include 6 | 7 | #include "num.h" 8 | int correct_return_four() { return 4; } 9 | 10 | static gotcha_wrappee_handle_t buggy_return_four; 11 | struct gotcha_binding_t funcs[] = { 12 | {"return_four", correct_return_four, &buggy_return_four}}; 13 | int main() { 14 | int (*fp)(void) = &return_four; 15 | int result = fp(); 16 | if (result != 3) { 17 | fprintf(stderr, "the libnum.so would return 3\n"); 18 | return -1; 19 | } 20 | result = gotcha_wrap(funcs, 1, "dlopen_test"); 21 | if (result == GOTCHA_FUNCTION_NOT_FOUND) { 22 | fprintf(stderr, "GOTCHA should have found a function, but found it\n"); 23 | return -1; 24 | } 25 | int (*fp2)(void) = &return_four; 26 | result = fp2(); 27 | if (result != 4) { 28 | fprintf(stderr, "wrapper should return 4\n"); 29 | return -1; 30 | } 31 | return 0; 32 | } -------------------------------------------------------------------------------- /test/hammer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #The test size is based around (XSIZE * YSIZE) change these variables to make 2 | # the test smaller/larger. 3 | # 4 | #Keep this test small for day-to-day builds. But occasionally, before release 5 | #or when performance testing, it's worth bumping this up to something big 6 | #e.g, 64x64. Note that this will take hours to build (but parallelizes well) 7 | #and about a dozen gigs of disk space. 8 | # 9 | #Don't enable debug information at (64 * 64), do that at something like (4 * 4). 10 | #Also, enabling optimizations in gcc currently breaks the test by eliminating 11 | #needed symbols. Don't do it. 12 | 13 | set(XSIZE 1) 14 | set(YSIZE 1) 15 | 16 | set(CMAKE_BUILD_TYPE Debug) 17 | SET(CMAKE_CXX_FLAGS_DEBUG " ${CMAKE_CXX_FLAGS_DEBUG} -Wall -Werror -Wextra") 18 | 19 | add_definitions(-DXSIZE=${XSIZE}) 20 | add_definitions(-DYSIZE=${YSIZE}) 21 | add_definitions(--std=c++11) 22 | include_directories(${CMAKE_BINARY_DIR}/test/hammer) 23 | 24 | add_library(math SHARED gen.cc) 25 | 26 | add_library(wrap SHARED wrap.cc) 27 | target_link_libraries(wrap gotcha dl) 28 | 29 | add_custom_target(externals.h 30 | COMMAND ${CMAKE_SOURCE_DIR}/test/hammer/gen_externals_h.sh ${YSIZE} ${XSIZE}) 31 | 32 | add_executable(hammer hammer.cc) 33 | target_link_libraries(hammer math wrap) 34 | 35 | foreach (y RANGE ${YSIZE}) 36 | foreach (x RANGE ${XSIZE}) 37 | add_library(ref${y}_${x} SHARED multref.cc addref.cc) 38 | target_compile_definitions(ref${y}_${x} PRIVATE -DSTARTY=${y} PRIVATE -DSTARTX=${x}) 39 | add_dependencies(ref${y}_${x} externals.h) 40 | target_link_libraries(ref${y}_${x} wrap) 41 | target_link_libraries(hammer ref${y}_${x}) 42 | endforeach (x) 43 | endforeach (y) 44 | 45 | gotcha_add_test(hammer_time_test hammer) 46 | environment_add(hammer_time_test TEST "GOTCHA_DEBUG=3") 47 | set(preload_libs "") 48 | foreach (y RANGE ${YSIZE}) 49 | foreach (x RANGE ${XSIZE}) 50 | string(CONCAT preload_libs ${preload_libs} ":${CMAKE_CURRENT_BINARY_DIR}/libref${y}_${x}.so") 51 | endforeach (x) 52 | endforeach (y) 53 | environment_add(hammer_time_test TEST "LD_PRELOAD=${preload_libs}") -------------------------------------------------------------------------------- /test/hammer/addref.cc: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(_GNU_SOURCE) 17 | #define _GNU_SOURCE 18 | #endif 19 | 20 | #include "math.hpp" 21 | #include "externals.h" 22 | 23 | template 24 | class AddChecker { 25 | public: 26 | static bool doCheck(bool is_neg) { 27 | (void)AddChecker::doCheck; 28 | (void)AddChecker::doCheck; 29 | 30 | if (!AddChecker::doCheck(is_neg)) return false; 31 | 32 | result_t add = Add::math(); 33 | result_t target = (A + B) * (is_neg ? -1 : 1); 34 | return (add == target); 35 | } 36 | }; 37 | 38 | template 39 | class AddChecker { 40 | public: 41 | static bool doCheck(bool is_neg) { 42 | if (!AddChecker::doCheck(is_neg)) return false; 43 | 44 | result_t add = Add::math(); 45 | result_t target = A * (is_neg ? -1 : 1); 46 | return (add == target); 47 | } 48 | }; 49 | 50 | template <> 51 | class AddChecker<0, 0> { 52 | public: 53 | static bool doCheck(bool) { 54 | result_t add = Add<0, 0>::math(); 55 | return (add == 0); 56 | } 57 | }; 58 | 59 | static bool check(bool is_neg) { 60 | return AddChecker::doCheck(is_neg); 61 | } 62 | 63 | static void onLoad() __attribute__((constructor)); 64 | static void onLoad() { addinfo.checkFunctions.insert(check); } 65 | -------------------------------------------------------------------------------- /test/hammer/gen.cc: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(_GNU_SOURCE) 17 | #define _GNU_SOURCE 18 | #endif 19 | 20 | #include "math.hpp" 21 | 22 | using namespace std; 23 | 24 | template 25 | class Generate { 26 | public: 27 | static void init() { 28 | Mult::init(); 29 | Add::init(); 30 | Neg::init(); 31 | 32 | // Extra gens here prevents recursive template overflow 33 | (void)Generate::init; 34 | (void)Generate::init; 35 | 36 | Generate::init(); 37 | } 38 | }; 39 | 40 | template 41 | class Generate { 42 | public: 43 | static void init() { 44 | Mult::init(); 45 | Add::init(); 46 | Neg::init(); 47 | 48 | Generate::init(); 49 | } 50 | }; 51 | 52 | template <> 53 | class Generate<0, 0> { 54 | public: 55 | static void init() { 56 | Mult<0, 0>::init(); 57 | Add<0, 0>::init(); 58 | Neg<0, 0>::init(); 59 | } 60 | }; 61 | 62 | template 63 | gotcha_wrappee_handle_t *Neg::mathfn_mult_handle = NULL; 64 | 65 | template 66 | gotcha_wrappee_handle_t *Neg::mathfn_add_handle = NULL; 67 | 68 | void initMath() { Generate::init(); } 69 | -------------------------------------------------------------------------------- /test/hammer/gen_externals_h.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -f externals.h.tmp 3 | for y in $(seq 0 $1); do for x in $(seq 0 $2); do echo extern template class Mult\<${y}, ${x}\>\;; done; done > externals.h.tmp 4 | for y in $(seq 0 $1); do for x in $(seq 0 $2); do echo extern template class Add\<${y}, ${x}\>\;; done; done >> externals.h.tmp 5 | if ! [ -f externals.h ] || ! diff -q externals.h externals.h.tmp; then mv -f externals.h.tmp externals.h; fi 6 | rm -f externals.h.tmp 7 | 8 | -------------------------------------------------------------------------------- /test/hammer/hammer.cc: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | /** 17 | * This test is meant to hammer gotcha_wrap with an excessively large workload. 18 | * It should be linked with: 19 | * -- one libmath.so that contains: 20 | * - (X+1)*(Y+1) template instantiations for each Add, Mult 21 | * class, which does the appropriately named math() operation on its 22 | * template arguments. (e.g, Mult<5, 4>::math() == 20) 23 | * - (X+1)*(Y+1) template instantiations of Neg, which we will wrap 24 | * around the Add and Mult calls. Each Neg instance contains a 25 | * pair of function pointers that will be pointed at Add::math() 26 | * and Mult::math, and functions that call those Add/Mult function 27 | * pointer and negate the result. 28 | * -- (X+1)*(Y+1) librefY_X.so libraries. Each libref$y_$x.so contains: 29 | * - (X+1)*(Y+1) calls to Add::math(), and functions that validate 30 | * whether that call returned the positive or negative result of its 31 | * operation (which tells whether it was wrapped or not). 32 | * - $x calls to Mult::math(), along with similar validation calls 33 | * that are used in the Add case. 34 | * -- one libwrap.so, which contains bookkeeping datastructures to collect 35 | * function pointers and references to all the various Add/Mult data 36 | *structures, and gotcha calls to trigger wrapping. 37 | * 38 | * In summary, there are a bunch of calls across many libraries to Add::math() and Mult::math() that do a simple math operation. After 40 | *gotcha wrapping, they will start to return -1 * their result. 41 | **/ 42 | 43 | #if !defined(_GNU_SOURCE) 44 | #define _GNU_SOURCE 45 | #endif 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | 56 | #include "gotcha/gotcha.h" 57 | #include "math.hpp" 58 | #include "wrap.h" 59 | 60 | using namespace std; 61 | 62 | int main() { 63 | initMath(); 64 | bool had_error = false; 65 | 66 | if (!multinfo.validate(false)) { 67 | cerr << "ERROR: mult sanity check failed" << endl; 68 | had_error = true; 69 | } 70 | if (!addinfo.validate(false)) { 71 | cerr << "ERROR: add sanity check failed" << endl; 72 | had_error = true; 73 | } 74 | 75 | multinfo.dowrap("Multiplies"); 76 | 77 | if (!multinfo.validate(true)) { 78 | cerr << "ERROR: mult was not wrapped" << endl; 79 | had_error = true; 80 | } 81 | if (!addinfo.validate(false)) { 82 | cerr << "ERROR: add was modified by mult" << endl; 83 | had_error = true; 84 | } 85 | 86 | addinfo.dowrap("Additions"); 87 | 88 | if (!multinfo.validate(true)) { 89 | cerr << "ERROR: mult was modified by add" << endl; 90 | had_error = true; 91 | } 92 | if (!addinfo.validate(true)) { 93 | cerr << "ERROR: add was not wrapped" << endl; 94 | had_error = true; 95 | } 96 | 97 | if (had_error) 98 | cout << "Failed hammering:" << endl; 99 | else 100 | cout << "Successfully hammered:" << endl; 101 | cout << "\t" << multinfo.checkFunctions.size() << "/" 102 | << addinfo.checkFunctions.size() << " mult/add libraries" << endl 103 | << "\twrapped " << multinfo.mathFunctionNames.size() 104 | << " mult functions and " << addinfo.mathFunctionNames.size() 105 | << " add functions" << endl 106 | << "\twith " << (X + 1) * (X + 2) * (Y + 1) / 2 107 | << " mult functions references" << endl 108 | << "\twith " << (X + 1) * (Y + 1) * addinfo.checkFunctions.size() 109 | << " add functions references" << endl; 110 | return had_error ? -1 : 0; 111 | } 112 | -------------------------------------------------------------------------------- /test/hammer/math.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(MULT_HPP_) 17 | #define MULT_HPP_ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "wrap.h" 27 | 28 | #define X XSIZE 29 | #define Y YSIZE 30 | 31 | typedef signed long result_t; 32 | 33 | template 34 | class Mult { 35 | public: 36 | static void init() { multinfo.addName(A, B, (void *)Mult::math); } 37 | 38 | static result_t math() { return A * B; } 39 | }; 40 | 41 | template 42 | class Add { 43 | public: 44 | static void init() { addinfo.addName(A, B, (void *)Add::math); } 45 | 46 | static result_t math() { return A + B; } 47 | }; 48 | 49 | template 50 | class Neg { 51 | public: 52 | static gotcha_wrappee_handle_t *mathfn_add_handle; 53 | static gotcha_wrappee_handle_t *mathfn_mult_handle; 54 | static void init() { 55 | multinfo.addNegPtr(A, B, (void **)Neg::mult_math_wrapper, 56 | (void **)&mathfn_mult_handle); 57 | addinfo.addNegPtr(A, B, (void **)Neg::add_math_wrapper, 58 | (void **)&mathfn_add_handle); 59 | } 60 | 61 | static result_t mult_math_wrapper() { 62 | auto mathfn_mult = reinterpret_cast( 63 | gotcha_get_wrappee(mathfn_mult_handle)); 64 | return mathfn_mult() * -1; 65 | } 66 | 67 | static result_t add_math_wrapper() { 68 | auto mathfn_add = reinterpret_cast( 69 | gotcha_get_wrappee(mathfn_add_handle)); 70 | return mathfn_add() * -1; 71 | } 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /test/hammer/multref.cc: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(_GNU_SOURCE) 17 | #define _GNU_SOURCE 18 | #endif 19 | 20 | #include "math.hpp" 21 | #include "externals.h" 22 | 23 | #include 24 | 25 | #if !defined(STARTX) || !defined(STARTY) 26 | #error Build ref.cc with STARTX and STARTY defined 27 | #endif 28 | 29 | using namespace std; 30 | 31 | template 32 | class MultChecker { 33 | public: 34 | static bool doCheck(bool is_neg) { 35 | if (!MultChecker::doCheck(is_neg)) return false; 36 | 37 | result_t mult = Mult::math(); 38 | result_t target = A * B * (is_neg ? -1 : 1); 39 | return (mult == target); 40 | } 41 | }; 42 | 43 | template 44 | class MultChecker { 45 | public: 46 | static int doCheck(bool is_neg __attribute__((unused))) { 47 | return Mult::math() == 0; 48 | } 49 | }; 50 | 51 | static bool check(bool is_neg) { 52 | return MultChecker::doCheck(is_neg); 53 | } 54 | 55 | static void onLoad() __attribute__((constructor)); 56 | static void onLoad() { multinfo.checkFunctions.insert(check); } 57 | -------------------------------------------------------------------------------- /test/hammer/wrap.cc: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(_GNU_SOURCE) 17 | #define _GNU_SOURCE 18 | #endif 19 | 20 | #include "wrap.h" 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "gotcha/gotcha.h" 31 | 32 | using namespace std; 33 | 34 | WrapperInfo multinfo; 35 | WrapperInfo addinfo; 36 | 37 | void WrapperInfo::addName(int a, int b, void *func) { 38 | Dl_info info; 39 | if (mathFunctionNames.find(make_pair(a, b)) != mathFunctionNames.end()) 40 | return; 41 | 42 | int result = dladdr(func, &info); 43 | if (result && info.dli_sname) { 44 | mathFunctionNames[make_pair(a, b)] = string(info.dli_sname); 45 | } 46 | } 47 | 48 | void WrapperInfo::addNegPtr(int a, int b, void **negfunc, void **multfptr) { 49 | negFunctionPtrs[make_pair(a, b)] = make_pair(negfunc, multfptr); 50 | } 51 | 52 | bool WrapperInfo::validate(bool is_neg) { 53 | for (auto i = checkFunctions.begin(); i != checkFunctions.end(); i++) 54 | if (!(*i)(is_neg)) return false; 55 | return true; 56 | } 57 | 58 | bool WrapperInfo::dowrap(std::string toolname) { 59 | int j = 0; 60 | 61 | size_t size = mathFunctionNames.size(); 62 | gotcha_binding_t *bindings = new gotcha_binding_t[size]; 63 | 64 | for (auto i = mathFunctionNames.begin(); i != mathFunctionNames.end(); 65 | i++, j++) { 66 | auto neg = negFunctionPtrs.find(make_pair(i->first.first, i->first.second)); 67 | 68 | bindings[j].name = i->second.c_str(); 69 | bindings[j].wrapper_pointer = neg->second.first; 70 | bindings[j].function_handle = neg->second.second; 71 | } 72 | 73 | auto start = chrono::steady_clock::now(); 74 | gotcha_error_t result = 75 | gotcha_wrap(bindings, size, const_cast(toolname.c_str())); 76 | if (result != GOTCHA_SUCCESS) { 77 | cerr << "gotcha_wrap did not return success" << endl; 78 | return false; 79 | } 80 | auto end = chrono::steady_clock::now(); 81 | cout << "gotcha_wrap took " 82 | << chrono::duration(end - start).count() / 1000.0 83 | << " seconds for " << toolname << endl; 84 | 85 | return true; 86 | } 87 | -------------------------------------------------------------------------------- /test/hammer/wrap.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #if !defined(_WRAP_H_) 17 | #define _WRAP_H_ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | extern void initMath(); 27 | class WrapperInfo { 28 | public: 29 | std::map, std::string> mathFunctionNames; 30 | std::map, std::pair> 31 | negFunctionPtrs; 32 | std::set checkFunctions; 33 | void addName(int a, int b, void *func); 34 | void addNegPtr(int a, int b, void **negfunc, void **mathfptr); 35 | bool validate(bool is_neg); 36 | bool dowrap(std::string toolname); 37 | }; 38 | 39 | extern WrapperInfo multinfo; 40 | extern WrapperInfo addinfo; 41 | 42 | void initMath(); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /test/ppc_stress_multi_module/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(cross_tool1 SHARED tool1.c) 2 | add_library(cross_tool2 SHARED tool2.c) 3 | add_executable(cross_app app.c) 4 | target_link_libraries(cross_app gotcha) 5 | target_link_libraries(cross_tool1 gotcha) 6 | target_link_libraries(cross_tool2 gotcha) 7 | set_target_properties(cross_tool1 PROPERTIES COMPILE_FLAGS "-fPIC") 8 | set_target_properties(cross_tool2 PROPERTIES COMPILE_FLAGS "-fPIC") 9 | target_link_libraries(cross_app cross_tool1 cross_tool2) 10 | add_test(test_cross cross_app) 11 | 12 | -------------------------------------------------------------------------------- /test/ppc_stress_multi_module/app.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "tool1.h" 20 | #include "tool2.h" 21 | 22 | extern int init_autotee(char *filename); 23 | extern int close_autotee(); 24 | 25 | #define OUTPUT_FILE "tee.out" 26 | 27 | int main() { 28 | int result; 29 | 30 | result = init_tool1(); 31 | if (result != 0) return -1; 32 | 33 | result = retX(10); 34 | printf("Result %d\n", result); 35 | return (result == 25) ? 0 : 1; 36 | } 37 | -------------------------------------------------------------------------------- /test/ppc_stress_multi_module/tool1.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool1.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | static int storage1test = 10; 27 | int storage2test = 5; 28 | 29 | static int retX_wrapper(int x); 30 | 31 | static gotcha_wrappee_handle_t origRetX_handle = 0x0; 32 | 33 | #define NUM_IOFUNCS 1 34 | struct gotcha_binding_t iofuncs[] = {{"retX", retX_wrapper, &origRetX_handle}}; 35 | 36 | int retX_wrapper(int x) { 37 | typeof(&retX_wrapper) origRetX = gotcha_get_wrappee(origRetX_handle); 38 | printf("In tool1 wrapper, calling %p\n", origRetX); 39 | return origRetX ? (origRetX(x) + storage1test + storage2test) : 0; 40 | } 41 | 42 | int init_tool1() { 43 | enum gotcha_error_t result; 44 | 45 | result = gotcha_wrap(iofuncs, NUM_IOFUNCS, "tool1"); 46 | if (result != GOTCHA_SUCCESS) { 47 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 48 | return -1; 49 | } 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /test/ppc_stress_multi_module/tool1.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL1_H 16 | #define GOTCHA_TOOL1_H 17 | int init_tool1(); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /test/ppc_stress_multi_module/tool2.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool2.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | int retX(int x) { return x; } 27 | -------------------------------------------------------------------------------- /test/ppc_stress_multi_module/tool2.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL2_H 16 | #define GOTCHA_TOOL2_H 17 | int retX(int x); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/priority/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(priority_lib1 SHARED lib1.c) 2 | add_library(priority_tool1 SHARED tool1.c) 3 | add_library(priority_tool2 SHARED tool2.c) 4 | add_library(priority_tool3 SHARED tool3.c) 5 | add_executable(priority_app app.c) 6 | target_link_libraries(priority_app gotcha) 7 | target_link_libraries(priority_tool1 gotcha) 8 | target_link_libraries(priority_tool2 gotcha) 9 | target_link_libraries(priority_tool3 gotcha) 10 | target_link_libraries(priority_app priority_lib1 priority_tool1 priority_tool2 priority_tool3) 11 | add_test(test_priority_123 priority_app) 12 | set_property(TEST test_priority_123 13 | PROPERTY 14 | ENVIRONMENT "tool_one_priority=1" 15 | ) 16 | set_property(TEST test_priority_123 17 | APPEND 18 | PROPERTY 19 | ENVIRONMENT "tool_two_priority=2" 20 | ) 21 | set_property(TEST test_priority_123 22 | APPEND 23 | PROPERTY 24 | ENVIRONMENT "tool_three_priority=3" 25 | ) 26 | add_test(test_priority_132 priority_app) 27 | set_property(TEST test_priority_132 28 | PROPERTY 29 | ENVIRONMENT "tool_one_priority=1" 30 | ) 31 | set_property(TEST test_priority_132 32 | APPEND 33 | PROPERTY 34 | ENVIRONMENT "tool_two_priority=3" 35 | ) 36 | set_property(TEST test_priority_132 37 | APPEND 38 | PROPERTY 39 | ENVIRONMENT "tool_three_priority=2" 40 | ) 41 | add_test(test_priority_213 priority_app) 42 | set_property(TEST test_priority_213 43 | PROPERTY 44 | ENVIRONMENT "tool_one_priority=2" 45 | ) 46 | set_property(TEST test_priority_213 47 | APPEND 48 | PROPERTY 49 | ENVIRONMENT "tool_two_priority=1" 50 | ) 51 | set_property(TEST test_priority_213 52 | APPEND 53 | PROPERTY 54 | ENVIRONMENT "tool_three_priority=3" 55 | ) 56 | add_test(test_priority_231 priority_app) 57 | set_property(TEST test_priority_231 58 | PROPERTY 59 | ENVIRONMENT "tool_one_priority=2" 60 | ) 61 | set_property(TEST test_priority_231 62 | APPEND 63 | PROPERTY 64 | ENVIRONMENT "tool_two_priority=3" 65 | ) 66 | set_property(TEST test_priority_231 67 | APPEND 68 | PROPERTY 69 | ENVIRONMENT "tool_three_priority=1" 70 | ) 71 | add_test(test_priority_312 priority_app) 72 | set_property(TEST test_priority_312 73 | PROPERTY 74 | ENVIRONMENT "tool_one_priority=3" 75 | ) 76 | set_property(TEST test_priority_312 77 | APPEND 78 | PROPERTY 79 | ENVIRONMENT "tool_two_priority=1" 80 | ) 81 | set_property(TEST test_priority_312 82 | APPEND 83 | PROPERTY 84 | ENVIRONMENT "tool_three_priority=2" 85 | ) 86 | add_test(test_priority_321 priority_app) 87 | set_property(TEST test_priority_321 88 | PROPERTY 89 | ENVIRONMENT "tool_one_priority=3" 90 | ) 91 | set_property(TEST test_priority_321 92 | APPEND 93 | PROPERTY 94 | ENVIRONMENT "tool_two_priority=2" 95 | ) 96 | set_property(TEST test_priority_321 97 | APPEND 98 | PROPERTY 99 | ENVIRONMENT "tool_three_priority=1" 100 | ) 101 | 102 | #add_test(test_priority_221 priority_app) 103 | #set_property(TEST test_priority_221 104 | # PROPERTY 105 | # ENVIRONMENT "tool_one_priority=2" 106 | #) 107 | #set_property(TEST test_priority_221 108 | # APPEND 109 | # PROPERTY 110 | # ENVIRONMENT "tool_two_priority=2" 111 | #) 112 | #set_property(TEST test_priority_221 113 | # APPEND 114 | # PROPERTY 115 | # ENVIRONMENT "tool_three_priority=1" 116 | #) 117 | add_test(test_priority_212 priority_app) 118 | set_property(TEST test_priority_212 119 | PROPERTY 120 | ENVIRONMENT "tool_one_priority=2" 121 | ) 122 | set_property(TEST test_priority_212 123 | APPEND 124 | PROPERTY 125 | ENVIRONMENT "tool_two_priority=1" 126 | ) 127 | set_property(TEST test_priority_212 128 | APPEND 129 | PROPERTY 130 | ENVIRONMENT "tool_three_priority=2" 131 | ) 132 | #add_test(test_priority_122 priority_app) 133 | #set_property(TEST test_priority_122 134 | # PROPERTY 135 | # ENVIRONMENT "tool_one_priority=1" 136 | #) 137 | #set_property(TEST test_priority_122 138 | # APPEND 139 | # PROPERTY 140 | # ENVIRONMENT "tool_two_priority=2" 141 | #) 142 | #set_property(TEST test_priority_122 143 | # APPEND 144 | # PROPERTY 145 | # ENVIRONMENT "tool_three_priority=2" 146 | #) 147 | -------------------------------------------------------------------------------- /test/priority/app.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "lib1.h" 22 | #include "tool1.h" 23 | #include "tool2.h" 24 | #include "tool3.h" 25 | extern int init_autotee(char *filename); 26 | extern int close_autotee(); 27 | 28 | #define OUTPUT_FILE "tee.out" 29 | char *get_string(char *in) { 30 | if (in) { 31 | free(in); 32 | } 33 | char *str = (char *)malloc(sizeof(char) * 15); 34 | memset(str, 0, sizeof(const char) * 15); 35 | return str; 36 | } 37 | #define Q(x) #x 38 | #define QUOTE(x) Q(x) 39 | 40 | void bubble3(int *in) { 41 | int indices[3]; 42 | indices[0] = 1; 43 | indices[1] = 2; 44 | indices[2] = 3; 45 | int i = 0; 46 | int k = 0; 47 | for (i = 0; i < 3; i++) { 48 | for (k = 0; k < 2; k++) { 49 | if (in[k] <= in[k + 1]) { 50 | int temp = in[k]; 51 | in[k] = in[k + 1]; 52 | in[k + 1] = temp; 53 | temp = indices[k]; 54 | indices[k] = indices[k + 1]; 55 | indices[k + 1] = temp; 56 | } 57 | } 58 | } 59 | in[0] = indices[0]; 60 | in[1] = indices[1]; 61 | in[2] = indices[2]; 62 | } 63 | int priority_from_str(const char *in, int default_val) { 64 | return in ? atoi(in) : default_val; 65 | } 66 | char *get_expected_result(int p1, int p2, int p3) { 67 | char *x = (char *)malloc(sizeof(char) * 13); 68 | int ordering[3]; 69 | ordering[0] = p1; 70 | ordering[1] = p2; 71 | ordering[2] = p3; 72 | bubble3(ordering); 73 | p1 = ordering[0]; 74 | p2 = ordering[1]; 75 | p3 = ordering[2]; 76 | sprintf(x, "t%d=>t%d=>t%d=>", p1, p2, p3); 77 | return x; 78 | } 79 | int main() { 80 | const char *env_one = getenv("tool_one_priority"); 81 | const char *env_two = getenv("tool_two_priority"); 82 | const char *env_three = getenv("tool_three_priority"); 83 | int tool_one_priority = priority_from_str(env_one, 1); 84 | int tool_two_priority = priority_from_str(env_two, 2); 85 | int tool_three_priority = priority_from_str(env_three, 3); 86 | 87 | char *expected_result = get_expected_result( 88 | tool_one_priority, tool_two_priority, tool_three_priority); 89 | int result; 90 | // breaks on:: 321 91 | char *str = NULL; 92 | gotcha_set_priority("tool1", tool_one_priority); 93 | gotcha_set_priority("tool2", tool_two_priority); 94 | gotcha_set_priority("tool3", tool_three_priority); 95 | result = init_tool1(); 96 | result = init_tool2(); 97 | result = init_tool3(); 98 | if (result != 0) return -1; 99 | str = get_string(str); 100 | retX(str); 101 | int fail = strncmp(str, expected_result, 12); 102 | if (fail) { 103 | fprintf(stderr, "Failed test, expected %s, got %s\n", expected_result, str); 104 | } 105 | return fail; 106 | } 107 | -------------------------------------------------------------------------------- /test/priority/lib1.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "lib1.h" 16 | const char *retX(const char *x) { return x; } 17 | -------------------------------------------------------------------------------- /test/priority/lib1.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_LIB1_H 16 | #define GOTCHA_LIB1_H 17 | const char *retX(const char *x); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/priority/tool1.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool1.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | static char *retX_wrapper(char *x); 27 | 28 | static gotcha_wrappee_handle_t origRetX_handle = 0x0; 29 | 30 | #define NUM_IOFUNCS 1 31 | struct gotcha_binding_t iofuncs[] = {{"retX", retX_wrapper, &origRetX_handle}}; 32 | 33 | char *retX_wrapper(char *x) { 34 | typeof(&retX_wrapper) origRetX = gotcha_get_wrappee(origRetX_handle); 35 | strcat(x, "t1=>"); 36 | 37 | return origRetX ? (origRetX(x)) : 0; 38 | } 39 | 40 | int init_tool1() { 41 | enum gotcha_error_t result; 42 | 43 | result = gotcha_wrap(iofuncs, NUM_IOFUNCS, "tool1"); 44 | if (result != GOTCHA_SUCCESS) { 45 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 46 | return -1; 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/priority/tool1.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL1_H 16 | #define GOTCHA_TOOL1_H 17 | int init_tool1(); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/priority/tool2.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool2.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | __attribute__((unused)) static char *retX_wrapper(char *x); 27 | 28 | static gotcha_wrappee_handle_t origRetX_handle = 0x0; 29 | 30 | #define NUM_IOFUNCS 1 31 | struct gotcha_binding_t iofuncs2[] = {{"retX", retX_wrapper, &origRetX_handle}}; 32 | 33 | char *retX_wrapper(char *x) { 34 | typeof(&retX_wrapper) origRetX = gotcha_get_wrappee(origRetX_handle); 35 | strcat(x, "t2=>"); 36 | 37 | return origRetX ? (origRetX(x)) : 0; 38 | } 39 | 40 | int init_tool2() { 41 | enum gotcha_error_t result; 42 | 43 | result = gotcha_wrap(iofuncs2, NUM_IOFUNCS, "tool2"); 44 | if (result != GOTCHA_SUCCESS) { 45 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 46 | return -1; 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /test/priority/tool2.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL2_H 16 | #define GOTCHA_TOOL2_H 17 | int init_tool2(); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/priority/tool3.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool3.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | __attribute__((unused)) static char *retX_wrapper(char *x); 27 | 28 | static gotcha_wrappee_handle_t origRetX_handle = 0x0; 29 | 30 | #define NUM_IOFUNCS 1 31 | struct gotcha_binding_t iofuncs3[] = {{"retX", retX_wrapper, &origRetX_handle}}; 32 | 33 | char *retX_wrapper(char *x) { 34 | typeof(&retX_wrapper) origRetX = gotcha_get_wrappee(origRetX_handle); 35 | strcat(x, "t3=>"); 36 | 37 | return origRetX ? (origRetX(x)) : 0; 38 | } 39 | 40 | int init_tool3() { 41 | enum gotcha_error_t result; 42 | 43 | result = gotcha_wrap(iofuncs3, NUM_IOFUNCS, "tool3"); 44 | if (result != GOTCHA_SUCCESS) { 45 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 46 | return -1; 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /test/priority/tool3.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL3_H 16 | #define GOTCHA_TOOL3_H 17 | int init_tool3(); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/rogot/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-z -Wl,relro -Wl,-z,combreloc,-z,now") 2 | add_library(autotee2 SHARED autotee.c) 3 | add_executable(autotee_test2 test_autotee.c) 4 | target_link_libraries(autotee2 gotcha) 5 | target_link_libraries(autotee_test2 autotee2) 6 | gotcha_add_test(test_readonly_got autotee_test2) 7 | 8 | -------------------------------------------------------------------------------- /test/rogot/test_autotee.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | extern int init_autotee(char *filename); 20 | extern int close_autotee(); 21 | 22 | #define OUTPUT_FILE "tee.out" 23 | 24 | int main() { 25 | int result; 26 | 27 | printf("Every stdout print after this line should also appear in %s:\n", 28 | OUTPUT_FILE); 29 | 30 | result = init_autotee(OUTPUT_FILE); 31 | if (result != 0) return -1; 32 | 33 | printf("First line\n"); 34 | printf("Second %s\n", "line"); 35 | fprintf(stdout, "Third line\n"); 36 | fprintf(stdout, "%s line\n", "Forth"); 37 | puts("Fifth line"); 38 | fputs("Sixth ", stdout); 39 | fputs("line\n", stdout); 40 | fwrite("Seventh line\n", 1, strlen("Seventh line\n"), stdout); 41 | fprintf(stderr, "Eighth line is stderr and should not appear in in %s\n", 42 | OUTPUT_FILE); 43 | close_autotee(); 44 | printf("Ninth line is after close and should not appear in %s\n", 45 | OUTPUT_FILE); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test/stack/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(stacked_lib1 SHARED lib1.c) 2 | add_library(stacked_tool1 SHARED tool1.c) 3 | add_library(stacked_tool2 SHARED tool2.c) 4 | add_executable(stacked_app app.c) 5 | target_link_libraries(stacked_app gotcha) 6 | target_link_libraries(stacked_tool1 gotcha) 7 | target_link_libraries(stacked_tool2 gotcha) 8 | target_link_libraries(stacked_app stacked_lib1 stacked_tool1 stacked_tool2) 9 | add_test(test_stacked stacked_app) 10 | 11 | -------------------------------------------------------------------------------- /test/stack/app.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "lib1.h" 20 | #include "tool1.h" 21 | #include "tool2.h" 22 | 23 | extern int init_autotee(char *filename); 24 | extern int close_autotee(); 25 | 26 | #define OUTPUT_FILE "tee.out" 27 | 28 | int main() { 29 | int result; 30 | 31 | result = init_tool1(); 32 | result = init_tool2(); 33 | if (result != 0) return -1; 34 | 35 | result = retX(10); 36 | printf("Result %d\n", result); 37 | return (result == 13) ? 0 : 1; 38 | } 39 | -------------------------------------------------------------------------------- /test/stack/lib1.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "lib1.h" 16 | int retX(int x) { return x; } 17 | -------------------------------------------------------------------------------- /test/stack/lib1.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_LIB1_H 16 | #define GOTCHA_LIB1_H 17 | int retX(int x); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/stack/tool1.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool1.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | static int retX_wrapper(int x); 27 | 28 | static gotcha_wrappee_handle_t origRetX_handle = 0x0; 29 | 30 | #define NUM_IOFUNCS 1 31 | struct gotcha_binding_t iofuncs[] = {{"retX", retX_wrapper, &origRetX_handle}}; 32 | 33 | int retX_wrapper(int x) { 34 | typeof(&retX_wrapper) origRetX = gotcha_get_wrappee(origRetX_handle); 35 | printf("In tool1 wrapper, calling %p\n", origRetX); 36 | return origRetX ? (origRetX(x) + 1) : 0; 37 | } 38 | 39 | int init_tool1() { 40 | enum gotcha_error_t result; 41 | 42 | result = gotcha_wrap(iofuncs, NUM_IOFUNCS, "tool1"); 43 | if (result != GOTCHA_SUCCESS) { 44 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 45 | return -1; 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test/stack/tool1.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL1_H 16 | #define GOTCHA_TOOL1_H 17 | int init_tool1(); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/stack/tool2.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "tool2.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gotcha/gotcha.h" 24 | #include "gotcha/gotcha_types.h" 25 | 26 | __attribute__((unused)) static int retX_wrapper(int x); 27 | 28 | static gotcha_wrappee_handle_t origRetX_handle = 0x0; 29 | 30 | #define NUM_IOFUNCS 1 31 | struct gotcha_binding_t iofuncs2[] = {{"retX", retX_wrapper, &origRetX_handle}}; 32 | 33 | int retX_wrapper(int x) { 34 | typeof(&retX_wrapper) origRetX = gotcha_get_wrappee(origRetX_handle); 35 | printf("In tool2 wrapper, calling %p\n", origRetX); 36 | return origRetX ? (origRetX(x) + 2) : 0; 37 | } 38 | 39 | int init_tool2() { 40 | enum gotcha_error_t result; 41 | 42 | result = gotcha_wrap(iofuncs2, NUM_IOFUNCS, "tool2"); 43 | if (result != GOTCHA_SUCCESS) { 44 | fprintf(stderr, "gotcha_wrap returned %d\n", (int)result); 45 | return -1; 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/stack/tool2.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef GOTCHA_TOOL2_H 16 | #define GOTCHA_TOOL2_H 17 | int init_tool2(); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/symver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/symver.map") 2 | add_library(retX SHARED retX_old.c retX_new.c) 3 | 4 | add_executable(symver_test test_symver.c) 5 | target_link_libraries(symver_test retX gotcha) 6 | gotcha_add_test(test_symbol_versions symver_test) 7 | -------------------------------------------------------------------------------- /test/symver/retX.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #ifndef RETX_LIB_H 16 | #define RETX_LIB_H 17 | int retX(int x); 18 | #endif 19 | -------------------------------------------------------------------------------- /test/symver/retX_new.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "sym_macro.h" 16 | // clang-format off 17 | SYMVER_ATTRIBUTE(retX_new, retX@@GOTCHA_2) 18 | int retX_new(int x) { return x; } 19 | // clang-format on -------------------------------------------------------------------------------- /test/symver/retX_old.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | #include "sym_macro.h" 16 | 17 | // clang-format off 18 | SYMVER_ATTRIBUTE(retX_old, retX@GOTCHA_1) 19 | int retX_old(int x) { return -x; } 20 | // clang-format on 21 | -------------------------------------------------------------------------------- /test/symver/sym_macro.h: -------------------------------------------------------------------------------- 1 | #ifndef GOTCHA_SYM_MACRO_H 2 | #define GOTCHA_SYM_MACRO_H 3 | #ifdef __has_attribute 4 | #if __has_attribute(__symver__) 5 | #define SYMVER_ATTRIBUTE(sym, symver) __attribute__((__symver__(#symver))) 6 | #endif 7 | #endif 8 | #ifndef SYMVER_ATTRIBUTE 9 | #define SYMVER_ATTRIBUTE(sym, symver) \ 10 | __asm__("\t.globl __" #sym \ 11 | "\n" \ 12 | "\t.equiv __" #sym "," #sym \ 13 | "\n" \ 14 | "\t.symver __" #sym "," #symver); 15 | #endif 16 | #endif // GOTCHA_SYM_MACRO_H 17 | -------------------------------------------------------------------------------- /test/symver/symver.map: -------------------------------------------------------------------------------- 1 | GOTCHA_1 { 2 | global: 3 | retX; 4 | local: *; 5 | }; 6 | GOTCHA_2 { 7 | global: 8 | retX; 9 | local: *; 10 | } GOTCHA_1; 11 | -------------------------------------------------------------------------------- /test/symver/test_symver.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "retX.h" 21 | 22 | // We need a place to store the pointer to the function we've wrapped 23 | static gotcha_wrappee_handle_t origRetX_handle; 24 | 25 | static int dogRetX(int x); 26 | 27 | static struct gotcha_binding_t bindings[] = { 28 | {"retX", dogRetX, &origRetX_handle}}; 29 | 30 | // This is like a tool library's initialization function 31 | static int wrap_init(void) { 32 | gotcha_wrap(bindings, 1, "symbol_version_test"); 33 | return 0; 34 | } 35 | 36 | int dogRetX(int x) { 37 | typeof(&dogRetX) origRetX = gotcha_get_wrappee(origRetX_handle); 38 | printf("SO I FOR ONE THINK DOGS SHOULD RETURN %i\n", x); 39 | return origRetX ? origRetX(x) + 1 : 0; 40 | } 41 | 42 | int main(int ac, char *av[]) { 43 | wrap_init(); 44 | int check_val = retX(9); 45 | assert(check_val == 10); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /test/unit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(internal_unit_sample SHARED testing_lib.c) 2 | include(ExternalProject) 3 | find_package(Git REQUIRED) 4 | if (DEPENDENCIES_PREINSTALLED) 5 | else () 6 | ExternalProject_Add( 7 | check_project 8 | PREFIX ${CMAKE_CURRENT_BINARY_DIR} 9 | GIT_REPOSITORY https://github.com/libcheck/check 10 | TIMEOUT 10 11 | UPDATE_COMMAND ${GIT_EXECUTABLE} pull 12 | CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/tpl" 13 | BUILD_COMMAND "make" 14 | INSTALL_COMMAND make install 15 | LOG_DOWNLOAD ON 16 | ) 17 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/tpl/include) 18 | LINK_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/tpl/lib) 19 | endif () 20 | 21 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../src) 22 | find_library(check NAME libcheck.a) 23 | add_executable(unit_tests gotcha_unit_tests.c) 24 | target_link_libraries(unit_tests check gotcha internal_unit_sample m rt pthread) 25 | set_source_files_properties(testing_lib.c PROPERTIES LINK_FLAGS -Wl,--hash-style=sysv) 26 | add_library(internal_unit_sample_elf SHARED testing_lib.c) 27 | set_target_properties(internal_unit_sample_elf PROPERTIES LINK_FLAGS -Wl,--hash-style=sysv) 28 | add_executable(unit_tests_elf gotcha_unit_tests.c) 29 | target_link_libraries(unit_tests_elf check gotcha_no_libc internal_unit_sample_elf m rt pthread) 30 | set_target_properties(unit_tests_elf PROPERTIES COMPILE_DEFINITIONS "FORCE_NO_LIBC") 31 | gotcha_add_test(full_unit unit_tests) 32 | gotcha_add_test(full_unit_elf unit_tests_elf) 33 | environment_add(full_unit TEST "GOTCHA_DEBUG=3") 34 | environment_add(full_unit_elf TEST "GOTCHA_DEBUG=3") 35 | -------------------------------------------------------------------------------- /test/unit/testing_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #include "testing_lib.h" 17 | int simpleFunc() { return TESTING_LIB_RET_VAL; } 18 | int hiddenFunc() { return TESTING_LIB_RET_VAL; } 19 | -------------------------------------------------------------------------------- /test/unit/testing_lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of GOTCHA. For copyright information see the COPYRIGHT 3 | file in the top level directory, or at 4 | https://github.com/LLNL/gotcha/blob/master/COPYRIGHT 5 | This program is free software; you can redistribute it and/or modify it under 6 | the terms of the GNU Lesser General Public License (as published by the Free 7 | Software Foundation) version 2.1 dated February 1999. This program is 8 | distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 9 | without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | PURPOSE. See the terms and conditions of the GNU Lesser General Public License 11 | for more details. You should have received a copy of the GNU Lesser General 12 | Public License along with this program; if not, write to the Free Software 13 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 14 | */ 15 | 16 | #ifndef GOTCHA_TESTING_LIB_H 17 | #define GOTCHA_TESTING_LIB_H 18 | #include 19 | #define TESTING_LIB_RET_VAL 0x23cf3 20 | int simpleFunc(); 21 | int __attribute__((visibility("hidden"))) hiddenFunc(); 22 | #endif 23 | -------------------------------------------------------------------------------- /test/wrap_main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(main_functions SHARED lib.c) 2 | add_executable(main app.c) 3 | target_link_libraries(main_functions gotcha) 4 | target_link_libraries(main main_functions) 5 | gotcha_add_test(main_test main) 6 | environment_add(main_test TEST "GOTCHA_DEBUG=3") 7 | -------------------------------------------------------------------------------- /test/wrap_main/app.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "lib.h" 4 | int main() { 5 | printf("In main main\n"); 6 | return getX(); 7 | } 8 | -------------------------------------------------------------------------------- /test/wrap_main/lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | #include 5 | gotcha_wrappee_handle_t orig_main_handle; 6 | int x; 7 | int getX() { return x; } 8 | int couldnt_find_a_better_main(int argc, char **argv) { 9 | printf("In wrapper main\n"); 10 | typeof(&couldnt_find_a_better_main) orig_main = 11 | gotcha_get_wrappee(orig_main_handle); 12 | int i; 13 | for (i = 0; i < argc; i++) { 14 | printf("%d : %s\n", i, argv[i]); 15 | } 16 | int return_code = orig_main(argc, argv) - 1; 17 | printf("Returning %d\n", return_code); 18 | return return_code; 19 | } 20 | struct gotcha_binding_t actions[] = { 21 | {"main", couldnt_find_a_better_main, &orig_main_handle}}; 22 | void phnglui() __attribute__((constructor)); 23 | void phnglui() { 24 | x += 1; 25 | printf("In attr constructor func\n"); 26 | gotcha_wrap(actions, 1, "test_tool"); 27 | } 28 | -------------------------------------------------------------------------------- /test/wrap_main/lib.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void phnglui(); 4 | int couldnt_find_a_better_main(int argc, char **argv); 5 | int getX(); 6 | --------------------------------------------------------------------------------