├── .clang-format ├── .dockerignore ├── .github └── workflows │ └── build.yml ├── .gitignore ├── CMakeLists.txt ├── CTestCustom.cmake ├── LICENSE ├── README.md ├── build-pytorch.sh ├── cmake └── third-party.cmake ├── ehframe_builder.h ├── elf_binary.cc ├── elf_binary.h ├── feature_unit_tests ├── call_once-g++-aarch64 │ ├── .gitignore │ ├── fuga.cc │ ├── hoge.cc │ ├── main.cc │ └── test.sh ├── call_once-g++ │ ├── .gitignore │ ├── fuga.cc │ ├── hoge.cc │ ├── main.cc │ └── test.sh ├── delete-unused-PT_DYNAMIC │ ├── answer │ │ └── .gitkeep │ ├── base.c │ ├── base.h │ ├── base2.c │ ├── base2.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ ├── sold_out │ │ └── .gitkeep │ └── test.sh ├── dynamic_cast-g++-aarch64 │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── dynamic_cast-g++ │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── exception-g++-aarch64 │ ├── fuga.cc │ ├── fuga.h │ ├── hoge.cc │ ├── hoge.h │ ├── main.cc │ └── test.sh ├── exception-g++ │ ├── fuga.cc │ ├── fuga.h │ ├── hoge.cc │ ├── hoge.h │ ├── main.cc │ └── test.sh ├── exception-str-g++-aarch64 │ ├── fuga.cc │ ├── fuga.h │ ├── hoge.cc │ ├── hoge.h │ ├── main.cc │ └── test.sh ├── exe.cc ├── extern │ ├── hoge.c │ ├── main.c │ └── test.sh ├── global-write-aarch64 │ ├── hoge.c │ ├── main.c │ └── test.sh ├── hello-g++-aarch64 │ ├── .gitignore │ ├── hello.cc │ └── test.sh ├── hello-g++ │ ├── .gitignore │ ├── hello.cc │ └── test.sh ├── hello-gcc-aarch64 │ ├── hello.c │ └── test.sh ├── hello-gcc │ ├── .gitignore │ ├── hello.c │ └── test.sh ├── inheritance-g++-aarch64 │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── inheritance-g++ │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── just-return-g++-aarch64 │ ├── return.cc │ └── test.sh ├── just-return-g++ │ ├── return.cc │ └── test.sh ├── just-return-gcc-aarch64 │ ├── .gitignore │ ├── return.c │ └── test.sh ├── just-return-gcc │ ├── .gitignore │ ├── return.c │ └── test.sh ├── mprotect-aarch64 │ ├── .gitignore │ ├── base.c │ ├── base.h │ ├── main.c │ ├── mprotect_check.c │ ├── mprotect_check.h │ └── test.sh ├── mprotect │ ├── .gitignore │ ├── base.c │ ├── base.h │ ├── main.c │ ├── mprotect_check.c │ ├── mprotect_check.h │ └── test.sh ├── renamer │ ├── .gitignore │ ├── fugafuga.c │ ├── hoge.c │ ├── mapping │ ├── test.sh │ └── use_fugafuga.c ├── run-all-tests.sh ├── setjmp-gcc-aarch64 │ ├── .gitignore │ ├── hoge.c │ ├── hoge.h │ ├── main.c │ └── test.sh ├── setjmp-gcc │ ├── .gitignore │ ├── hoge.c │ ├── hoge.h │ ├── main.c │ └── test.sh ├── simple-lib-g++-aarch64 │ ├── .gitignore │ ├── libmax.cc │ ├── libmax.h │ ├── main.cc │ └── test.sh ├── simple-lib-g++ │ ├── .gitignore │ ├── libmax.cc │ ├── libmax.h │ ├── main.cc │ └── test.sh ├── simple-lib-gcc-aarch64 │ ├── .gitignore │ ├── libmax.c │ ├── libmax.h │ ├── main.c │ └── test.sh ├── simple-lib-gcc │ ├── .gitignore │ ├── libmax.c │ ├── libmax.h │ ├── main.c │ └── test.sh ├── static-in-class-g++-aarch64 │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── static-in-class-g++ │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── static-in-function-g++-aarch64 │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── static-in-function-g++ │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── stb_gnu_unique_tls-aarch64 │ ├── .gitignore │ ├── main.cc │ ├── test.sh │ └── unique.cc ├── stb_gnu_unique_tls │ ├── .gitignore │ ├── main.cc │ ├── test.sh │ └── unique.cc ├── tls-bss-g++-aarch64 │ ├── main.cc │ └── test.sh ├── tls-bss-g++ │ ├── main.cc │ └── test.sh ├── tls-bss-gcc-aarch64 │ ├── main.c │ └── test.sh ├── tls-bss-gcc │ ├── main.c │ └── test.sh ├── tls-conflict-aarch64 │ ├── fuga.cc │ ├── hoge.cc │ ├── main.cc │ └── test.sh ├── tls-dlopen-gcc-aarch64 │ ├── .gitignore │ ├── lib.c │ ├── main.c │ └── test.sh ├── tls-dlopen-gcc │ ├── .gitignore │ ├── lib.c │ ├── main.c │ └── test.sh ├── tls-gcc-aarch64 │ ├── main.c │ └── test.sh ├── tls-gcc │ ├── main.c │ └── test.sh ├── tls-lib-gcc-aarch64 │ ├── answer │ │ └── .gitkeep │ ├── base.c │ ├── base.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ ├── sold_out │ │ └── .gitkeep │ └── test.sh ├── tls-lib-gcc-without-base-aarch64 │ ├── base.c │ ├── base.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ ├── sold_out │ │ └── .gitkeep │ └── test.sh ├── tls-lib-gcc-without-base │ ├── base.c │ ├── base.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ ├── sold_out │ │ └── .gitkeep │ └── test.sh ├── tls-lib-gcc │ ├── answer │ │ └── .gitkeep │ ├── base.c │ ├── base.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ ├── sold_out │ │ └── .gitkeep │ └── test.sh ├── tls-multiple-lib-gcc-aarch64 │ ├── answer │ │ └── .gitkeep │ ├── base.c │ ├── base.h │ ├── base2.c │ ├── base2.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ └── test.sh ├── tls-multiple-lib-gcc │ ├── answer │ │ └── .gitkeep │ ├── base.c │ ├── base.h │ ├── base2.c │ ├── base2.h │ ├── lib.c │ ├── lib.h │ ├── main.c │ ├── original │ │ └── .gitkeep │ ├── sold_out │ │ └── .gitkeep │ └── test.sh ├── tls-multiple-module-g++-aarch64 │ ├── .gitignore │ ├── fuga.cc │ ├── fuga.h │ ├── fugahoge.cc │ ├── hoge.cc │ ├── hoge.h │ ├── main.cc │ └── test.sh ├── tls-multiple-module-g++ │ ├── .gitignore │ ├── fuga.cc │ ├── fuga.h │ ├── fugahoge.cc │ ├── hoge.cc │ ├── hoge.h │ ├── main.cc │ └── test.sh ├── tls-thread-g++-aarch64 │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── tls-thread-g++ │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── typeid-g++-aarch64 │ ├── .gitignore │ ├── fuga.h │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── typeid-g++ │ ├── .gitignore │ ├── lib.cc │ ├── lib.h │ ├── main.cc │ └── test.sh ├── unique_ptr-aarch64 │ ├── .gitignore │ ├── hoge.cc │ ├── main.cc │ └── test.sh ├── version-gcc-aarch64 │ ├── .gitignore │ ├── libmax1.c │ ├── libmax1.h │ ├── libmax2.c │ ├── libmax2.def │ ├── libmax2.h │ ├── test.sh │ ├── vertest1.c │ └── vertest2.c └── version-gcc │ ├── .gitignore │ ├── libmax1.c │ ├── libmax1.h │ ├── libmax2.c │ ├── libmax2.def │ ├── libmax2.h │ ├── test.sh │ ├── vertest1.c │ └── vertest2.c ├── fedora-latest.Dockerfile ├── hash.cc ├── hash.h ├── ldsoconf.cc ├── ldsoconf.h ├── libtorch_test ├── CMakeLists.txt ├── torch_test.cc ├── torch_test.h ├── torch_test_main.cc └── torch_test_main_dlopen.cc ├── mprotect_builder.cc ├── mprotect_builder.h ├── print_dtrela.cc ├── print_dynsymtab.cc ├── print_ehframe.cc ├── print_tls.cc ├── print_version.cc ├── pybind_libtorch_test ├── CMakeLists.txt ├── numpy.cc └── test_soldout_modules.py ├── pybind_test ├── CMakeLists.txt ├── README.md ├── add.cc ├── numpy.cc ├── object.cc └── test_soldout_modules.py ├── renamer_main.cc ├── renamer_test ├── .gitignore ├── fugafuga.c ├── hoge.c ├── mapping ├── test.sh └── use_fugafuga.c ├── run-docker-tests.sh ├── run-format.sh ├── shdr_builder.cc ├── shdr_builder.h ├── sold.cc ├── sold.h ├── sold_main.cc ├── strtab_builder.cc ├── strtab_builder.h ├── symtab_builder.cc ├── symtab_builder.h ├── tests ├── CMakeLists.txt ├── base.cc ├── base.h ├── exe.cc ├── lib.cc ├── lib.h └── runtest.sh ├── third_party ├── glog.cmake └── pybind11.cmake ├── tools ├── listup_duplicated_syms.py ├── raw_write.h ├── relocation-list-up.sh ├── resolve_addr.py ├── search-symbol.sh └── tracer.cc ├── ubuntu18.04-gpu.Dockerfile ├── ubuntu18.04.Dockerfile ├── ubuntu20.04.Dockerfile ├── ubuntu22.04.Dockerfile ├── utils.cc ├── utils.h ├── version_builder.cc └── version_builder.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | AccessModifierOffset: -4 3 | ColumnLimit: 140 4 | IndentWidth: 4 5 | DerivePointerAlignment: false 6 | PointerAlignment: Left 7 | IncludeBlocks: Preserve 8 | AllowShortFunctionsOnASingleLine: Inline 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | build/* 2 | myenv/* 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Install requirements 13 | run: sudo apt install ninja-build g++-aarch64-linux-gnu qemu qemu-system-aarch64 qemu-user 14 | - name: Install Python packages 15 | run: pip install pytest numpy cmake-format 16 | - name: format 17 | run: ./run-format.sh 18 | - name: CMake 19 | run: mkdir build && cd build && cmake -GNinja -DSOLD_PYBIND_TEST=ON .. 20 | - name: Build 21 | run: cmake --build build 22 | - name: Test 23 | run: cd build && ctest --output-on-failure 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.so 3 | *.original 4 | *.soldout 5 | *.o 6 | *.out 7 | pytorch 8 | pytorch-build 9 | pytorch-install 10 | .cache 11 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | project(sold LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | if(NOT CMAKE_BUILD_TYPE) 8 | set(CMAKE_BUILD_TYPE "RelWithDebInfo") 9 | endif() 10 | 11 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 12 | 13 | include(third-party) 14 | get_third_party(glog) 15 | set(WITH_GFLAGS OFF CACHE INTERNAL "" FORCE) 16 | add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_CURRENT_BINARY_DIR}/glog EXCLUDE_FROM_ALL) 17 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_CURRENT_BINARY_DIR}/glog/src) 18 | add_definitions(-DC10_USE_GLOG=1) 19 | 20 | add_library( 21 | sold_lib 22 | sold.cc 23 | elf_binary.cc 24 | hash.cc 25 | ldsoconf.cc 26 | mprotect_builder.cc 27 | strtab_builder.cc 28 | symtab_builder.cc 29 | shdr_builder.cc 30 | utils.cc 31 | version_builder.cc 32 | ) 33 | 34 | add_executable( 35 | sold 36 | sold_main.cc 37 | ) 38 | target_link_libraries(sold sold_lib glog) 39 | 40 | add_executable( 41 | print_dtrela 42 | print_dtrela.cc 43 | ) 44 | add_executable(renamer renamer_main.cc) 45 | target_link_libraries(renamer sold_lib glog) 46 | 47 | target_link_libraries(print_dtrela sold_lib glog) 48 | 49 | add_executable( 50 | print_dynsymtab 51 | print_dynsymtab.cc 52 | ) 53 | target_link_libraries(print_dynsymtab sold_lib glog) 54 | 55 | add_executable( 56 | print_tls 57 | print_tls.cc 58 | ) 59 | target_link_libraries(print_tls sold_lib glog) 60 | 61 | add_executable( 62 | print_version 63 | print_version.cc 64 | ) 65 | target_link_libraries(print_version sold_lib glog) 66 | 67 | add_executable( 68 | print_ehframe 69 | print_ehframe.cc 70 | ) 71 | target_link_libraries(print_ehframe sold_lib glog) 72 | 73 | add_subdirectory(tests) 74 | 75 | 76 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR}) 77 | include(CTest) 78 | 79 | if(BUILD_TESTING) 80 | add_custom_target(feature_unit_tests ALL COMMAND "rsync" "-au" "${CMAKE_CURRENT_SOURCE_DIR}/feature_unit_tests" "${CMAKE_CURRENT_BINARY_DIR}") 81 | add_custom_target(renamer_test ALL COMMAND "rsync" "-au" "${CMAKE_CURRENT_SOURCE_DIR}/renamer_test" "${CMAKE_CURRENT_BINARY_DIR}") 82 | foreach(t exe hash) 83 | add_custom_target( 84 | test_${t}_out ALL 85 | COMMAND "${CMAKE_CURRENT_BINARY_DIR}/sold" "${CMAKE_CURRENT_BINARY_DIR}/tests/test_${t}" -o "${CMAKE_CURRENT_BINARY_DIR}/tests/test_${t}_out" --section-headers 86 | DEPENDS sold test_${t} 87 | ) 88 | 89 | add_test( 90 | NAME ${t}_test 91 | COMMAND ${CMAKE_CURRENT_BINARY_DIR}/tests/test_${t}_out 92 | ) 93 | endforeach() 94 | add_test( 95 | NAME feature_unit_tests 96 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/feature_unit_tests" 97 | COMMAND run-all-tests.sh 98 | ) 99 | add_test( 100 | NAME renamer 101 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/renamer_test" 102 | COMMAND test.sh) 103 | endif() 104 | 105 | if(SOLD_PYBIND_TEST) 106 | get_third_party(pybind11) 107 | add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/pybind11 ${CMAKE_CURRENT_BINARY_DIR}/pybind11 EXCLUDE_FROM_ALL) 108 | add_subdirectory(pybind_test) 109 | endif() 110 | 111 | if(SOLD_LIBTORCH_TEST) 112 | add_subdirectory(libtorch_test) 113 | endif() 114 | 115 | if(SOLD_PYBIND_TEST AND SOLD_LIBTORCH_TEST) 116 | add_subdirectory(pybind_libtorch_test) 117 | endif() 118 | -------------------------------------------------------------------------------- /CTestCustom.cmake: -------------------------------------------------------------------------------- 1 | set(CTEST_CUSTOM_TESTS_IGNORE 2 | demangle 3 | logging 4 | signalhandler 5 | stacktrace 6 | stl_logging 7 | symbolize 8 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sold 2 | `sold` is a linker software which links a shared objects and its depending 3 | shared objects. For example, 4 | ```bash 5 | % ldd libhoge.so 6 | libfuga.so (0x00007fb6550b2000) 7 | % sold -i libhoge.so -o libhoge2.so 8 | % ldd libhoge2.so 9 | % 10 | ``` 11 | `sold` works only for shared objects not for executables. Sorry. 12 | 13 | ## Branches 14 | - `master`: I am developing on this branch. 15 | - `stable`: Stable version of master for our internal use. 16 | 17 | ## Requirements 18 | `sold` works only on Linux on x86-64 and aarch64 architectures. 19 | 20 | ## How to build 21 | ```bash 22 | git clone https://github.com/akawashiro/sold.git 23 | cd sold 24 | mkdir -p build 25 | cd build 26 | cmake .. 27 | make 28 | ``` 29 | Now you can see the `sold` in `build` directory. 30 | 31 | ## How to use 32 | ```bash 33 | sold -i [INPUT] -o [OUTPUT] 34 | ``` 35 | Options 36 | - `--section-headers`: Emit section headers. Output shared objects work without section headers but they are useful for debugging. 37 | - `--check-output`: Check integrity of the output by parsing it again. 38 | - `--exclude-so`: Specify a shared object not to combine. 39 | 40 | # Renamer 41 | `renamer` is software to rename symbols in shared objects. You can rename symbols in shared objects like the following. 42 | ``` 43 | % cat mapping 44 | hoge fugafuga 45 | % renamer libhoge_original.so --output libhoge_renamed.so --rename-mapping-file mapping 46 | ``` 47 | 48 | ## Requirements & How to build 49 | Just same as `sold`. 50 | 51 | ## How to use 52 | ```bash 53 | renamer [INPUT] --output [OUTPUT] --rename-mapping-file [MAPPING] 54 | ``` 55 | All lines in [MAPPING] must be a space separated pair of the old name of a symbol and the new name. 56 | 57 | # For developers 58 | Please run "./run-format.sh" before merging to master branch. 59 | 60 | ## TODO 61 | - Executables 62 | - TLS in executables 63 | - Initial exec and local exec 64 | - x86-32 65 | - Test Fedora linux in CI 66 | 67 | ## Integration test with practical libraries 68 | ### pybind test 69 | The purpose of this test is to check `sold` can preserve the complex ABI. 70 | ```bash 71 | git clone https://github.com/akawashiro/sold.git 72 | cd sold 73 | mkdir -p build 74 | cmake -S . -B build -DSOLD_PYBIND_TEST=ON -G Ninja 75 | cmake --build build 76 | ctest --test-dir build 77 | ``` 78 | ## libtorch test 79 | Note: You can generate libtorch using `./build-pytorch.sh`. This script install libtorch to `sold/pytorch-install`. 80 | ``` 81 | git clone https://github.com/akawashiro/sold.git 82 | cd sold 83 | mkdir -p build 84 | cmake -B build -S . -DCMAKE_PREFIX_PATH=/absolute/path/to/libtorch/dir -DSOLD_LIBTORCH_TEST=ON -GNinja 85 | cmake --build build 86 | ctest --test-dir build 87 | ``` 88 | ## pybind + libtorch test 89 | Note: You can generate libtorch using `./build-pytorch.sh`. This script install libtorch to `sold/pytorch-install`. 90 | ``` 91 | git clone https://github.com/akawashiro/sold.git 92 | cd sold 93 | mkdir -p build 94 | cmake -DCMAKE_PREFIX_PATH=/absolute/path/to/libtorch/dir -DSOLD_LIBTORCH_TEST=ON -DSOLD_PYBIND_TEST=ON -GNinja -B build -S . 95 | cmake --build build 96 | ctest --test-dir build 97 | ``` 98 | 99 | 100 | ## Test with Docker 101 | ``` 102 | sudo docker build -f ubuntu18.04.Dockerfile . 103 | sudo docker build -f ubuntu20.04.Dockerfile . 104 | sudo docker build -f ubuntu22.04.Dockerfile . 105 | sudo docker build -f fedora-latest.Dockerfile . 106 | ``` 107 | -------------------------------------------------------------------------------- /build-pytorch.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | # git clone --branch v1.13.0 git@github.com:pytorch/pytorch.git pytorch 4 | # pushd pytorch 5 | # git submodule update --init --recursive 6 | # popd 7 | 8 | BUILD_DIR=$(pwd)/pytorch-build 9 | INSTALL_DIR=$(pwd)/pytorch-install 10 | mkdir -p ${BUILD_DIR} 11 | mkdir -p ${INSTALL_DIR} 12 | cmake -S pytorch -B ${BUILD_DIR} -G Ninja \ 13 | -DBUILD_SHARED_LIBS:BOOL=ON \ 14 | -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \ 15 | -DPYTHON_EXECUTABLE:PATH=`which python3` \ 16 | -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ 17 | -DUSE_CUDA=OFF \ 18 | -DUSE_CUDNN=OFF \ 19 | -DUSE_ROCM=OFF \ 20 | -DUSE_NCCL=OFF \ 21 | -DUSE_NNPACK=OFF \ 22 | -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ 23 | -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_DIR} 24 | cmake --build pytorch-build -- -j12 install 25 | -------------------------------------------------------------------------------- /cmake/third-party.cmake: -------------------------------------------------------------------------------- 1 | # Download and unpack a third-party library at configure time 2 | # The original code is at the README of google-test: 3 | # https://github.com/google/googletest/tree/master/googletest 4 | function(get_third_party name) 5 | configure_file( 6 | "${PROJECT_SOURCE_DIR}/third_party/${name}.cmake" 7 | "${CMAKE_CURRENT_BINARY_DIR}/${name}-download/CMakeLists.txt") 8 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . 9 | RESULT_VARIABLE result 10 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${name}-download") 11 | if(result) 12 | message(FATAL_ERROR "CMake step for ${name} failed: ${result}") 13 | endif() 14 | execute_process(COMMAND ${CMAKE_COMMAND} --build . 15 | RESULT_VARIABLE result 16 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${name}-download") 17 | if(result) 18 | message(FATAL_ERROR "Build step for ${name} failed: ${result}") 19 | endif() 20 | endfunction() 21 | -------------------------------------------------------------------------------- /ehframe_builder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include "utils.h" 19 | 20 | class EHFrameBuilder { 21 | public: 22 | EHFrameBuilder() { 23 | eh_frame_header_.version = 0x1; 24 | eh_frame_header_.eh_frame_ptr_enc = DW_EH_PE_sdata4 + DW_EH_PE_pcrel; 25 | eh_frame_header_.fde_count_enc = DW_EH_PE_udata4; 26 | eh_frame_header_.table_enc = DW_EH_PE_sdata4 | DW_EH_PE_datarel; 27 | eh_frame_header_.eh_frame_ptr = 0; 28 | eh_frame_header_.fde_count = 0; 29 | eh_frame_header_.table = std::vector(); 30 | } 31 | 32 | void Emit(FILE* fp) { 33 | Write(fp, eh_frame_header_.version); 34 | Write(fp, eh_frame_header_.eh_frame_ptr_enc); 35 | Write(fp, eh_frame_header_.fde_count_enc); 36 | Write(fp, eh_frame_header_.table_enc); 37 | Write(fp, eh_frame_header_.eh_frame_ptr); 38 | Write(fp, eh_frame_header_.fde_count); 39 | for (const EHFrameHeader::FDETableEntry te : eh_frame_header_.table) { 40 | Write(fp, te.initial_loc); 41 | Write(fp, te.fde_ptr); 42 | } 43 | } 44 | 45 | uintptr_t Size() const { 46 | return sizeof(eh_frame_header_.version) + sizeof(eh_frame_header_.eh_frame_ptr_enc) + sizeof(eh_frame_header_.fde_count_enc) + 47 | sizeof(eh_frame_header_.table_enc) + sizeof(eh_frame_header_.eh_frame_ptr) + sizeof(eh_frame_header_.fde_count) + 48 | eh_frame_header_.fde_count * 49 | (sizeof(EHFrameHeader::FDETableEntry::fde_ptr) + sizeof(EHFrameHeader::FDETableEntry::initial_loc)); 50 | } 51 | 52 | void Add(const std::string& name, const EHFrameHeader& efh, const uintptr_t efh_vaddr, const uintptr_t load_offset, 53 | const uintptr_t new_efh_vaddr) { 54 | LOG(INFO) << "EHFrameBuilder" << SOLD_LOG_BITS(efh.version) << SOLD_LOG_DWEHPE(efh.eh_frame_ptr_enc) 55 | << SOLD_LOG_DWEHPE(efh.fde_count_enc) << SOLD_LOG_DWEHPE(efh.table_enc) << SOLD_LOG_BITS(efh.eh_frame_ptr) 56 | << SOLD_LOG_BITS(efh.fde_count); 57 | for (const auto te : efh.table) { 58 | LOG(INFO) << "EHFrameBuilder" << SOLD_LOG_BITS(te.fde_ptr) << SOLD_LOG_BITS(te.initial_loc); 59 | } 60 | 61 | eh_frame_header_.fde_count += efh.fde_count; 62 | for (const auto te : efh.table) { 63 | EHFrameHeader::FDETableEntry new_te; 64 | new_te.fde_ptr = static_cast(efh_vaddr) + te.fde_ptr + static_cast(load_offset) - new_efh_vaddr; 65 | new_te.initial_loc = static_cast(efh_vaddr) + te.initial_loc + static_cast(load_offset) - new_efh_vaddr; 66 | eh_frame_header_.table.emplace_back(new_te); 67 | VLOG(3) << "EHFrameBuilder" << SOLD_LOG_BITS(new_te.fde_ptr) << SOLD_LOG_BITS(new_te.initial_loc); 68 | } 69 | } 70 | 71 | uint32_t fde_count() const { return eh_frame_header_.fde_count; } 72 | 73 | private: 74 | EHFrameHeader eh_frame_header_; 75 | }; 76 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libfuga.so 2 | libfuga.so.original 3 | libfuga.so.soldout 4 | libhoge.so 5 | main 6 | sold.* 7 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++-aarch64/fuga.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void thread_proc(); 4 | 5 | void fuga() { 6 | std::thread t1(thread_proc); 7 | std::thread t2(thread_proc); 8 | std::thread t3(thread_proc); 9 | 10 | t1.join(); 11 | t2.join(); 12 | t3.join(); 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++-aarch64/hoge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | std::once_flag once; 6 | 7 | void init() { 8 | std::cout << "initialize" << std::endl; 9 | } 10 | 11 | void thread_proc() { 12 | std::call_once(once, init); 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | void fuga(); 2 | 3 | int main() { 4 | fuga(); 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | aarch64-linux-gnu-g++ -fPIC -shared -Wl,-soname,libhoge.so -o libhoge.so hoge.cc 4 | aarch64-linux-gnu-g++ -fPIC -shared -Wl,-soname,libfuga.so -o libfuga.so fuga.cc libhoge.so 5 | LD_LIBRARY_PATH=. aarch64-linux-gnu-g++ -o main main.cc libfuga.so libhoge.so -pthread 6 | 7 | mv libfuga.so libfuga.so.original 8 | GLOG_log_dir=. LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libfuga.so.original -o libfuga.so.soldout --section-headers --custom-library-path /usr/aarch64-linux-gnu/lib 9 | ln -sf libfuga.so.soldout libfuga.so 10 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++/.gitignore: -------------------------------------------------------------------------------- 1 | libfuga.so 2 | libfuga.so.original 3 | libfuga.so.soldout 4 | libhoge.so 5 | main 6 | sold.* 7 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++/fuga.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void thread_proc(); 4 | 5 | void fuga() { 6 | std::thread t1(thread_proc); 7 | std::thread t2(thread_proc); 8 | std::thread t3(thread_proc); 9 | 10 | t1.join(); 11 | t2.join(); 12 | t3.join(); 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++/hoge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | std::once_flag once; 6 | 7 | void init() { 8 | std::cout << "initialize" << std::endl; 9 | } 10 | 11 | void thread_proc() { 12 | std::call_once(once, init); 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++/main.cc: -------------------------------------------------------------------------------- 1 | void fuga(); 2 | 3 | int main() { 4 | fuga(); 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/call_once-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | g++ -fPIC -shared -Wl,-soname,libhoge.so -o libhoge.so hoge.cc 4 | g++ -fPIC -shared -Wl,-soname,libfuga.so -o libfuga.so fuga.cc libhoge.so 5 | LD_LIBRARY_PATH=. g++ -o main main.cc libfuga.so -pthread 6 | 7 | mv libfuga.so libfuga.so.original 8 | GLOG_log_dir=. LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libfuga.so.original -o libfuga.so.soldout --section-headers 9 | ln -sf libfuga.so.soldout libfuga.so 10 | LD_LIBRARY_PATH=. ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/answer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/delete-unused-PT_DYNAMIC/answer/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/base.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_i = 3; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/base2.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_j = 100; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/base2.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_j; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | 7 | int return_tls_j() { 8 | return thread_local_j; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/lib.h: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | #include "base2.h" 3 | 4 | int return_tls_i(); 5 | int return_tls_j(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("i = %d\n", return_tls_i()); 6 | printf("j = %d\n", return_tls_j()); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/delete-unused-PT_DYNAMIC/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/sold_out/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/delete-unused-PT_DYNAMIC/sold_out/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/delete-unused-PT_DYNAMIC/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o base.o base.c 4 | gcc -fPIC -c -o base2.o base2.c 5 | gcc -fPIC -c -o lib.o lib.c 6 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 7 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base2.so -o original/base2.so base2.o 8 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base2.so original/base.so 9 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o answer/lib.so lib.o base2.o base.o 10 | 11 | # Without sold 12 | # LD_LIBRARY_PATH=original gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base2.so original/base.so 13 | # LD_LIBRARY_PATH=original ./main.out 14 | 15 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --delete-unused-DT_STRTAB 16 | 17 | LD_LIBRARY_PATH=sold_out gcc -Wl,--hash-style=gnu -o main.out main.c sold_out/lib.so 18 | LD_LIBRARY_PATH=sold_out ./main.out 19 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | lib.o 2 | lib.so 3 | lib.so.original 4 | lib.so.soldout 5 | main 6 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++-aarch64/lib.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Base { 5 | public: 6 | virtual ~Base() {} 7 | }; 8 | class Sub1 : public Base {}; 9 | class Sub2 : public Base {}; 10 | 11 | void TryDowncast() { 12 | Base* base = new Sub1; 13 | Sub2* sub2 = dynamic_cast(base); 14 | if (sub2 == nullptr) { 15 | std::cout << "Downcast failed" << std::endl; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | void TryDowncast(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int main() { 4 | TryDowncast(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o lib.o lib.cc 4 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | echo ----------- Use sold ----------- 13 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 14 | 15 | # Use original 16 | ln -sf lib.so.original lib.so 17 | echo ----------- Use original ----------- 18 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 19 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++/.gitignore: -------------------------------------------------------------------------------- 1 | lib.o 2 | lib.so 3 | lib.so.original 4 | lib.so.soldout 5 | main 6 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++/lib.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Base { 5 | public: 6 | virtual ~Base() {} 7 | }; 8 | class Sub1 : public Base {}; 9 | class Sub2 : public Base {}; 10 | 11 | void TryDowncast() { 12 | Base* base = new Sub1; 13 | Sub2* sub2 = dynamic_cast(base); 14 | if (sub2 == nullptr) { 15 | std::cout << "Downcast failed" << std::endl; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++/lib.h: -------------------------------------------------------------------------------- 1 | void TryDowncast(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int main() { 4 | TryDowncast(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/dynamic_cast-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o lib.o lib.cc 4 | g++ -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | g++ -Wl,--hash-style=gnu -o main main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | echo ----------- Use sold ----------- 13 | LD_LIBRARY_PATH=. ./main 14 | 15 | # Use original 16 | ln -sf lib.so.original lib.so 17 | echo ----------- Use original ----------- 18 | LD_LIBRARY_PATH=. ./main 19 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++-aarch64/fuga.cc: -------------------------------------------------------------------------------- 1 | #include "fuga.h" 2 | 3 | void throw_exception_fuga() { 4 | throw std::runtime_error("fuga"); 5 | } 6 | 7 | void catch_exception_fuga() { 8 | try { 9 | throw_exception_fuga(); 10 | } catch (std::exception& e) { 11 | std::cout << e.what() << std::endl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++-aarch64/fuga.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void throw_exception_fuga(); 6 | void catch_exception_fuga(); 7 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++-aarch64/hoge.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | #include "fuga.h" 3 | 4 | void throw_exception_hoge() { 5 | throw std::runtime_error("hoge"); 6 | } 7 | 8 | void catch_exception_hoge() { 9 | try { 10 | throw_exception_hoge(); 11 | } catch (std::exception& e) { 12 | std::cout << e.what() << std::endl; 13 | } 14 | 15 | try { 16 | throw_exception_fuga(); 17 | } catch (std::exception& e) { 18 | std::cout << e.what() << std::endl; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++-aarch64/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void throw_exception_hoge(); 6 | void catch_exception_hoge(); 7 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int main() { 4 | std::cout << "catch_exception" << std::endl; 5 | catch_exception_hoge(); 6 | 7 | std::cout << "throw_exception" << std::endl; 8 | try { 9 | throw_exception_hoge(); 10 | } catch (std::exception& e) { 11 | std::cout << e.what() << std::endl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -shared -o libfuga.so -Wl,-soname,libfuga.so fuga.cc 4 | aarch64-linux-gnu-g++ -fPIC -shared -o libhoge.so.original -Wl,-soname,libhoge.so hoge.cc libfuga.so 5 | aarch64-linux-gnu-g++ main.cc -o main.out libhoge.so.original libfuga.so 6 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 7 | 8 | # Use sold 9 | ln -sf libhoge.so.soldout libhoge.so 10 | # Use original 11 | # ln -sf libhoge.so.original libhoge.so 12 | 13 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++/fuga.cc: -------------------------------------------------------------------------------- 1 | #include "fuga.h" 2 | 3 | void throw_exception_fuga() { 4 | throw std::runtime_error("fuga"); 5 | } 6 | 7 | void catch_exception_fuga() { 8 | try { 9 | throw_exception_fuga(); 10 | } catch (std::exception& e) { 11 | std::cout << e.what() << std::endl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++/fuga.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void throw_exception_fuga(); 6 | void catch_exception_fuga(); 7 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++/hoge.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | #include "fuga.h" 3 | 4 | void throw_exception_hoge() { 5 | throw std::runtime_error("hoge"); 6 | } 7 | 8 | void catch_exception_hoge() { 9 | try { 10 | throw_exception_hoge(); 11 | } catch (std::exception& e) { 12 | std::cout << e.what() << std::endl; 13 | } 14 | 15 | try { 16 | throw_exception_fuga(); 17 | } catch (std::exception& e) { 18 | std::cout << e.what() << std::endl; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void throw_exception_hoge(); 6 | void catch_exception_hoge(); 7 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int main() { 4 | std::cout << "catch_exception" << std::endl; 5 | catch_exception_hoge(); 6 | 7 | std::cout << "throw_exception" << std::endl; 8 | try { 9 | throw_exception_hoge(); 10 | } catch (std::exception& e) { 11 | std::cout << e.what() << std::endl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -shared -o libfuga.so -Wl,-soname,libfuga.so fuga.cc 4 | g++ -fPIC -shared -o libhoge.so.original -Wl,-soname,libhoge.so hoge.cc libfuga.so 5 | g++ main.cc -o main.out libhoge.so.original libfuga.so 6 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers --check-output 7 | 8 | # Use sold 9 | ln -sf libhoge.so.soldout libhoge.so 10 | # Use original 11 | # ln -sf libhoge.so.original libhoge.so 12 | 13 | LD_LIBRARY_PATH=. ./main.out 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-str-g++-aarch64/fuga.cc: -------------------------------------------------------------------------------- 1 | #include "fuga.h" 2 | 3 | void throw_exception_fuga() { 4 | std::cout << "QWERHOGETYUIOPASDFGHJKLZXCVBNM" << std::endl; 5 | throw std::runtime_error("fuga"); 6 | } 7 | 8 | void catch_exception_fuga() { 9 | try { 10 | std::cout << "QWERTYUIOPASDFGHJKLZXCVBNM" << std::endl; 11 | throw_exception_fuga(); 12 | } catch (std::exception& e) { 13 | std::cout << "QWERHOGETYUIOPASDFGHJKLZXCVBNM" << std::endl; 14 | std::cout << e.what() << std::endl; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-str-g++-aarch64/fuga.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void throw_exception_fuga(); 6 | void catch_exception_fuga(); 7 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-str-g++-aarch64/hoge.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | #include "fuga.h" 3 | 4 | void throw_exception_hoge() { 5 | throw std::runtime_error("hoge"); 6 | } 7 | 8 | void catch_exception_hoge() { 9 | try { 10 | std::cout << "QWERTYUIOPASDFGHJKLZXCVBNM" << std::endl; 11 | throw_exception_hoge(); 12 | } catch (std::exception& e) { 13 | std::cout << e.what() << std::endl; 14 | } 15 | 16 | try { 17 | std::cout << "QWERTYUIOPASDFGHJKLZXCVBNM" << std::endl; 18 | throw_exception_fuga(); 19 | } catch (std::exception& e) { 20 | std::cout << e.what() << std::endl; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-str-g++-aarch64/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void throw_exception_hoge(); 6 | void catch_exception_hoge(); 7 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-str-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int main() { 4 | std::cout << "catch_exception" << std::endl; 5 | catch_exception_hoge(); 6 | 7 | std::cout << "throw_exception" << std::endl; 8 | try { 9 | throw_exception_hoge(); 10 | } catch (std::exception& e) { 11 | std::cout << e.what() << std::endl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exception-str-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -shared -o libfuga.so -Wl,-soname,libfuga.so fuga.cc 4 | aarch64-linux-gnu-g++ -fPIC -shared -o libhoge.so.original -Wl,-soname,libhoge.so hoge.cc libfuga.so 5 | aarch64-linux-gnu-g++ main.cc -o main libhoge.so.original libfuga.so 6 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 7 | 8 | # Use sold 9 | ln -sf libhoge.so.soldout libhoge.so 10 | # Use original 11 | # ln -sf libhoge.so.original libhoge.so 12 | 13 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 14 | -------------------------------------------------------------------------------- /feature_unit_tests/exe.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "lib.h" 5 | 6 | static int g_init; 7 | __attribute__((constructor)) static void init() { 8 | puts("Constructor in exe"); 9 | g_init = 42; 10 | } 11 | 12 | __attribute__((destructor)) static void quit() { 13 | puts("Destructor in exe"); 14 | } 15 | 16 | int main(int argc, char** argv) { 17 | int is_exe = (argc == 1); 18 | 19 | puts("Start main"); 20 | if (lib_add_42_via_base(10) != 52) abort(); 21 | if (in_both_lib_and_base() != 100) abort(); 22 | 23 | // fprintf(stderr, "Use stderr from main\n"); 24 | lib_use_stderr(); 25 | 26 | if (g_init != 42) abort(); 27 | // TODO(hamaji): Fix .init_array for the main binary. 28 | if (!is_exe) { 29 | if (lib_init_value() != 43) abort(); 30 | if (lib_base_init_value() != 44) abort(); 31 | puts("Constructors are OK"); 32 | } 33 | 34 | if (lib_base_global() != 98) abort(); 35 | 36 | if (lib_base_vf() != 1234) abort(); 37 | 38 | if (lib_base_thread_var() != 121) abort(); 39 | if (lib_base_thread_var_reloc() != 42) abort(); 40 | if (lib_thread_var() != 111) abort(); 41 | if (lib_thread_var_reloc() != 32) abort(); 42 | 43 | puts("OK"); 44 | } 45 | -------------------------------------------------------------------------------- /feature_unit_tests/extern/hoge.c: -------------------------------------------------------------------------------- 1 | int hoge_var = 0xdeadbeef; 2 | 3 | void inc() { 4 | hoge_var++; 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/extern/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int hoge_var; 5 | int fuga_var = 0xaaaaaaaa; 6 | void inc(); 7 | 8 | int main() { 9 | printf("hoge_var = %x &hoge_var = %x\n", hoge_var, &hoge_var); 10 | printf("hoge_var = %x &hoge_var = %x\n", *((&hoge_var - 1)), (&hoge_var - 1)); 11 | printf("hoge_var = %x &hoge_var = %x\n", *((&hoge_var - 2)), (&hoge_var - 2)); 12 | assert(hoge_var == 0xdeadbeef); 13 | inc(); 14 | printf("hoge_var = %x &hoge_var = %x\n", hoge_var, &hoge_var); 15 | assert(hoge_var == 0xdeadbeef + 1); 16 | hoge_var = 3; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /feature_unit_tests/extern/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | pushd ~/sold/build 4 | ninja 5 | popd 6 | gcc hoge.c -fPIC -shared -Wl,-soname,libhoge.so -o libhoge.so 7 | gcc main.c libhoge.so -rdynamic -export-dynamic 8 | # GLOG_logtostderr=1 ../../build/print_dynsymtab libhoge.so 9 | 10 | GLOG_log_dir=. LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold a.out -o a.out.soldout --section-headers 11 | GLOG_logtostderr=1 LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold a.out -o a.out.soldout --section-headers 12 | ./a.out.soldout 13 | -------------------------------------------------------------------------------- /feature_unit_tests/global-write-aarch64/hoge.c: -------------------------------------------------------------------------------- 1 | int hoge; 2 | __thread int hoge_th; 3 | -------------------------------------------------------------------------------- /feature_unit_tests/global-write-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern int hoge; 4 | 5 | int main() { 6 | hoge = 10; 7 | printf("hoge = %d\n", hoge); 8 | } 9 | -------------------------------------------------------------------------------- /feature_unit_tests/global-write-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | aarch64-linux-gnu-gcc -fPIC -shared -o libhoge.so -Wl,-soname,libhoge.so hoge.c 4 | aarch64-linux-gnu-gcc -o main main.c libhoge.so 5 | 6 | mv libhoge.so libhoge.so.original 7 | $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 8 | ln -sf libhoge.so.soldout libhoge.so 9 | 10 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | hello.out 3 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-g++-aarch64/hello.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello World!" << std::endl; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | aarch64-linux-gnu-g++ hello.cc -o hello 4 | $(git rev-parse --show-toplevel)/build/sold hello -o hello.out --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 5 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./hello.out 6 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-g++/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | hello.out 3 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-g++/hello.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello World!" << std::endl; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | g++ hello.cc -o hello 4 | $(git rev-parse --show-toplevel)/build/sold hello -o hello.out --section-headers --check-output 5 | ./hello.out 6 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-gcc-aarch64/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | puts("Hello World!\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | aarch64-linux-gnu-gcc hello.c -o hello 4 | $(git rev-parse --show-toplevel)/build/sold hello -o hello.out --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 5 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./hello.out 6 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-gcc/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | hello.out 3 | test.sh 4 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-gcc/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | puts("Hello World!\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/hello-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | gcc hello.c -o hello 4 | $(git rev-parse --show-toplevel)/build/sold hello -o hello.out --section-headers --check-output 5 | ./hello.out 6 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | hello.out 3 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++-aarch64/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void B::Speak() { 4 | std::cout << "I am B." << std::endl; 5 | } 6 | 7 | void C::Speak() { 8 | std::cout << "I am C." << std::endl; 9 | } 10 | 11 | void JustHelloFun() { 12 | std::cout << "Hello from lib" << std::endl; 13 | 14 | B* bptr = new B; 15 | C* cptr = new C; 16 | 17 | A* aptr = bptr; 18 | aptr->Speak(); 19 | aptr = cptr; 20 | aptr->Speak(); 21 | 22 | delete bptr; 23 | delete cptr; 24 | } 25 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class A { 4 | public: 5 | virtual void Speak(){}; 6 | }; 7 | 8 | class B : public A { 9 | public: 10 | void Speak() override; 11 | int a; 12 | int b; 13 | }; 14 | 15 | class C : public A { 16 | public: 17 | void Speak() override; 18 | }; 19 | 20 | void JustHelloFun(); 21 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | #include 5 | 6 | void JustHelloFunMain() { 7 | std::cout << "Hello from main" << std::endl; 8 | 9 | B* bptr = new B; 10 | C* cptr = new C; 11 | 12 | A* aptr = bptr; 13 | aptr->Speak(); 14 | aptr = cptr; 15 | aptr->Speak(); 16 | 17 | delete bptr; 18 | delete cptr; 19 | 20 | std::unique_ptr buptr = std::make_unique(); 21 | std::unique_ptr cuptr = std::make_unique(); 22 | buptr->Speak(); 23 | cuptr->Speak(); 24 | 25 | std::shared_ptr bsptr = std::make_unique(); 26 | std::shared_ptr csptr = std::make_unique(); 27 | bsptr->Speak(); 28 | csptr->Speak(); 29 | } 30 | 31 | void CallSpeak(A* aptr) { 32 | aptr->Speak(); 33 | } 34 | 35 | int main() { 36 | std::cout << "Before JustHelloFun" << std::endl; 37 | JustHelloFun(); 38 | std::cout << "After JustHelloFun\n" << std::endl; 39 | 40 | std::cout << "Before JustHelloFunMain" << std::endl; 41 | JustHelloFunMain(); 42 | std::cout << "After JustHelloFunMain\n" << std::endl; 43 | 44 | std::cout << "Before constructors" << std::endl; 45 | B b; 46 | C c; 47 | std::cout << "After constructors\n" << std::endl; 48 | 49 | std::cout << "Before member functions" << std::endl; 50 | b.Speak(); 51 | c.Speak(); 52 | std::cout << "After member functions\n" << std::endl; 53 | 54 | std::cout << "Before CallSpeak" << std::endl; 55 | CallSpeak(&b); 56 | CallSpeak(&c); 57 | std::cout << "After CallSpeak" << std::endl; 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o lib.o lib.cc 4 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main.out main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | hello.out 3 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void B::Speak() { 4 | std::cout << "I am B." << std::endl; 5 | } 6 | 7 | void C::Speak() { 8 | std::cout << "I am C." << std::endl; 9 | } 10 | 11 | void JustHelloFun() { 12 | std::cout << "Hello from lib" << std::endl; 13 | 14 | B* bptr = new B; 15 | C* cptr = new C; 16 | 17 | A* aptr = bptr; 18 | aptr->Speak(); 19 | aptr = cptr; 20 | aptr->Speak(); 21 | 22 | delete bptr; 23 | delete cptr; 24 | } 25 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++/lib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class A { 4 | public: 5 | virtual void Speak(){}; 6 | }; 7 | 8 | class B : public A { 9 | public: 10 | void Speak() override; 11 | int a; 12 | int b; 13 | }; 14 | 15 | class C : public A { 16 | public: 17 | void Speak() override; 18 | }; 19 | 20 | void JustHelloFun(); 21 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | #include 5 | 6 | void JustHelloFunMain() { 7 | std::cout << "Hello from main" << std::endl; 8 | 9 | B* bptr = new B; 10 | C* cptr = new C; 11 | 12 | A* aptr = bptr; 13 | aptr->Speak(); 14 | aptr = cptr; 15 | aptr->Speak(); 16 | 17 | delete bptr; 18 | delete cptr; 19 | 20 | std::unique_ptr buptr = std::make_unique(); 21 | std::unique_ptr cuptr = std::make_unique(); 22 | buptr->Speak(); 23 | cuptr->Speak(); 24 | 25 | std::shared_ptr bsptr = std::make_unique(); 26 | std::shared_ptr csptr = std::make_unique(); 27 | bsptr->Speak(); 28 | csptr->Speak(); 29 | } 30 | 31 | void CallSpeak(A* aptr) { 32 | aptr->Speak(); 33 | } 34 | 35 | int main() { 36 | std::cout << "Before JustHelloFun" << std::endl; 37 | JustHelloFun(); 38 | std::cout << "After JustHelloFun\n" << std::endl; 39 | 40 | std::cout << "Before JustHelloFunMain" << std::endl; 41 | JustHelloFunMain(); 42 | std::cout << "After JustHelloFunMain\n" << std::endl; 43 | 44 | std::cout << "Before constructors" << std::endl; 45 | B b; 46 | C c; 47 | std::cout << "After constructors\n" << std::endl; 48 | 49 | std::cout << "Before member functions" << std::endl; 50 | b.Speak(); 51 | c.Speak(); 52 | std::cout << "After member functions\n" << std::endl; 53 | 54 | std::cout << "Before CallSpeak" << std::endl; 55 | CallSpeak(&b); 56 | CallSpeak(&c); 57 | std::cout << "After CallSpeak" << std::endl; 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /feature_unit_tests/inheritance-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o lib.o lib.cc 4 | g++ -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | g++ -Wl,--hash-style=gnu -o main.out main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. ./main.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-g++-aarch64/return.cc: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 0; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | aarch64-linux-gnu-g++ return.cc -o return.out 4 | $(git rev-parse --show-toplevel)/build/sold return.out -o return.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 5 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./return.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-g++/return.cc: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 0; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | g++ return.cc -o return.out 4 | $(git rev-parse --show-toplevel)/build/sold return.out -o return.soldout --section-headers --check-output 5 | ./return.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-gcc-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | return 2 | return.out 3 | return.soldout 4 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-gcc-aarch64/return.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 0; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | aarch64-linux-gnu-gcc return.c -o return.out 4 | $(git rev-parse --show-toplevel)/build/sold return.out -o return.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 5 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./return.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-gcc/.gitignore: -------------------------------------------------------------------------------- 1 | return.c 2 | test.sh 3 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-gcc/return.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 0; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/just-return-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | gcc return.c -o return.out 4 | $(git rev-parse --show-toplevel)/build/sold return.out -o return.soldout --section-headers --check-output 5 | ./return.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | base.so 2 | main 3 | mprotect_check.so 4 | mprotect_check.so.original 5 | mprotect_check.so.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/base.c: -------------------------------------------------------------------------------- 1 | 2 | int func(int a, int b) { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/base.h: -------------------------------------------------------------------------------- 1 | int func(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include "mprotect_check.h" 2 | 3 | int main() { 4 | check(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/mprotect_check.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "base.h" 4 | 5 | void check() { 6 | int x = func(1, 2); 7 | char str[1024]; 8 | FILE* fp = fopen("/proc/self/maps", "r"); 9 | while ((fgets(str, 256, fp)) != NULL) { 10 | printf("%s", str); 11 | } 12 | fclose(fp); 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/mprotect_check.h: -------------------------------------------------------------------------------- 1 | void check(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | aarch64-linux-gnu-gcc -shared -fPIC base.c -o base.so -Wl,-soname,base.so 4 | aarch64-linux-gnu-gcc -shared -fPIC mprotect_check.c base.so -o mprotect_check.so 5 | aarch64-linux-gnu-gcc main.c mprotect_check.so -o main 6 | 7 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i mprotect_check.so -o mprotect_check.so.soldout --custom-library-path /usr/aarch64-linux-gnu/lib 8 | mv mprotect_check.so mprotect_check.so.original 9 | ln -sf mprotect_check.so.soldout mprotect_check.so 10 | # ln -sf mprotect_check.so.original mprotect_check.so 11 | 12 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 13 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/.gitignore: -------------------------------------------------------------------------------- 1 | base.so 2 | main 3 | mprotect_check.so 4 | mprotect_check.so.original 5 | mprotect_check.so.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/base.c: -------------------------------------------------------------------------------- 1 | 2 | int func(int a, int b) { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/base.h: -------------------------------------------------------------------------------- 1 | int func(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/main.c: -------------------------------------------------------------------------------- 1 | #include "mprotect_check.h" 2 | 3 | int main() { 4 | check(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/mprotect_check.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "base.h" 4 | 5 | void check() { 6 | int x = func(1, 2); 7 | char str[1024]; 8 | FILE* fp = fopen("/proc/self/maps", "r"); 9 | while ((fgets(str, 256, fp)) != NULL) { 10 | printf("%s", str); 11 | } 12 | fclose(fp); 13 | } 14 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/mprotect_check.h: -------------------------------------------------------------------------------- 1 | void check(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/mprotect/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | gcc -shared -fPIC base.c -o base.so -Wl,-soname,base.so 4 | gcc -shared -fPIC mprotect_check.c base.so -o mprotect_check.so 5 | gcc main.c mprotect_check.so -o main 6 | 7 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i mprotect_check.so -o mprotect_check.so.soldout 8 | mv mprotect_check.so mprotect_check.so.original 9 | ln -sf mprotect_check.so.soldout mprotect_check.so 10 | # ln -sf mprotect_check.so.original mprotect_check.so 11 | 12 | LD_LIBRARY_PATH=. ./main 13 | -------------------------------------------------------------------------------- /feature_unit_tests/renamer/.gitignore: -------------------------------------------------------------------------------- 1 | libfugafuga.so 2 | libhoge_original.so 3 | libhoge_renamed.so 4 | libhoge.so 5 | use_fugafuga 6 | -------------------------------------------------------------------------------- /feature_unit_tests/renamer/fugafuga.c: -------------------------------------------------------------------------------- 1 | int fugafuga(int a, int b) { 2 | return a - b; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/renamer/hoge.c: -------------------------------------------------------------------------------- 1 | int hoge(int a, int b) { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/renamer/mapping: -------------------------------------------------------------------------------- 1 | hoge fugafuga 2 | -------------------------------------------------------------------------------- /feature_unit_tests/renamer/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | gcc -fPIC -fpic -shared -o libhoge_original.so hoge.c -Wl,-soname,libhoge.so 4 | gcc -fPIC -fpic -shared -o libfugafuga.so fugafuga.c -Wl,-soname,libhoge.so 5 | ln -sf libfugafuga.so libhoge.so 6 | gcc -o use_fugafuga use_fugafuga.c libhoge.so 7 | ../../build/renamer libhoge_original.so --output libhoge_renamed.so --rename-mapping-file mapping 8 | ln -sf libhoge_renamed.so libhoge.so 9 | LD_LIBRARY_PATH=. ./use_fugafuga 10 | -------------------------------------------------------------------------------- /feature_unit_tests/renamer/use_fugafuga.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Although `fugafuga` in fugafuga.c is subtraction, `hoge` in hoge.c is 5 | // addition. renamer renames `hoge` to `fugafuga`. 6 | int fugafuga(int a, int b); 7 | 8 | int main() { 9 | int a = fugafuga(1, 2); 10 | assert(a == 3); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /feature_unit_tests/run-all-tests.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -u 2 | 3 | unexpected_failed_tests= 4 | unexpected_succeeded_tests= 5 | 6 | # TODO(akawashiro): extern 7 | for dir in hello-g++ hello-gcc just-return-g++ just-return-gcc simple-lib-g++ simple-lib-gcc version-gcc tls-lib-gcc tls-lib-gcc-without-base tls-multiple-lib-gcc tls-thread-g++ call_once-g++ inheritance-g++ typeid-g++ dynamic_cast-g++ tls-dlopen-gcc static-in-function-g++ static-in-class-g++ tls-multiple-module-g++ exception-g++ stb_gnu_unique_tls setjmp-gcc tls-bss-gcc tls-bss-g++ hello-g++-aarch64 hello-gcc-aarch64 just-return-g++-aarch64 simple-lib-g++-aarch64 simple-lib-gcc-aarch64 version-gcc-aarch64 tls-bss-gcc-aarch64 tls-bss-g++-aarch64 just-return-gcc-aarch64 setjmp-gcc-aarch64 exception-g++-aarch64 typeid-g++-aarch64 inheritance-g++-aarch64 dynamic_cast-g++-aarch64 static-in-class-g++-aarch64 static-in-function-g++-aarch64 tls-lib-gcc-aarch64 stb_gnu_unique_tls-aarch64 tls-multiple-module-g++-aarch64 tls-dlopen-gcc-aarch64 call_once-g++-aarch64 tls-thread-g++-aarch64 tls-lib-gcc-without-base-aarch64 delete-unused-PT_DYNAMIC 8 | do 9 | pushd `pwd` 10 | cd $dir 11 | echo =========== $dir =========== 12 | ./test.sh 13 | if [ "$?" -ne 0 ];then 14 | if [ -z "${unexpected_failed_tests}" ];then 15 | unexpected_failed_tests=${dir} 16 | else 17 | unexpected_failed_tests=${unexpected_failed_tests},${dir} 18 | fi 19 | fi 20 | popd 21 | done 22 | 23 | # TODO(akawashiro): tls-multiple-lib-gcc-aarch64 fails on CI although it succeeds in containers. 24 | # for dir in tls-multiple-lib-gcc-aarch64 25 | # do 26 | # pushd `pwd` 27 | # cd $dir 28 | # echo =========== $dir =========== 29 | # ./test.sh 30 | # if [ "$?" -eq 0 ];then 31 | # if [ -z "${unexpected_succeeded_tests}" ];then 32 | # unexpected_succeeded_tests=${dir} 33 | # else 34 | # unexpected_succeeded_tests=${unexpected_succeeded_tests},${dir} 35 | # fi 36 | # fi 37 | # popd 38 | # done 39 | 40 | echo Unexpected failed tests: ${unexpected_failed_tests} 41 | echo Unexpected succeeded tests: ${unexpected_succeeded_tests} 42 | 43 | if [ -z "${unexpected_failed_tests}" ] 44 | then 45 | exit 0 46 | else 47 | exit 1 48 | fi 49 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libhoge.so 2 | libhoge.so.original 3 | libhoge.so.soldout 4 | main 5 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc-aarch64/hoge.c: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int counter = 0; 4 | jmp_buf buf; 5 | 6 | void setjmp_longjmp_in_function() { 7 | int x = 1; 8 | setjmp(buf); // set the jump position using buf 9 | printf("x = %d\n", x); // Prints a number 10 | x++; 11 | if (x <= 5) longjmp(buf, 1); // Jump to the point located by setjmp 12 | } 13 | 14 | void call_longjmp() { 15 | if (counter <= 5) longjmp(buf, 1); // Jump to the point located by setjmp 16 | } 17 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc-aarch64/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int counter; 5 | extern jmp_buf buf; 6 | 7 | void setjmp_longjmp_in_function(); 8 | void call_longjmp(); 9 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int main() { 4 | printf("call setjmp_longjmp_in_function\n"); 5 | setjmp_longjmp_in_function(); 6 | 7 | printf("call longjmp\n"); 8 | counter = 0; 9 | 10 | setjmp(buf); // set the jump position using buf 11 | printf("counter = %d\n", counter); // Prints a number 12 | counter++; 13 | call_longjmp(); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | aarch64-linux-gnu-gcc -shared -fPIC -Wl,-soname,libhoge.so -o libhoge.so hoge.c 4 | aarch64-linux-gnu-gcc -o main main.c libhoge.so 5 | 6 | mv libhoge.so libhoge.so.original 7 | $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers --custom-library-path /usr/aarch64-linux-gnu/lib 8 | 9 | # Use sold 10 | ln -sf libhoge.so.soldout libhoge.so 11 | 12 | # Use original 13 | # ln -sf lib.so.original lib.so 14 | 15 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 16 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc/.gitignore: -------------------------------------------------------------------------------- 1 | libhoge.so 2 | libhoge.so.original 3 | libhoge.so.soldout 4 | main 5 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc/hoge.c: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int counter = 0; 4 | jmp_buf buf; 5 | 6 | void setjmp_longjmp_in_function() { 7 | int x = 1; 8 | setjmp(buf); // set the jump position using buf 9 | printf("x = %d\n", x); // Prints a number 10 | x++; 11 | if (x <= 5) longjmp(buf, 1); // Jump to the point located by setjmp 12 | } 13 | 14 | void call_longjmp() { 15 | if (counter <= 5) longjmp(buf, 1); // Jump to the point located by setjmp 16 | } 17 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int counter; 5 | extern jmp_buf buf; 6 | 7 | void setjmp_longjmp_in_function(); 8 | void call_longjmp(); 9 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | int main() { 4 | printf("call setjmp_longjmp_in_function\n"); 5 | setjmp_longjmp_in_function(); 6 | 7 | printf("call longjmp\n"); 8 | counter = 0; 9 | 10 | setjmp(buf); // set the jump position using buf 11 | printf("counter = %d\n", counter); // Prints a number 12 | counter++; 13 | call_longjmp(); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /feature_unit_tests/setjmp-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | gcc -shared -fPIC -Wl,-soname,libhoge.so -o libhoge.so hoge.c 4 | gcc -o main main.c libhoge.so 5 | 6 | mv libhoge.so libhoge.so.original 7 | $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers 8 | 9 | # Use sold 10 | ln -sf libhoge.so.soldout libhoge.so 11 | 12 | # Use original 13 | # ln -sf lib.so.original lib.so 14 | 15 | LD_LIBRARY_PATH=. ./main 16 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libmax.o 2 | libmax.so 3 | main 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++-aarch64/libmax.cc: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | return (a < b) ? b : a; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++-aarch64/libmax.h: -------------------------------------------------------------------------------- 1 | int max(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax.h" 3 | 4 | int main() { 5 | std::cout << "max(1,2) = " << max(1, 2) << std::endl; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o libmax.o libmax.cc 4 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -o libmax.so libmax.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main.out main.cc libmax.so 6 | 7 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 8 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.soldout 9 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++/.gitignore: -------------------------------------------------------------------------------- 1 | libmax.o 2 | libmax.so 3 | main 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++/libmax.cc: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | return (a < b) ? b : a; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++/libmax.h: -------------------------------------------------------------------------------- 1 | int max(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax.h" 3 | 4 | int main() { 5 | std::cout << "max(1,2) = " << max(1, 2) << std::endl; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o libmax.o libmax.cc 4 | g++ -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -o libmax.so libmax.o 5 | g++ -Wl,--hash-style=gnu -o main.out main.cc libmax.so 6 | 7 | GLOG_logtostderr=1 LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers --check-output 8 | LD_LIBRARY_PATH=. ./main.soldout 9 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libmax.o 2 | libmax.so 3 | main 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc-aarch64/libmax.c: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | return (a < b) ? b : a; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc-aarch64/libmax.h: -------------------------------------------------------------------------------- 1 | extern int max(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax.h" 3 | 4 | int main() { 5 | printf("max(1,2) = %d\n", max(1, 2)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -fPIC -c -o libmax.o libmax.c 4 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -o libmax.so libmax.o 5 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main.out main.c libmax.so 6 | 7 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 8 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.soldout 9 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc/.gitignore: -------------------------------------------------------------------------------- 1 | libmax.o 2 | libmax.so 3 | main 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc/libmax.c: -------------------------------------------------------------------------------- 1 | int max(int a, int b) { 2 | return (a < b) ? b : a; 3 | } 4 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc/libmax.h: -------------------------------------------------------------------------------- 1 | extern int max(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax.h" 3 | 4 | int main() { 5 | printf("max(1,2) = %d\n", max(1, 2)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/simple-lib-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o libmax.o libmax.c 4 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -o libmax.so libmax.o 5 | gcc -Wl,--hash-style=gnu -o main.out main.c libmax.so 6 | 7 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers --check-output 8 | LD_LIBRARY_PATH=. ./main.soldout 9 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++-aarch64/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int X::i_static = 42; 4 | double X::d_static = 42.00; 5 | 6 | double func() { 7 | X x; 8 | return x.f(); 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | class X { 2 | public: 3 | double f() { return i_static + d_static; } 4 | 5 | private: 6 | static int i_static; 7 | static double d_static; 8 | }; 9 | 10 | double func(); 11 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | 5 | int main() { 6 | std::cout << func() << std::endl; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o lib.o lib.cc 4 | aarch64-linux-gnu-g++ -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main.out main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int X::i_static = 42; 4 | double X::d_static = 42.00; 5 | 6 | double func() { 7 | X x; 8 | return x.f(); 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++/lib.h: -------------------------------------------------------------------------------- 1 | class X { 2 | public: 3 | double f() { return i_static + d_static; } 4 | 5 | private: 6 | static int i_static; 7 | static double d_static; 8 | }; 9 | 10 | double func(); 11 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | 5 | int main() { 6 | std::cout << func() << std::endl; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-class-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o lib.o lib.cc 4 | g++ -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | g++ -Wl,--hash-style=gnu -o main.out main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. ./main.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | lib.so.original 3 | lib.so.soldout 4 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++-aarch64/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int func() { 4 | static int v = 0; 5 | v++; 6 | return v; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | int func(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | 5 | int main() { 6 | std::cout << func() << std::endl; 7 | std::cout << func() << std::endl; 8 | std::cout << func() << std::endl; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o lib.o lib.cc 4 | aarch64-linux-gnu-g++ -lpthread -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main.out main.cc lib.so -lpthread 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++/.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | lib.so.original 3 | lib.so.soldout 4 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int func() { 4 | static int v = 0; 5 | v++; 6 | return v; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++/lib.h: -------------------------------------------------------------------------------- 1 | int func(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | 5 | int main() { 6 | std::cout << func() << std::endl; 7 | std::cout << func() << std::endl; 8 | std::cout << func() << std::endl; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/static-in-function-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o lib.o lib.cc 4 | g++ -lpthread -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | g++ -Wl,--hash-style=gnu -o main.out main.cc lib.so -lpthread 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. ./main.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libunique.so 2 | libunique.so.original 3 | libunique.so.soldout 4 | main 5 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | int fn(); 2 | 3 | int main() { 4 | int x = fn(); 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | aarch64-linux-gnu-g++ -std=c++17 -fPIC -shared unique.cc -o libunique.so 4 | aarch64-linux-gnu-g++ -std=c++17 -o main main.cc libunique.so 5 | 6 | mv libunique.so libunique.so.original 7 | $(git rev-parse --show-toplevel)/build/sold -i libunique.so.original -o libunique.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 8 | ln -sf libunique.so.soldout libunique.so 9 | 10 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls-aarch64/unique.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // OK 4 | // No symbol 5 | // int inline_fn() { 6 | // thread_local int c = 0; 7 | // return c++; 8 | // } 9 | 10 | // OK 11 | // No symbol 12 | // static int inline_fn() { 13 | // thread_local int c = 0; 14 | // return c++; 15 | // } 16 | 17 | // OK 18 | // OBJECT UNIQUE 19 | // Deleted by sold 20 | // inline int inline_fn() { 21 | // static int c = 0; 22 | // return c++; 23 | // } 24 | 25 | // NG 26 | // TLS UNIQUE 27 | inline int inline_fn() { 28 | thread_local int c = 0; 29 | return c++; 30 | } 31 | 32 | // NG 33 | // TLS UNIQUE 34 | // inline thread_local int x = 10; 35 | // int inline_fn() { 36 | // return x; 37 | // } 38 | 39 | // NG 40 | // TLS UNIQUE 41 | // inline int inline_fn() { 42 | // static thread_local int c = 0; 43 | // return c++; 44 | // } 45 | 46 | int fn() { 47 | printf("%d\n", inline_fn()); 48 | printf("%d\n", inline_fn()); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls/.gitignore: -------------------------------------------------------------------------------- 1 | libunique.so 2 | libunique.so.original 3 | libunique.so.soldout 4 | main 5 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls/main.cc: -------------------------------------------------------------------------------- 1 | int fn(); 2 | 3 | int main() { 4 | int x = fn(); 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | g++ -std=c++17 -fPIC -shared unique.cc -o libunique.so 4 | g++ -std=c++17 -o main main.cc libunique.so 5 | 6 | mv libunique.so libunique.so.original 7 | $(git rev-parse --show-toplevel)/build/sold -i libunique.so.original -o libunique.so.soldout --section-headers --check-output 8 | ln -sf libunique.so.soldout libunique.so 9 | 10 | LD_LIBRARY_PATH=. ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/stb_gnu_unique_tls/unique.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // OK 4 | // No symbol 5 | // int inline_fn() { 6 | // thread_local int c = 0; 7 | // return c++; 8 | // } 9 | 10 | // OK 11 | // No symbol 12 | // static int inline_fn() { 13 | // thread_local int c = 0; 14 | // return c++; 15 | // } 16 | 17 | // OK 18 | // OBJECT UNIQUE 19 | // Deleted by sold 20 | // inline int inline_fn() { 21 | // static int c = 0; 22 | // return c++; 23 | // } 24 | 25 | // NG 26 | // TLS UNIQUE 27 | inline int inline_fn() { 28 | thread_local int c = 0; 29 | return c++; 30 | } 31 | 32 | // NG 33 | // TLS UNIQUE 34 | // inline thread_local int x = 10; 35 | // int inline_fn() { 36 | // return x; 37 | // } 38 | 39 | // NG 40 | // TLS UNIQUE 41 | // inline int inline_fn() { 42 | // static thread_local int c = 0; 43 | // return c++; 44 | // } 45 | 46 | int fn() { 47 | printf("%d\n", inline_fn()); 48 | printf("%d\n", inline_fn()); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | thread_local int tls_bss_i; 4 | 5 | int main() { 6 | tls_bss_i = 2; 7 | printf("tls_bss_i = %d\n", tls_bss_i); 8 | printf("tls_bss_i = %d\n", tls_bss_i + 10); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -o main.out main.cc 4 | $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers --custom-library-path /usr/aarch64-linux-gnu/lib 5 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | thread_local int tls_bss_i; 4 | 5 | int main() { 6 | tls_bss_i = 2; 7 | printf("tls_bss_i = %d\n", tls_bss_i); 8 | printf("tls_bss_i = %d\n", tls_bss_i + 10); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -o main.out main.cc 4 | $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers 5 | ./main.soldout 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __thread int tls_bss_i; 4 | 5 | int main() { 6 | tls_bss_i = 2; 7 | printf("tls_bss_i = %d\n", tls_bss_i); 8 | printf("tls_bss_i = %d\n", tls_bss_i + 10); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main.out main.c 4 | 5 | $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers --custom-library-path /usr/aarch64-linux-gnu/lib 6 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.soldout 7 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __thread int tls_bss_i; 4 | 5 | int main() { 6 | tls_bss_i = 2; 7 | printf("tls_bss_i = %d\n", tls_bss_i); 8 | printf("tls_bss_i = %d\n", tls_bss_i + 10); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-bss-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -Wl,--hash-style=gnu -o main.out main.c 4 | 5 | $(git rev-parse --show-toplevel)/build/sold main.out -o main.soldout --section-headers 6 | ./main.soldout 7 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-conflict-aarch64/fuga.cc: -------------------------------------------------------------------------------- 1 | thread_local int fuga; 2 | thread_local int dummy; 3 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-conflict-aarch64/hoge.cc: -------------------------------------------------------------------------------- 1 | extern thread_local int dummy; 2 | extern thread_local int fuga; 3 | thread_local int hoge; 4 | 5 | void fn() { 6 | dummy = 10; 7 | fuga = 10; 8 | } 9 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-conflict-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern thread_local int hoge; 4 | extern thread_local int fuga; 5 | 6 | int main() { 7 | hoge = 42; 8 | fuga = 10; 9 | printf("hoge = %d, fuga = %d\n", hoge, fuga); 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-conflict-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | aarch64-linux-gnu-g++ -fPIC -shared -o libfuga.so -Wl,-soname,libfuga.so fuga.cc 4 | aarch64-linux-gnu-g++ -fPIC -shared -o libhoge.so -Wl,-soname,libhoge.so hoge.cc libfuga.so 5 | aarch64-linux-gnu-g++ -o main main.cc libhoge.so 6 | 7 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 8 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | lib.so 2 | lib.so.original 3 | lib.so.soldout 4 | main 5 | 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc-aarch64/lib.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __thread int tls_with_init_value = 0; 4 | __thread int tls_without_init_value; 5 | 6 | void show_tls_variables() { 7 | tls_with_init_value = 10; 8 | tls_without_init_value = 10; 9 | printf("tls_with_init_value = %d, tls_without_init_value = %d\n", tls_with_init_value, tls_without_init_value); 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | void* handle = dlopen("lib.so", RTLD_LAZY); 6 | if (handle != NULL) { 7 | void (*func)() = (void (*)())dlsym(handle, "show_tls_variables"); 8 | func(); 9 | 10 | int* tls_with_init_value_p = (int*)dlsym(handle, "tls_with_init_value"); 11 | int* tls_without_init_value_p = (int*)dlsym(handle, "tls_without_init_value"); 12 | 13 | printf("*tls_with_init_value_p = %d, *tls_without_init_value_p = %d\n", *tls_with_init_value_p, *tls_without_init_value_p); 14 | 15 | } else { 16 | printf("Cannot open lib.so\n"); 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -fPIC -c -o lib.o lib.c 4 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main main.c -ldl 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 17 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc/.gitignore: -------------------------------------------------------------------------------- 1 | lib.so 2 | lib.so.original 3 | lib.so.soldout 4 | main 5 | 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc/lib.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __thread int tls_with_init_value = 0; 4 | __thread int tls_without_init_value; 5 | 6 | void show_tls_variables() { 7 | tls_with_init_value = 10; 8 | tls_without_init_value = 10; 9 | printf("tls_with_init_value = %d, tls_without_init_value = %d\n", tls_with_init_value, tls_without_init_value); 10 | } 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | void* handle = dlopen("lib.so", RTLD_LAZY); 6 | if (handle != NULL) { 7 | void (*func)() = (void (*)())dlsym(handle, "show_tls_variables"); 8 | func(); 9 | 10 | int* tls_with_init_value_p = (int*)dlsym(handle, "tls_with_init_value"); 11 | int* tls_without_init_value_p = (int*)dlsym(handle, "tls_without_init_value"); 12 | 13 | printf("*tls_with_init_value_p = %d, *tls_without_init_value_p = %d\n", *tls_with_init_value_p, *tls_without_init_value_p); 14 | 15 | } else { 16 | printf("Cannot open lib.so\n"); 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-dlopen-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o lib.o lib.c 4 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | gcc -Wl,--hash-style=gnu -o main main.c -ldl 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. ./main 17 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // thread_local int tls_bss_i; 5 | static int global_x; 6 | thread_local int tls_data_j = 3; 7 | 8 | int main() { 9 | // tls_bss_i = 2; 10 | // printf("tls_bss_i = %d\n", tls_bss_i); 11 | global_x = 2; 12 | printf("global_x = %d\n", global_x); 13 | printf("tls_data_j = %d\n", tls_data_j); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main main.c 4 | 5 | $(git rev-parse --show-toplevel)/build/sold main -o main.out --section-headers --custom-library-path /usr/aarch64-linux-gnu/lib 6 | qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 7 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // thread_local int tls_bss_i; 5 | static int global_x; 6 | thread_local int tls_data_j = 3; 7 | 8 | int main() { 9 | // tls_bss_i = 2; 10 | // printf("tls_bss_i = %d\n", tls_bss_i); 11 | global_x = 2; 12 | printf("global_x = %d\n", global_x); 13 | printf("tls_data_j = %d\n", tls_data_j); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -Wl,--hash-style=gnu -o main main.c 4 | 5 | $(git rev-parse --show-toplevel)/build/sold main -o main.out --section-headers 6 | ./main.out 7 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/answer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-aarch64/answer/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/base.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_i = 3; 2 | __thread int thread_local_j; 3 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | extern __thread int thread_local_j; 3 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | int return_tls_i(); 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("i = %d\n", return_tls_i()); 6 | thread_local_j = 3; 7 | printf("j = %d\n", thread_local_j); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-aarch64/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/sold_out/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-aarch64/sold_out/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -fPIC -c -o lib.o lib.c 4 | aarch64-linux-gnu-gcc -fPIC -c -o base.o base.c 5 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 6 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base.so 7 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o answer/lib.so lib.o base.o 8 | 9 | # Without sold 10 | # LD_LIBRARY_PATH=original gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base.so 11 | # LD_LIBRARY_PATH=original ./main.out 12 | 13 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --check-output aarch64-linux-gnu-gcc 14 | 15 | LD_LIBRARY_PATH=sold_out aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main.out main.c sold_out/lib.so 16 | LD_LIBRARY_PATH=sold_out qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 17 | 18 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/base.c: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | __thread int thread_local_i = 3; 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/lib.c: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | int return_tls_i(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("j = %d\n", return_tls_i()); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-without-base-aarch64/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/sold_out/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-without-base-aarch64/sold_out/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -fPIC -c -o lib.o lib.c 4 | aarch64-linux-gnu-gcc -fPIC -c -o base.o base.c 5 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 6 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base.so 7 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base.so 8 | 9 | cp original/base.so sold_out/base.so 10 | 11 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --exclude-so base.so --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 12 | LD_LIBRARY_PATH=sold_out qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 13 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/base.c: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | __thread int thread_local_i = 3; 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/lib.c: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/lib.h: -------------------------------------------------------------------------------- 1 | int return_tls_i(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("j = %d\n", return_tls_i()); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-without-base/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/sold_out/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc-without-base/sold_out/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc-without-base/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o lib.o lib.c 4 | gcc -fPIC -c -o base.o base.c 5 | 6 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 7 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base.so 8 | 9 | gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base.so 10 | 11 | cp original/base.so sold_out/base.so 12 | 13 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --exclude-so base.so --check-output 14 | LD_LIBRARY_PATH=sold_out ./main.out 15 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/answer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc/answer/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/base.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_i = 3; 2 | __thread int thread_local_j; 3 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | extern __thread int thread_local_j; 3 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/lib.h: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | int return_tls_i(); 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("i = %d\n", return_tls_i()); 6 | thread_local_j = 3; 7 | printf("j = %d\n", thread_local_j); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/sold_out/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-lib-gcc/sold_out/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-lib-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o lib.o lib.c 4 | gcc -fPIC -c -o base.o base.c 5 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 6 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base.so 7 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o answer/lib.so lib.o base.o 8 | 9 | # Without sold 10 | # LD_LIBRARY_PATH=original gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base.so 11 | # LD_LIBRARY_PATH=original ./main.out 12 | 13 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --check-output 14 | 15 | LD_LIBRARY_PATH=sold_out gcc -Wl,--hash-style=gnu -o main.out main.c sold_out/lib.so 16 | LD_LIBRARY_PATH=sold_out ./main.out 17 | 18 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/answer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-multiple-lib-gcc-aarch64/answer/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/base.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_i = 3; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/base2.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_j = 100; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/base2.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_j; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | 7 | int return_tls_j() { 8 | return thread_local_j; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | #include "base2.h" 3 | 4 | int return_tls_i(); 5 | int return_tls_j(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("i = %d\n", return_tls_i()); 6 | printf("j = %d\n", return_tls_j()); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-multiple-lib-gcc-aarch64/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -fPIC -c -o base.o base.c 4 | aarch64-linux-gnu-gcc -fPIC -c -o base2.o base2.c 5 | aarch64-linux-gnu-gcc -fPIC -c -o lib.o lib.c 6 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 7 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base2.so -o original/base2.so base2.o 8 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base2.so original/base.so 9 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o answer/lib.so lib.o base2.o base.o 10 | 11 | # Without sold 12 | # LD_LIBRARY_PATH=original gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base2.so original/base.so 13 | # LD_LIBRARY_PATH=original ./main.out 14 | 15 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 16 | 17 | LD_LIBRARY_PATH=sold_out aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o main.out main.c sold_out/lib.so 18 | LD_LIBRARY_PATH=sold_out qemu-aarch64 -L /usr/aarch64-linux-gnu ./main.out 19 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/answer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-multiple-lib-gcc/answer/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/base.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_i = 3; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/base.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_i; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/base2.c: -------------------------------------------------------------------------------- 1 | __thread int thread_local_j = 100; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/base2.h: -------------------------------------------------------------------------------- 1 | extern __thread int thread_local_j; 2 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int return_tls_i() { 4 | return thread_local_i; 5 | } 6 | 7 | int return_tls_j() { 8 | return thread_local_j; 9 | } 10 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/lib.h: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | #include "base2.h" 3 | 4 | int return_tls_i(); 5 | int return_tls_j(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "lib.h" 3 | 4 | int main() { 5 | printf("i = %d\n", return_tls_i()); 6 | printf("j = %d\n", return_tls_j()); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/original/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-multiple-lib-gcc/original/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/sold_out/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akawashiro/sold/3ef99b72cf319481269e2e9adc473ef2ea8dcabe/feature_unit_tests/tls-multiple-lib-gcc/sold_out/.gitkeep -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-lib-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o base.o base.c 4 | gcc -fPIC -c -o base2.o base2.c 5 | gcc -fPIC -c -o lib.o lib.c 6 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base.so -o original/base.so base.o 7 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,base2.so -o original/base2.so base2.o 8 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o original/lib.so lib.o original/base2.so original/base.so 9 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o answer/lib.so lib.o base2.o base.o 10 | 11 | # Without sold 12 | # LD_LIBRARY_PATH=original gcc -Wl,--hash-style=gnu -o main.out main.c original/lib.so original/base2.so original/base.so 13 | # LD_LIBRARY_PATH=original ./main.out 14 | 15 | LD_LIBRARY_PATH=original $(git rev-parse --show-toplevel)/build/sold original/lib.so -o sold_out/lib.so --section-headers --check-output 16 | 17 | LD_LIBRARY_PATH=sold_out gcc -Wl,--hash-style=gnu -o main.out main.c sold_out/lib.so 18 | LD_LIBRARY_PATH=sold_out ./main.out 19 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libfugahoge.so.original 2 | libfugahoge.so.soldout 3 | libfuga.so 4 | libhoge.so 5 | main 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/fuga.cc: -------------------------------------------------------------------------------- 1 | #include "fuga.h" 2 | 3 | namespace { 4 | thread_local uint64_t fuga_data = 0xDEADBEEFDEADBEEF; 5 | thread_local uint64_t fuga_bss; 6 | } // namespace 7 | 8 | uint64_t get_fuga_data() { 9 | return fuga_data; 10 | } 11 | 12 | uint64_t get_fuga_bss() { 13 | return fuga_bss; 14 | } 15 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/fuga.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void show_fuga(); 4 | uint64_t get_fuga_data(); 5 | uint64_t get_fuga_bss(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/fugahoge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "fuga.h" 6 | #include "hoge.h" 7 | 8 | extern "C" void show_fuga_hoge() { 9 | uint64_t fuga_data = get_fuga_data(); 10 | uint64_t fuga_bss = get_fuga_bss(); 11 | uint64_t hoge_data = get_hoge_data(); 12 | uint64_t hoge_bss = get_hoge_bss(); 13 | 14 | std::cout << std::hex << "fuga_data = " << fuga_data << ", fuga_bss = " << fuga_bss << std::endl 15 | << "hoge_data = " << hoge_data << ", hoge_bss = " << hoge_bss << std::endl; 16 | 17 | assert(fuga_data == 0xDEADBEEFDEADBEEF && fuga_bss == 0 && hoge_data == 0xABCDEFABCDEFABCD && hoge_bss == 0); 18 | } 19 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/hoge.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | namespace { 4 | thread_local uint64_t hoge_data = 0xABCDEFABCDEFABCD; 5 | thread_local uint64_t hoge_bss; 6 | } // namespace 7 | 8 | uint64_t get_hoge_data() { 9 | return hoge_data; 10 | } 11 | 12 | uint64_t get_hoge_bss() { 13 | return hoge_bss; 14 | } 15 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void show_hoge(); 4 | uint64_t get_hoge_data(); 5 | uint64_t get_hoge_bss(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main() { 6 | std::cout << "---------- libfugahoge.so.original ----------" << std::endl; 7 | void* handle = dlopen("./libfugahoge.so.original", RTLD_LAZY); 8 | if (handle == NULL) { 9 | std::cout << "Cannot find libfugahoge.so.original" << std::endl; 10 | return 0; 11 | } 12 | int (*show_fuga_hoge)() = (int (*)())dlsym(handle, "show_fuga_hoge"); 13 | if (show_fuga_hoge == NULL) { 14 | std::cout << "Cannot find show_fuga_hoge" << std::endl; 15 | return 0; 16 | } 17 | show_fuga_hoge(); 18 | 19 | std::cout << "---------- libfugahoge.so.soldout ----------" << std::endl; 20 | handle = dlopen("./libfugahoge.so.soldout", RTLD_LAZY); 21 | if (handle == NULL) { 22 | std::cout << "Cannot find libfugahoge.so.soldout" << std::endl; 23 | return 0; 24 | } 25 | show_fuga_hoge = (int (*)())dlsym(handle, "show_fuga_hoge"); 26 | if (show_fuga_hoge == NULL) { 27 | std::cout << "Cannot find show_fuga_hoge" << std::endl; 28 | return 0; 29 | } 30 | show_fuga_hoge(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -shared -fPIC -o libfuga.so -Wl,-soname,libfuga.so fuga.cc 4 | aarch64-linux-gnu-g++ -shared -fPIC -o libhoge.so -Wl,-soname,libhoge.so hoge.cc 5 | aarch64-linux-gnu-g++ -shared -fPIC -o libfugahoge.so.original fugahoge.cc libfuga.so libhoge.so 6 | aarch64-linux-gnu-g++ -o main main.cc -ldl 7 | 8 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libfugahoge.so.original -o libfugahoge.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/.gitignore: -------------------------------------------------------------------------------- 1 | libfugahoge.so.original 2 | libfugahoge.so.soldout 3 | libfuga.so 4 | libhoge.so 5 | main 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/fuga.cc: -------------------------------------------------------------------------------- 1 | #include "fuga.h" 2 | 3 | namespace { 4 | thread_local uint64_t fuga_data = 0xDEADBEEFDEADBEEF; 5 | thread_local uint64_t fuga_bss; 6 | } // namespace 7 | 8 | uint64_t get_fuga_data() { 9 | return fuga_data; 10 | } 11 | 12 | uint64_t get_fuga_bss() { 13 | return fuga_bss; 14 | } 15 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/fuga.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void show_fuga(); 4 | uint64_t get_fuga_data(); 5 | uint64_t get_fuga_bss(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/fugahoge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "fuga.h" 6 | #include "hoge.h" 7 | 8 | extern "C" void show_fuga_hoge() { 9 | uint64_t fuga_data = get_fuga_data(); 10 | uint64_t fuga_bss = get_fuga_bss(); 11 | uint64_t hoge_data = get_hoge_data(); 12 | uint64_t hoge_bss = get_hoge_bss(); 13 | 14 | std::cout << std::hex << "fuga_data = " << fuga_data << ", fuga_bss = " << fuga_bss << std::endl 15 | << "hoge_data = " << hoge_data << ", hoge_bss = " << hoge_bss << std::endl; 16 | 17 | assert(fuga_data == 0xDEADBEEFDEADBEEF && fuga_bss == 0 && hoge_data == 0xABCDEFABCDEFABCD && hoge_bss == 0); 18 | } 19 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/hoge.cc: -------------------------------------------------------------------------------- 1 | #include "hoge.h" 2 | 3 | namespace { 4 | thread_local uint64_t hoge_data = 0xABCDEFABCDEFABCD; 5 | thread_local uint64_t hoge_bss; 6 | } // namespace 7 | 8 | uint64_t get_hoge_data() { 9 | return hoge_data; 10 | } 11 | 12 | uint64_t get_hoge_bss() { 13 | return hoge_bss; 14 | } 15 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/hoge.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void show_hoge(); 4 | uint64_t get_hoge_data(); 5 | uint64_t get_hoge_bss(); 6 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main() { 6 | std::cout << "---------- libfugahoge.so.original ----------" << std::endl; 7 | void* handle = dlopen("./libfugahoge.so.original", RTLD_LAZY); 8 | if (handle == NULL) { 9 | std::cout << "Cannot find libfugahoge.so.original" << std::endl; 10 | return 0; 11 | } 12 | int (*show_fuga_hoge)() = (int (*)())dlsym(handle, "show_fuga_hoge"); 13 | if (show_fuga_hoge == NULL) { 14 | std::cout << "Cannot find show_fuga_hoge" << std::endl; 15 | return 0; 16 | } 17 | show_fuga_hoge(); 18 | 19 | std::cout << "---------- libfugahoge.so.soldout ----------" << std::endl; 20 | handle = dlopen("./libfugahoge.so.soldout", RTLD_LAZY); 21 | if (handle == NULL) { 22 | std::cout << "Cannot find libfugahoge.so.soldout" << std::endl; 23 | return 0; 24 | } 25 | show_fuga_hoge = (int (*)())dlsym(handle, "show_fuga_hoge"); 26 | if (show_fuga_hoge == NULL) { 27 | std::cout << "Cannot find show_fuga_hoge" << std::endl; 28 | return 0; 29 | } 30 | show_fuga_hoge(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-multiple-module-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -shared -fPIC -o libfuga.so -Wl,-soname,libfuga.so fuga.cc 4 | g++ -shared -fPIC -o libhoge.so -Wl,-soname,libhoge.so hoge.cc 5 | g++ -shared -fPIC -o libfugahoge.so.original fugahoge.cc libfuga.so libhoge.so 6 | g++ -o main main.cc -ldl 7 | 8 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i libfugahoge.so.original -o libfugahoge.so.soldout --section-headers --check-output 9 | 10 | LD_LIBRARY_PATH=. ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | lib.so.original 3 | lib.so.soldout 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++-aarch64/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int create_id() { 4 | thread_local int current_id = 0; 5 | return current_id++; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int create_id(); 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "lib.h" 4 | 5 | int main() { 6 | int t1_id1, t1_id2; 7 | std::thread t1([&t1_id1, &t1_id2] { 8 | t1_id1 = create_id(); 9 | t1_id2 = create_id(); 10 | }); 11 | 12 | int t2_id1, t2_id2; 13 | std::thread t2([&t2_id1, &t2_id2] { 14 | t2_id1 = create_id(); 15 | t2_id2 = create_id(); 16 | }); 17 | 18 | t1.join(); 19 | t2.join(); 20 | 21 | std::cout << "t1_id1=" << t1_id1 << " t1_id2=" << t1_id2 << " t2_id1=" << t2_id1 << " t2_id2=" << t2_id2 << std::endl; 22 | } 23 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o lib.o lib.cc 4 | aarch64-linux-gnu-g++ -lpthread -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main main.cc lib.so -lpthread 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | 13 | # Use original 14 | # ln -sf lib.so.original lib.so 15 | 16 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 17 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++/.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | lib.so.original 3 | lib.so.soldout 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int create_id() { 4 | thread_local int current_id = 0; 5 | return current_id++; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++/lib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int create_id(); 4 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "lib.h" 4 | 5 | int main() { 6 | int t1_id1, t1_id2; 7 | std::thread t1([&t1_id1, &t1_id2] { 8 | t1_id1 = create_id(); 9 | t1_id2 = create_id(); 10 | }); 11 | 12 | int t2_id1, t2_id2; 13 | std::thread t2([&t2_id1, &t2_id2] { 14 | t2_id1 = create_id(); 15 | t2_id2 = create_id(); 16 | }); 17 | 18 | t1.join(); 19 | t2.join(); 20 | 21 | std::cout << "t1_id1=" << t1_id1 << " t1_id2=" << t1_id2 << " t2_id1=" << t2_id1 << " t2_id2=" << t2_id2 << std::endl; 22 | } 23 | -------------------------------------------------------------------------------- /feature_unit_tests/tls-thread-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o lib.o lib.cc 4 | g++ -lpthread -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | g++ -Wl,--hash-style=gnu -o main main.cc lib.so -lpthread 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | # $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers 10 | 11 | # Use sold 12 | ln -sf lib.so.soldout lib.so 13 | 14 | # Use original 15 | # ln -sf lib.so.original lib.so 16 | 17 | LD_LIBRARY_PATH=. ./main 18 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | lib.o 2 | lib.so 3 | lib.so.original 4 | lib.so.soldout 5 | main 6 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++-aarch64/fuga.h: -------------------------------------------------------------------------------- 1 | struct BaseFuga { 2 | public: 3 | virtual void f() {} 4 | }; 5 | 6 | struct DerivedFuga : public BaseFuga {}; 7 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++-aarch64/lib.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Base { 5 | public: 6 | virtual void f() {} 7 | }; 8 | 9 | class Derived : public Base {}; 10 | 11 | void PrintTypeid() { 12 | Base b; 13 | Derived d; 14 | Base* p1 = &b; 15 | Base* p2 = &d; 16 | 17 | std::cout << typeid(b).name() << "\n" 18 | << typeid(d).name() << "\n" 19 | << typeid(p1).name() << "\n" 20 | << typeid(*p1).name() << "\n" 21 | << typeid(p2).name() << "\n" 22 | << typeid(*p2).name() << std::endl; 23 | } 24 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++-aarch64/lib.h: -------------------------------------------------------------------------------- 1 | void PrintTypeid(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int main() { 4 | PrintTypeid(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-g++ -fPIC -c -o lib.o lib.cc 4 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | aarch64-linux-gnu-g++ -Wl,--hash-style=gnu -o main main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | echo ----------- Use sold ----------- 13 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 14 | 15 | # Use original 16 | ln -sf lib.so.original lib.so 17 | echo ----------- Use original ----------- 18 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 19 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++/.gitignore: -------------------------------------------------------------------------------- 1 | lib.o 2 | lib.so 3 | lib.so.original 4 | lib.so.soldout 5 | main 6 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++/lib.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Base { 5 | public: 6 | virtual void f() {} 7 | }; 8 | 9 | class Derived : public Base {}; 10 | 11 | void PrintTypeid() { 12 | Base b; 13 | Derived d; 14 | Base* p1 = &b; 15 | Base* p2 = &d; 16 | 17 | std::cout << typeid(b).name() << "\n" 18 | << typeid(d).name() << "\n" 19 | << typeid(p1).name() << "\n" 20 | << typeid(*p1).name() << "\n" 21 | << typeid(p2).name() << "\n" 22 | << typeid(*p2).name() << std::endl; 23 | } 24 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++/lib.h: -------------------------------------------------------------------------------- 1 | void PrintTypeid(); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++/main.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int main() { 4 | PrintTypeid(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/typeid-g++/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | g++ -fPIC -c -o lib.o lib.cc 4 | g++ -Wl,--hash-style=gnu -shared -Wl,-soname,lib.so -o lib.so lib.o 5 | g++ -Wl,--hash-style=gnu -o main main.cc lib.so 6 | 7 | mv lib.so lib.so.original 8 | $(git rev-parse --show-toplevel)/build/sold -i lib.so.original -o lib.so.soldout --section-headers --check-output 9 | 10 | # Use sold 11 | ln -sf lib.so.soldout lib.so 12 | echo ----------- Use sold ----------- 13 | LD_LIBRARY_PATH=. ./main 14 | 15 | # Use original 16 | ln -sf lib.so.original lib.so 17 | echo ----------- Use original ----------- 18 | LD_LIBRARY_PATH=. ./main 19 | -------------------------------------------------------------------------------- /feature_unit_tests/unique_ptr-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libhoge.so 2 | libhoge.so.original 3 | libhoge.so.soldout 4 | main 5 | sold.* 6 | -------------------------------------------------------------------------------- /feature_unit_tests/unique_ptr-aarch64/hoge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct X { 5 | X(int v) : var(v){}; 6 | int var; 7 | int fn() { return var; } 8 | }; 9 | 10 | void fn() { 11 | auto up = std::make_unique(42); 12 | auto p = up.release(); 13 | printf("%d\n", p->fn()); 14 | } 15 | -------------------------------------------------------------------------------- /feature_unit_tests/unique_ptr-aarch64/main.cc: -------------------------------------------------------------------------------- 1 | void fn(); 2 | 3 | int main() { 4 | fn(); 5 | } 6 | -------------------------------------------------------------------------------- /feature_unit_tests/unique_ptr-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | aarch64-linux-gnu-g++ -fPIC -shared -o libhoge.so -Wl,-soname,libhoge.so hoge.cc 4 | aarch64-linux-gnu-g++ -o main main.cc libhoge.so 5 | 6 | mv libhoge.so libhoge.so.original 7 | GLOG_log_dir=. $(git rev-parse --show-toplevel)/build/sold -i libhoge.so.original -o libhoge.so.soldout --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 8 | ln -sf libhoge.so.soldout libhoge.so 9 | 10 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./main 11 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/.gitignore: -------------------------------------------------------------------------------- 1 | libmax.so 2 | libmax.so.1 3 | libmax.so.2 4 | libmax1.o 5 | libmax2.o 6 | vertest1 7 | vertest1.out 8 | vertest2 9 | vertest2.out 10 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/libmax1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int max(int a, int b) { 4 | printf("max__1 @ libmax1\n"); 5 | return (a > b ? a : b); 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/libmax1.h: -------------------------------------------------------------------------------- 1 | extern int max(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/libmax2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int max__1(int a, int b) { 4 | printf("max__1 @ libmax2\n"); 5 | return (a > b ? a : b); 6 | } 7 | 8 | int max__2(int a, int b, int c) { 9 | printf("max__2 @ libmax2\n"); 10 | int r = a > b ? a : b; 11 | r = r > c ? r : c; 12 | return r; 13 | } 14 | 15 | __asm__(".symver max__1,max@LIBMAX_1.0"); 16 | __asm__(".symver max__2,max@@LIBMAX_2.0"); 17 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/libmax2.def: -------------------------------------------------------------------------------- 1 | LIBMAX_1.0{ 2 | global: 3 | max*; 4 | local: *; 5 | }; 6 | LIBMAX_2.0{ 7 | global: 8 | max*; 9 | local: *; 10 | } LIBMAX_1.0; 11 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/libmax2.h: -------------------------------------------------------------------------------- 1 | extern int max(int a, int b, int c); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | aarch64-linux-gnu-gcc -fPIC -c -o libmax1.o libmax1.c 4 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -o libmax.so.1 libmax1.o 5 | ln -sf libmax.so.1 libmax.so 6 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o vertest1 vertest1.c libmax.so 7 | 8 | aarch64-linux-gnu-gcc -fPIC -c -o libmax2.o libmax2.c 9 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -Wl,--version-script,libmax2.def -o libmax.so.2 libmax2.o 10 | ln -sf libmax.so.2 libmax.so 11 | aarch64-linux-gnu-gcc -Wl,--hash-style=gnu -o vertest2 vertest2.c libmax.so 12 | 13 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -e libmax.so -o vertest1.out vertest1 --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 14 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./vertest1.out 15 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -e libmax.so -o vertest2.out vertest2 --section-headers --check-output --custom-library-path /usr/aarch64-linux-gnu/lib 16 | LD_LIBRARY_PATH=. qemu-aarch64 -L /usr/aarch64-linux-gnu ./vertest2.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/vertest1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax1.h" 3 | 4 | int main(void) { 5 | printf("max(1,2) = %d\n", max(1, 2)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc-aarch64/vertest2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax2.h" 3 | 4 | int main(void) { 5 | printf("max(1, 2, 3) = %d\n", max(1, 2, 3)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/.gitignore: -------------------------------------------------------------------------------- 1 | libmax.so 2 | libmax.so.1 3 | libmax.so.2 4 | libmax1.o 5 | libmax2.o 6 | vertest1 7 | vertest1.out 8 | vertest2 9 | vertest2.out 10 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/libmax1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int max(int a, int b) { 4 | printf("max__1 @ libmax1\n"); 5 | return (a > b ? a : b); 6 | } 7 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/libmax1.h: -------------------------------------------------------------------------------- 1 | extern int max(int a, int b); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/libmax2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int max__1(int a, int b) { 4 | printf("max__1 @ libmax2\n"); 5 | return (a > b ? a : b); 6 | } 7 | 8 | int max__2(int a, int b, int c) { 9 | printf("max__2 @ libmax2\n"); 10 | int r = a > b ? a : b; 11 | r = r > c ? r : c; 12 | return r; 13 | } 14 | 15 | __asm__(".symver max__1,max@LIBMAX_1.0"); 16 | __asm__(".symver max__2,max@@LIBMAX_2.0"); 17 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/libmax2.def: -------------------------------------------------------------------------------- 1 | LIBMAX_1.0{ 2 | global: 3 | max*; 4 | local: *; 5 | }; 6 | LIBMAX_2.0{ 7 | global: 8 | max*; 9 | local: *; 10 | } LIBMAX_1.0; 11 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/libmax2.h: -------------------------------------------------------------------------------- 1 | extern int max(int a, int b, int c); 2 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | gcc -fPIC -c -o libmax1.o libmax1.c 4 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -o libmax.so.1 libmax1.o 5 | ln -sf libmax.so.1 libmax.so 6 | gcc -Wl,--hash-style=gnu -o vertest1 vertest1.c libmax.so 7 | 8 | gcc -fPIC -c -o libmax2.o libmax2.c 9 | gcc -Wl,--hash-style=gnu -shared -Wl,-soname,libmax.so -Wl,--version-script,libmax2.def -o libmax.so.2 libmax2.o 10 | ln -sf libmax.so.2 libmax.so 11 | gcc -Wl,--hash-style=gnu -o vertest2 vertest2.c libmax.so 12 | 13 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -e libmax.so -o vertest1.out vertest1 --section-headers --check-output 14 | LD_LIBRARY_PATH=. ./vertest1.out 15 | LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -e libmax.so -o vertest2.out vertest2 --section-headers --check-output 16 | LD_LIBRARY_PATH=. ./vertest2.out 17 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/vertest1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax1.h" 3 | 4 | int main(void) { 5 | printf("max(1,2) = %d\n", max(1, 2)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /feature_unit_tests/version-gcc/vertest2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libmax2.h" 3 | 4 | int main(void) { 5 | printf("max(1, 2, 3) = %d\n", max(1, 2, 3)); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /fedora-latest.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:34 2 | RUN dnf install -y ninja-build cmake gcc g++ git libstdc++ python3 python3-devel python3-pip rsync 3 | RUN pip3 install numpy pytest 4 | COPY . /sold 5 | WORKDIR /sold 6 | RUN rm -rf build 7 | RUN mkdir build && cd build && cmake -GNinja -DSOLD_PYBIND_TEST=ON .. 8 | RUN cmake --build build 9 | RUN cd build && ctest 10 | -------------------------------------------------------------------------------- /hash.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "hash.h" 17 | 18 | uint32_t CalcGnuHash(const std::string& name) { 19 | uint32_t h = 5381; 20 | for (unsigned char c : name) { 21 | h = h * 33 + c; 22 | } 23 | return h; 24 | } 25 | 26 | uint32_t CalcHash(const std::string& name) { 27 | uint32_t h = 0, g; 28 | for (unsigned char c : name) { 29 | h = (h << 4) + c; 30 | g = h & 0xf0000000; 31 | h ^= g >> 24; 32 | h ^= g; 33 | } 34 | return h; 35 | } 36 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include "utils.h" 19 | 20 | struct Elf_GnuHash { 21 | uint32_t nbuckets{0}; 22 | uint32_t symndx{0}; 23 | uint32_t maskwords{0}; 24 | uint32_t shift2{0}; 25 | uint8_t tail[1]; 26 | 27 | Elf_Addr* bloom_filter() { return reinterpret_cast(tail); } 28 | 29 | uint32_t* buckets() { return reinterpret_cast(&bloom_filter()[maskwords]); } 30 | 31 | uint32_t* hashvals() { return reinterpret_cast(&buckets()[nbuckets]); } 32 | }; 33 | 34 | uint32_t CalcGnuHash(const std::string& name); 35 | 36 | uint32_t CalcHash(const std::string& name); 37 | 38 | struct Elf_Hash { 39 | uint32_t nbuckets{0}; 40 | uint32_t nchains{0}; 41 | uint8_t tail[1]; 42 | 43 | const uint32_t* buckets() const { return reinterpret_cast(tail); } 44 | 45 | const uint32_t* chains() const { return buckets() + nbuckets; } 46 | }; 47 | -------------------------------------------------------------------------------- /ldsoconf.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "ldsoconf.h" 17 | 18 | #include 19 | 20 | #include 21 | 22 | namespace ldsoconf { 23 | namespace { 24 | void read_ldsoconf_dfs(std::vector& res, const std::string& filename) { 25 | std::ifstream f; 26 | f.open(filename); 27 | if (!f) { 28 | return; 29 | } 30 | std::string head; 31 | while (f >> head) { 32 | if (head.substr(0, 1) == "#") { 33 | std::string comment; 34 | std::getline(f, comment); 35 | } else if (head == "include") { 36 | std::string descendants; 37 | f >> descendants; 38 | 39 | glob_t globbuf; 40 | glob(descendants.c_str(), 0, NULL, &globbuf); 41 | for (int i = 0; i < globbuf.gl_pathc; i++) { 42 | read_ldsoconf_dfs(res, globbuf.gl_pathv[i]); 43 | } 44 | globfree(&globbuf); 45 | } else { 46 | res.push_back(head); 47 | } 48 | } 49 | } 50 | 51 | } // namespace 52 | 53 | std::vector read_ldsoconf() { 54 | std::vector res; 55 | read_ldsoconf_dfs(res, "/etc/ld.so.conf"); 56 | 57 | return res; 58 | } 59 | } // namespace ldsoconf 60 | -------------------------------------------------------------------------------- /ldsoconf.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | namespace ldsoconf { 22 | std::vector read_ldsoconf(); 23 | } 24 | -------------------------------------------------------------------------------- /libtorch_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | project(torch-test LANGUAGES CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | if(NOT CMAKE_BUILD_TYPE) 8 | set(CMAKE_BUILD_TYPE "RelWithDebInfo") 9 | endif() 10 | 11 | find_package(Torch REQUIRED) 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") 13 | 14 | add_library(torch_test SHARED torch_test.cc) 15 | target_link_libraries(torch_test PRIVATE "${TORCH_LIBRARIES}" 16 | -Wl,-soname,libtorch_test.so) 17 | set_target_properties(torch_test PROPERTIES SUFFIX ".so.original") 18 | 19 | add_custom_target( 20 | torch_test_soldout ALL 21 | COMMAND 22 | GLOG_log_dir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/sold -i 23 | ${CMAKE_CURRENT_BINARY_DIR}/libtorch_test.so.original -o 24 | ${CMAKE_CURRENT_BINARY_DIR}/libtorch_test.so.soldout --section-headers 25 | --check-output && ln -sf libtorch_test.so.soldout libtorch_test.so 26 | DEPENDS torch_test sold 27 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 28 | 29 | add_custom_target( 30 | torch_test_soldout_wo_section 31 | EXCLUDE_FROM_ALL 32 | COMMAND 33 | GLOG_log_dir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/sold -i 34 | ${CMAKE_CURRENT_BINARY_DIR}/libtorch_test.so.original -o 35 | ${CMAKE_CURRENT_BINARY_DIR}/libtorch_test.so.wosection.soldout 36 | --check-output 37 | DEPENDS torch_test sold 38 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 39 | 40 | add_custom_target( 41 | torch_test_main ALL 42 | COMMAND 43 | g++ ${CMAKE_CURRENT_SOURCE_DIR}/torch_test_main.cc 44 | ${CMAKE_CURRENT_BINARY_DIR}/libtorch_test.so.original -o torch_test_main 45 | DEPENDS torch_test 46 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 47 | 48 | add_custom_target( 49 | torch_test_main_linked_soldout 50 | EXCLUDE_FROM_ALL 51 | COMMAND 52 | g++ ${CMAKE_CURRENT_SOURCE_DIR}/torch_test_main.cc 53 | ${CMAKE_CURRENT_BINARY_DIR}/libtorch_test.so.soldout -o 54 | torch_test_main_linked_sold 55 | DEPENDS torch_test_soldout 56 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 57 | 58 | add_executable(torch_test_main_dlopen torch_test_main_dlopen.cc) 59 | target_link_libraries(torch_test_main_dlopen PRIVATE -ldl) 60 | 61 | add_test( 62 | NAME libtorch_test 63 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 64 | COMMAND ./torch_test_main) 65 | set_tests_properties( 66 | libtorch_test PROPERTIES ENVIRONMENT 67 | "LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}") 68 | add_test( 69 | NAME libtorch_test_dlopen 70 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 71 | COMMAND ./torch_test_main_dlopen) 72 | set_tests_properties( 73 | libtorch_test_dlopen PROPERTIES ENVIRONMENT 74 | "LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}") 75 | -------------------------------------------------------------------------------- /libtorch_test/torch_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define SLOG() std::cout << __FILE__ << ":" << __LINE__ << " " 11 | #define SSHOW_KV(key, value) " " << key << "=" << (value) 12 | #define SSHOW(x) SSHOW_KV(#x, x) 13 | 14 | extern "C" void test() { 15 | SLOG() << "add test" << std::endl; 16 | auto x = at::randn({1, 128, 224, 224}, at::kFloat); 17 | auto y = at::randn({1, 128, 224, 224}, at::kFloat); 18 | auto z = at::add(x, y); 19 | SLOG() << SSHOW(z.toString()) << std::endl; 20 | 21 | SLOG() << "convolution test" << std::endl; 22 | auto w = at::randn({32, 128, 224, 224}, at::kFloat); 23 | auto r2 = at::convolution(x, w, c10::nullopt, c10::IntArrayRef({1, 1}), c10::IntArrayRef({0}), c10::IntArrayRef({1, 1}), false, 24 | c10::IntArrayRef({0}), 1); 25 | SLOG() << SSHOW(r2.toString()) << std::endl; 26 | } 27 | -------------------------------------------------------------------------------- /libtorch_test/torch_test.h: -------------------------------------------------------------------------------- 1 | extern "C" void test(); 2 | -------------------------------------------------------------------------------- /libtorch_test/torch_test_main.cc: -------------------------------------------------------------------------------- 1 | #include "torch_test.h" 2 | 3 | int main() { 4 | test(); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /libtorch_test/torch_test_main_dlopen.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | void* handle; 7 | void (*test)(); 8 | handle = dlopen("libtorch_test.so", RTLD_LAZY); 9 | if (!handle) { 10 | fprintf(stderr, "%s\n", dlerror()); 11 | exit(1); 12 | } 13 | dlerror(); 14 | test = (void (*)())dlsym(handle, "test"); 15 | test(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /mprotect_builder.cc: -------------------------------------------------------------------------------- 1 | #include "mprotect_builder.h" 2 | 3 | constexpr uint8_t MprotectBuilder::memprotect_body_code_x86_64[]; 4 | constexpr uint8_t MprotectBuilder::memprotect_end_code_x86_64[]; 5 | constexpr uint8_t MprotectBuilder::memprotect_end_code_aarch64[]; 6 | 7 | void MprotectBuilder::EmitX86_64(FILE* fp, uintptr_t mprotect_code_offset) { 8 | uint8_t* mprotect_code = (uint8_t*)malloc(Size()); 9 | uint8_t* mprotect_code_head = mprotect_code; 10 | for (int i = 0; i < offsets.size(); i++) { 11 | LOG(INFO) << "MprotectBuilder::Emit: " << SOLD_LOG_BITS(offsets[i]) << SOLD_LOG_BITS(sizes[i]); 12 | 13 | memcpy(mprotect_code_head, memprotect_body_code_x86_64, sizeof(memprotect_body_code_x86_64)); 14 | int64_t* offset_p = (int64_t*)(mprotect_code_head + memprotect_body_addr_offset_x86_64); 15 | // 17 is the length of `mov $0xdeadbeefdeadbeef, %rdi; lea (%rip), %rsi' 16 | int64_t offset_v = (offsets[i] & (~(0x1000 - 1))) - 17 | (static_cast(mprotect_code_offset) + static_cast(mprotect_code_head - mprotect_code) + 17); 18 | LOG(INFO) << "MprotectBuilder::Emit" << SOLD_LOG_BITS(offset_v) << SOLD_LOG_KEY(offset_v); 19 | *offset_p = offset_v; 20 | uint32_t* size_p = (uint32_t*)(mprotect_code_head + memprotect_body_size_offset_x86_64); 21 | *size_p = ((offsets[i] + sizes[i]) & (~(0x1000 - 1))) - (offsets[i] & (~(0x1000 - 1))); 22 | mprotect_code_head += sizeof(memprotect_body_code_x86_64); 23 | } 24 | memcpy(mprotect_code_head, memprotect_end_code_x86_64, sizeof(memprotect_end_code_x86_64)); 25 | mprotect_code_head += sizeof(memprotect_end_code_x86_64); 26 | 27 | CHECK(fwrite(mprotect_code, sizeof(uint8_t), Size(), fp) == Size()); 28 | free(mprotect_code); 29 | } 30 | 31 | namespace { 32 | std::vector set_immediate_to_register_aarch64(int64_t value, uint8_t reg) { 33 | std::vector ret; 34 | for (int i = 0; i < 4; i++) { 35 | uint32_t u = 0b11110010'10000000'00000000'00000000; // movk instruction 36 | u |= (i << 21); 37 | u |= ((value >> (i * 16)) & 0xffff) << 5; 38 | u |= reg; 39 | ret.emplace_back(u); 40 | } 41 | return ret; 42 | } 43 | } // namespace 44 | 45 | void MprotectBuilder::EmitAarch64(FILE* fp, uintptr_t mprotect_code_offset) { 46 | long int old_pos = ftell(fp); 47 | 48 | LOG(INFO) << "MprotectBuilder::EmitAarch64"; 49 | std::vector insts; 50 | for (int i = 0; i < offsets.size(); i++) { 51 | // 5 is the length of x0 <- offsets[i] using 4 movk instructions; adr x3, 0 52 | int64_t offset = offsets[i] - (static_cast(mprotect_code_offset) + body_code_length_aarch64 + 5 * 4); 53 | auto set_x0 = set_immediate_to_register_aarch64(offset, 0); // x0 <- offsets[i] using 4 movk instructions 54 | insts.insert(insts.end(), set_x0.begin(), set_x0.end()); // 55 | insts.emplace_back(0b00010000'00000000'00000000'00000011); // adr x3, 0 56 | insts.emplace_back(0x8B030000); // add x0, x0,x3 57 | auto set_x1 = set_immediate_to_register_aarch64(sizes[i], 1); // x1 <- len[i] using 4 movk instructions 58 | insts.insert(insts.end(), set_x1.begin(), set_x1.end()); // 59 | insts.emplace_back(0xD2800022); // mov x2, 1(PROT_READ) 60 | insts.emplace_back(0x52800148); // mov w8, 10(mprotect) 61 | insts.emplace_back(0xD4000001); // svc 0 62 | } 63 | insts.emplace_back(0xD65F03C0); 64 | 65 | for (uint32_t i : insts) { 66 | CHECK(fwrite(&i, sizeof(uint32_t), 1, fp) == 1); 67 | } 68 | CHECK(ftell(fp) - old_pos == Size()); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /mprotect_builder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | #include "utils.h" 22 | 23 | class MprotectBuilder { 24 | public: 25 | void SetMachineType(const Elf64_Half machine_type) { 26 | CHECK(machine_type == EM_X86_64 || machine_type == EM_AARCH64); 27 | machine_type_ = machine_type; 28 | } 29 | void Add(uintptr_t offset, uintptr_t size) { 30 | offsets.emplace_back(offset); 31 | sizes.emplace_back(size); 32 | } 33 | uintptr_t Size() const { 34 | CHECK(offsets.size() == sizes.size()); 35 | if (machine_type_ == EM_X86_64) { 36 | return sizeof(memprotect_body_code_x86_64) * offsets.size() + sizeof(memprotect_end_code_x86_64); 37 | } else if (machine_type_ == EM_AARCH64) { 38 | return body_code_length_aarch64 * offsets.size() + ret_code_length_aarch64; 39 | } else { 40 | CHECK(false) << SOLD_LOG_KEY(machine_type_) << " is not supported."; 41 | } 42 | } 43 | void Emit(FILE* fp, uintptr_t mprotect_code_offset) { 44 | CHECK(machine_type_ == EM_X86_64 || machine_type_ == EM_AARCH64) << "SetMachineType before Emit"; 45 | if (machine_type_ == EM_X86_64) { 46 | EmitX86_64(fp, mprotect_code_offset); 47 | } else if (machine_type_ == EM_AARCH64) { 48 | EmitAarch64(fp, mprotect_code_offset); 49 | } else { 50 | CHECK(false) << SOLD_LOG_KEY(machine_type_) << " is not supported."; 51 | } 52 | } 53 | 54 | // call SYS_mprotect syscall 55 | // 56 | // mov $0xdeadbeefdeadbeef, %rdi 57 | // lea (%rip), %rsi 58 | // add %rsi, %rdi 59 | // mov $0xaabbcc, %rsi (size) 60 | // mov $0x1, %rdx (0x1 = PROT_READ) 61 | // mov $10, %eax (10 = SYS_mprotect) 62 | // syscall 63 | // test %eax, %eax 64 | // jz ok 65 | // ud2 66 | // ok: 67 | static constexpr uint8_t memprotect_body_code_x86_64[] = {0x48, 0xbf, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0x48, 0x8d, 68 | 0x35, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0xf7, 0x48, 0xc7, 0xc6, 0xcc, 69 | 0xbb, 0xaa, 0x00, 0x48, 0xc7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x0a, 70 | 0x00, 0x00, 0x00, 0x0f, 0x05, 0x85, 0xc0, 0x74, 0x02, 0x0f, 0x0b}; 71 | // offset to 0xabbccdd 72 | static constexpr int memprotect_body_addr_offset_x86_64 = 2; 73 | // offset to 0xaabbcc 74 | static constexpr int memprotect_body_size_offset_x86_64 = 23; 75 | 76 | // ret 77 | static constexpr uint8_t memprotect_end_code_x86_64[] = {0xc3}; 78 | 79 | // ret 80 | static constexpr uint8_t memprotect_end_code_aarch64[] = {0xc0, 0x03, 0x5f, 0xd6}; 81 | 82 | static constexpr int body_code_length_aarch64 = 13 * 4; 83 | static constexpr int ret_code_length_aarch64 = 4; 84 | 85 | private: 86 | void EmitX86_64(FILE* fp, uintptr_t mprotect_code_offset); 87 | void EmitAarch64(FILE* fp, uintptr_t mprotect_code_offset); 88 | Elf64_Half machine_type_; 89 | std::vector offsets; 90 | std::vector sizes; 91 | }; 92 | -------------------------------------------------------------------------------- /print_dtrela.cc: -------------------------------------------------------------------------------- 1 | // print_dtrela 2 | // This program shows relocation entries in DT_RELA. 3 | // 4 | // Copyright (C) 2021 The sold authors 5 | // 6 | // This program is free software: you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License as published by 8 | // the Free Software Foundation, either version 3 of the License, or 9 | // (at your option) any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program. If not, see . 18 | 19 | #include "elf_binary.h" 20 | 21 | #include 22 | 23 | int main(int argc, const char* argv[]) { 24 | google::InitGoogleLogging(argv[0]); 25 | 26 | if (argc != 2) { 27 | std::cerr << "Usage: " << argv[0] << " \nThis program parse DT_RELA of the given ELF file." << std::endl; 28 | return 1; 29 | } 30 | 31 | auto b = ReadELF(argv[1]); 32 | std::cout << b->ShowDtRela(); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /print_dynsymtab.cc: -------------------------------------------------------------------------------- 1 | // print_dynsymtab 2 | // 3 | // This program parses and prints DT_SYMTAB of a given ELF file. It prints all symbols 4 | // and version information. When the ELF file does not include version information, 5 | // it prints NO_VERSION_INFO instead of version information. 6 | // 7 | // Unlike nm -D --with-symbol-versions or readelf --dynsyms, it works without any shdrs 8 | // because print_dynsymtab gets all information only from phdrs. 9 | // 10 | // Copyright (C) 2021 The sold authors 11 | // 12 | // This program is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU General Public License as published by 14 | // the Free Software Foundation, either version 3 of the License, or 15 | // (at your option) any later version. 16 | // 17 | // This program is distributed in the hope that it will be useful, 18 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // GNU General Public License for more details. 21 | // 22 | // You should have received a copy of the GNU General Public License 23 | // along with this program. If not, see . 24 | 25 | #include "elf_binary.h" 26 | 27 | #include 28 | 29 | #include "sold.h" 30 | 31 | int main(int argc, const char* argv[]) { 32 | google::InitGoogleLogging(argv[0]); 33 | 34 | if (argc != 2) { 35 | std::cerr << "Usage: " << argv[0] << " \nThis program parse DT_SYMTAB of the given ELF file." << std::endl; 36 | return 1; 37 | } 38 | 39 | // This Sold class instrance is used only to get filename_to_soname map. 40 | Sold sold(argv[1], {}, {}, {}, {}, {}, false, false); 41 | 42 | auto b = ReadELF(argv[1]); 43 | b->ReadDynSymtab(sold.filename_to_soname()); 44 | std::cout << b->ShowDynSymtab(); 45 | } 46 | -------------------------------------------------------------------------------- /print_ehframe.cc: -------------------------------------------------------------------------------- 1 | // 2 | // print_ehframe 3 | // 4 | // This program shows .eh_frame_hdr 5 | // 6 | // Copyright (C) 2021 The sold authors 7 | // 8 | // This program is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // This program is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with this program. If not, see . 20 | 21 | #include "elf_binary.h" 22 | 23 | #include 24 | 25 | int main(int argc, const char* argv[]) { 26 | google::InitGoogleLogging(argv[0]); 27 | google::InstallFailureSignalHandler(); 28 | 29 | if (argc != 2) { 30 | std::cerr << "Usage: " << argv[0] << " \nThis program shows .eh_frame_hdr." << std::endl; 31 | return 1; 32 | } 33 | 34 | auto b = ReadELF(argv[1]); 35 | std::cout << b->ShowEHFrame(); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /print_tls.cc: -------------------------------------------------------------------------------- 1 | // 2 | // print_tls 3 | // 4 | // This program shows tls entries. 5 | // 6 | // Copyright (C) 2021 The sold authors 7 | // 8 | // This program is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // This program is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with this program. If not, see . 20 | 21 | #include "elf_binary.h" 22 | 23 | #include 24 | 25 | int main(int argc, const char* argv[]) { 26 | google::InitGoogleLogging(argv[0]); 27 | 28 | if (argc != 2) { 29 | std::cerr << "Usage: " << argv[0] << " \nThis program shows TLS entries of the given ELF file." << std::endl; 30 | return 1; 31 | } 32 | 33 | auto b = ReadELF(argv[1]); 34 | std::cout << b->ShowTLS(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /print_version.cc: -------------------------------------------------------------------------------- 1 | // 2 | // print_verneed 3 | // 4 | // This program shows version information. 5 | // 6 | // Copyright (C) 2021 The sold authors 7 | // 8 | // This program is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // This program is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with this program. If not, see . 20 | 21 | #include "elf_binary.h" 22 | 23 | #include 24 | 25 | int main(int argc, const char* argv[]) { 26 | google::InitGoogleLogging(argv[0]); 27 | 28 | if (argc != 2) { 29 | std::cerr << "Usage: " << argv[0] << " \nThis program shows verneed information of the given ELF file." << std::endl; 30 | return 1; 31 | } 32 | 33 | auto b = ReadELF(argv[1]); 34 | std::cout << b->ShowVersion(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /pybind_libtorch_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | 3 | find_package(Torch REQUIRED) 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") 5 | 6 | # I set PREFIX and SUFFIX here because I want to pass generated files to sold. 7 | # The default SUFFIX depends on the system configuration and is difficult to 8 | # infer. 9 | pybind11_add_module(my_add_kernel numpy.cc) 10 | set_target_properties(my_add_kernel PROPERTIES PREFIX "" SUFFIX ".so") 11 | target_link_libraries(my_add_kernel PRIVATE "${TORCH_LIBRARIES}") 12 | 13 | file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/soldout") 14 | add_custom_target( 15 | my_add_kernel_soldout ALL 16 | COMMAND 17 | "${PROJECT_BINARY_DIR}/sold" -i 18 | "${CMAKE_CURRENT_BINARY_DIR}/my_add_kernel.so" -o 19 | "${CMAKE_CURRENT_BINARY_DIR}/soldout/my_add_kernel.so" --section-headers 20 | --check-output 21 | DEPENDS sold my_add_kernel) 22 | 23 | # ${CMAKE_CURRENT_BINARY_DIR}/test_soldout_modules_original.py is for debug. 24 | configure_file( 25 | test_soldout_modules.py 26 | ${CMAKE_CURRENT_BINARY_DIR}/test_soldout_modules_original.py @ONLY) 27 | configure_file( 28 | test_soldout_modules.py 29 | ${CMAKE_CURRENT_BINARY_DIR}/soldout/test_soldout_modules.py @ONLY) 30 | 31 | add_test( 32 | NAME pybind_libtorch_test 33 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/soldout" 34 | COMMAND pytest -v) 35 | -------------------------------------------------------------------------------- /pybind_libtorch_test/numpy.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace py = pybind11; 12 | 13 | py::array_t add_arrays(py::array_t input1, py::array_t input2) { 14 | py::buffer_info buf1 = input1.request(), buf2 = input2.request(); 15 | 16 | if (buf1.ndim != 1 || buf2.ndim != 1) throw std::runtime_error("Number of dimensions must be one"); 17 | 18 | if (buf1.size != buf2.size) throw std::runtime_error("Input shapes must match"); 19 | 20 | /* No pointer is passed, so NumPy will allocate the buffer */ 21 | auto result = py::array_t(buf1.size); 22 | 23 | py::buffer_info buf3 = result.request(); 24 | 25 | double* ptr1 = static_cast(buf1.ptr); 26 | double* ptr2 = static_cast(buf2.ptr); 27 | double* ptr3 = static_cast(buf3.ptr); 28 | 29 | at::Tensor tensor1 = at::from_blob(ptr1, buf1.size, at::kDouble).clone(); 30 | at::Tensor tensor2 = at::from_blob(ptr2, buf1.size, at::kDouble).clone(); 31 | at::Tensor tensor3 = tensor1 + tensor2; 32 | 33 | for (size_t idx = 0; idx < buf1.shape[0]; idx++) ptr3[idx] = tensor3[idx].item(); 34 | 35 | return result; 36 | } 37 | 38 | PYBIND11_MODULE(my_add_kernel, m) { 39 | m.def("add_arrays", &add_arrays, "Add two NumPy arrays using libtorch"); 40 | } 41 | -------------------------------------------------------------------------------- /pybind_libtorch_test/test_soldout_modules.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | 3 | import my_add_kernel 4 | 5 | def test_mynumpy_add(): 6 | # The size of arrays is pretty large because I had encountered a bug that 7 | # appears only for large arrays. 8 | a = numpy.random.rand(32) 9 | b = numpy.random.rand(32) 10 | r = my_add_kernel.add_arrays(a, b) 11 | assert numpy.allclose(a + b, r) 12 | -------------------------------------------------------------------------------- /pybind_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | 3 | # I set PREFIX and SUFFIX here because I want to pass generated files to sold. 4 | # The default SUFFIX depends on the system configuration and is difficult to 5 | # infer. 6 | pybind11_add_module(myadd add.cc) 7 | set_target_properties(myadd PROPERTIES PREFIX "" SUFFIX ".so") 8 | pybind11_add_module(myobject object.cc) 9 | set_target_properties(myobject PROPERTIES PREFIX "" SUFFIX ".so") 10 | pybind11_add_module(mynumpy numpy.cc) 11 | set_target_properties(mynumpy PROPERTIES PREFIX "" SUFFIX ".so") 12 | 13 | file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/soldout") 14 | add_custom_target( 15 | myadd_soldout ALL 16 | COMMAND 17 | "${PROJECT_BINARY_DIR}/sold" -i "${CMAKE_CURRENT_BINARY_DIR}/myadd.so" -o 18 | "${CMAKE_CURRENT_BINARY_DIR}/soldout/myadd.so" --section-headers 19 | --check-output 20 | DEPENDS sold myadd) 21 | add_custom_target( 22 | myobject_soldout ALL 23 | COMMAND 24 | "${PROJECT_BINARY_DIR}/sold" -i "${CMAKE_CURRENT_BINARY_DIR}/myobject.so" -o 25 | "${CMAKE_CURRENT_BINARY_DIR}/soldout/myobject.so" --section-headers 26 | --check-output 27 | DEPENDS sold myobject) 28 | add_custom_target( 29 | mynumpy_soldout ALL 30 | COMMAND 31 | "${PROJECT_BINARY_DIR}/sold" -i "${CMAKE_CURRENT_BINARY_DIR}/mynumpy.so" -o 32 | "${CMAKE_CURRENT_BINARY_DIR}/soldout/mynumpy.so" --section-headers 33 | --check-output 34 | DEPENDS sold mynumpy) 35 | 36 | # ${CMAKE_CURRENT_BINARY_DIR}/test_soldout_modules_original.py is for debug. 37 | configure_file( 38 | test_soldout_modules.py 39 | ${CMAKE_CURRENT_BINARY_DIR}/test_soldout_modules_original.py @ONLY) 40 | configure_file( 41 | test_soldout_modules.py 42 | ${CMAKE_CURRENT_BINARY_DIR}/soldout/test_soldout_modules.py @ONLY) 43 | 44 | add_test( 45 | NAME pybind_test 46 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/soldout" 47 | COMMAND pytest -v) 48 | -------------------------------------------------------------------------------- /pybind_test/README.md: -------------------------------------------------------------------------------- 1 | # pybind test 2 | Most of codes in this directory comes from 3 | - [https://pybind11.readthedocs.io/en/stable/basics.html]() 4 | - [https://pybind11.readthedocs.io/en/stable/classes.html]() 5 | - [https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html]() 6 | -------------------------------------------------------------------------------- /pybind_test/add.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace py = pybind11; 4 | using namespace pybind11::literals; 5 | 6 | int add(int i, int j) { 7 | return i + j; 8 | } 9 | 10 | PYBIND11_MODULE(myadd, m) { 11 | m.doc() = "pybind11 example plugin"; // optional module docstring 12 | m.def("myadd", &add, "A function which adds two numbers"); 13 | m.def("myadd2", &add, "i"_a, "j"_a); 14 | m.def("myadd3", &add, "i"_a = 1, "j"_a = 2); 15 | 16 | m.attr("the_answer") = 42; 17 | py::object world = py::cast("World"); 18 | m.attr("what") = world; 19 | } 20 | -------------------------------------------------------------------------------- /pybind_test/numpy.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace py = pybind11; 5 | 6 | py::array_t add_arrays(py::array_t input1, py::array_t input2) { 7 | py::buffer_info buf1 = input1.request(), buf2 = input2.request(); 8 | 9 | if (buf1.ndim != 1 || buf2.ndim != 1) throw std::runtime_error("Number of dimensions must be one"); 10 | 11 | if (buf1.size != buf2.size) throw std::runtime_error("Input shapes must match"); 12 | 13 | /* No pointer is passed, so NumPy will allocate the buffer */ 14 | auto result = py::array_t(buf1.size); 15 | 16 | py::buffer_info buf3 = result.request(); 17 | 18 | double* ptr1 = static_cast(buf1.ptr); 19 | double* ptr2 = static_cast(buf2.ptr); 20 | double* ptr3 = static_cast(buf3.ptr); 21 | 22 | for (size_t idx = 0; idx < buf1.shape[0]; idx++) ptr3[idx] = ptr1[idx] + ptr2[idx]; 23 | 24 | return result; 25 | } 26 | 27 | PYBIND11_MODULE(mynumpy, m) { 28 | m.def("add_arrays", &add_arrays, "Add two NumPy arrays"); 29 | } 30 | -------------------------------------------------------------------------------- /pybind_test/object.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace py = pybind11; 4 | 5 | struct Pet { 6 | enum Kind { Dog = 0, Cat }; 7 | 8 | Pet(const std::string& name) : name(name), type(Kind::Dog) {} 9 | Pet(const std::string& name, Kind type) : name(name), type(type) {} 10 | 11 | void set(int age_) { age = age_; } 12 | void set(const std::string& name_) { name = name_; } 13 | void setName(const std::string& name_) { name = name_; } 14 | const std::string& getName() const { return name; } 15 | const int getAge() const { return age; } 16 | 17 | int age; 18 | std::string name; 19 | Kind type; 20 | }; 21 | 22 | struct Dog : Pet { 23 | Dog(const std::string& name) : Pet(name) {} 24 | std::string bark() const { return "woof!"; } 25 | }; 26 | 27 | struct PolymorphicPet { 28 | virtual ~PolymorphicPet() = default; 29 | }; 30 | 31 | struct PolymorphicDog : PolymorphicPet { 32 | std::string bark() const { return "woof!"; } 33 | }; 34 | 35 | PYBIND11_MODULE(myobject, m) { 36 | py::class_ pet(m, "Pet"); 37 | 38 | pet.def(py::init()) 39 | .def(py::init()) 40 | .def("set", py::overload_cast(&Pet::set), "Set the pet's age") 41 | .def("set", py::overload_cast(&Pet::set), "Set the pet's name") 42 | .def("setName", &Pet::setName) 43 | .def("getName", &Pet::getName) 44 | .def("getAge", &Pet::getAge) 45 | .def("__repr__", [](const Pet& a) { return ""; }) 46 | .def_readwrite("type", &Pet::type); 47 | py::enum_(pet, "Kind").value("Dog", Pet::Kind::Dog).value("Cat", Pet::Kind::Cat).export_values(); 48 | 49 | py::class_(m, "Dog").def(py::init()).def("bark", &Dog::bark); 50 | 51 | m.def("pet_store", []() { return std::unique_ptr(new Dog("Molly")); }); 52 | 53 | py::class_(m, "PolymorphicPet"); 54 | py::class_(m, "PolymorphicDog").def(py::init<>()).def("bark", &PolymorphicDog::bark); 55 | 56 | m.def("pet_store2", []() { return std::unique_ptr(new PolymorphicDog); }); 57 | } 58 | -------------------------------------------------------------------------------- /pybind_test/test_soldout_modules.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | 3 | import myadd 4 | import myobject 5 | import mynumpy 6 | 7 | def test_myadd(): 8 | assert myadd.myadd(1, 2) == 3 9 | 10 | def test_myadd_keyword(): 11 | assert myadd.myadd2(i=1, j=2) == 3 12 | 13 | def test_myadd_default(): 14 | assert myadd.myadd3() == 3 15 | 16 | def test_myadd_const(): 17 | assert myadd.the_answer == 42 18 | assert myadd.what == "World" 19 | 20 | def test_myobject_pet(): 21 | p = myobject.Pet('Molly') 22 | assert p.getName() == "Molly" 23 | p.setName('Charly') 24 | assert p.getName() == "Charly" 25 | 26 | def test_myobject_dog(): 27 | p = myobject.Dog('Molly') 28 | assert p.getName() == "Molly" 29 | assert p.bark() == "woof!" 30 | 31 | def test_myobject_pet_store(): 32 | p = myobject.pet_store() 33 | assert type(p).__name__ == "Pet" 34 | 35 | def test_myobject_pet_store2(): 36 | p = myobject.pet_store2() 37 | assert type(p).__name__ == "PolymorphicDog" 38 | assert p.bark() == "woof!" 39 | 40 | def test_myobject_overload(): 41 | p = myobject.Pet('Molly') 42 | p.set(10) 43 | p.set("hogehoge") 44 | assert p.getAge() == 10 45 | assert p.getName() == "hogehoge" 46 | 47 | def test_myobject_enum(): 48 | p = myobject.Pet('Lucy', myobject.Pet.Cat) 49 | assert p.type == 1 50 | 51 | def test_mynumpy_add(): 52 | # The size of arrays is pretty large because I had encountered a bug that 53 | # appears only for large arrays. 54 | a = numpy.random.rand(1024 * 1024 * 32) 55 | b = numpy.random.rand(1024 * 1024 * 32) 56 | r = mynumpy.add_arrays(a, b) 57 | assert numpy.allclose(a + b, r) 58 | -------------------------------------------------------------------------------- /renamer_test/.gitignore: -------------------------------------------------------------------------------- 1 | libfugafuga.so 2 | libhoge_original.so 3 | libhoge_renamed.so 4 | libhoge.so 5 | use_fugafuga 6 | -------------------------------------------------------------------------------- /renamer_test/fugafuga.c: -------------------------------------------------------------------------------- 1 | int fugafuga(int a, int b) { 2 | return a - b; 3 | } 4 | -------------------------------------------------------------------------------- /renamer_test/hoge.c: -------------------------------------------------------------------------------- 1 | int hoge(int a, int b) { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /renamer_test/mapping: -------------------------------------------------------------------------------- 1 | hoge fugafuga 2 | -------------------------------------------------------------------------------- /renamer_test/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | gcc -fPIC -fpic -shared -o libhoge_original.so hoge.c -Wl,-soname,libhoge.so 4 | gcc -fPIC -fpic -shared -o libfugafuga.so fugafuga.c -Wl,-soname,libhoge.so 5 | ln -sf libfugafuga.so libhoge.so 6 | gcc -o use_fugafuga use_fugafuga.c libhoge.so 7 | $(git rev-parse --show-toplevel)/build/renamer libhoge_original.so --output libhoge_renamed.so --rename-mapping-file mapping 8 | ln -sf libhoge_renamed.so libhoge.so 9 | LD_LIBRARY_PATH=. ./use_fugafuga 10 | -------------------------------------------------------------------------------- /renamer_test/use_fugafuga.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Although `fugafuga` in fugafuga.c is subtraction, `hoge` in hoge.c is 5 | // addition. renamer renames `hoge` to `fugafuga`. 6 | int fugafuga(int a, int b); 7 | 8 | int main() { 9 | int a = fugafuga(1, 2); 10 | assert(a == 3); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /run-docker-tests.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | # ========== ubuntu18.04 start ========== 4 | # ---------- CPU start ---------- 5 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.8.0+cpu IMAGE_NAME=ubuntu:18.04 . 6 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.8.1+cpu IMAGE_NAME=ubuntu:18.04 . 7 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.9.0+cpu IMAGE_NAME=ubuntu:18.04 . 8 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.9.1+cpu IMAGE_NAME=ubuntu:18.04 . 9 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.10.0+cpu IMAGE_NAME=ubuntu:18.04 . 10 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.10.1+cpu IMAGE_NAME=ubuntu:18.04 . 11 | sudo docker build -f ubuntu18.04.Dockerfile --build-arg TORCH_VERSION=1.10.2+cpu IMAGE_NAME=ubuntu:18.04 . 12 | # ---------- CPU end ---------- 13 | 14 | # ---------- GPU start ---------- 15 | # DT_INIT and DT_FINI. 16 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.8.0+cu101 --build-arg IMAGE_NAME=nvidia/cuda:10.1-devel-ubuntu18.04 . 17 | # F0530 00:17:28.955174 231 sold.cc:135] Check failed: file_offset < offsets_[main_binary_.get()] 18 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.8.0+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 19 | 20 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.8.1+cu101 --build-arg IMAGE_NAME=nvidia/cuda:10.1-devel-ubuntu18.04 . 21 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.8.1+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 22 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.8.1+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 23 | 24 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.9.0+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 25 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.9.0+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 26 | 27 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.9.0+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 28 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.9.0+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 29 | 30 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.9.1+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 31 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.9.1+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 32 | 33 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.0+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 34 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.0+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 35 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.0+cu113 --build-arg IMAGE_NAME=nvidia/cuda:11.3-devel-ubuntu18.04 . 36 | 37 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.1+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 38 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.1+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 39 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.1+cu113 --build-arg IMAGE_NAME=nvidia/cuda:11.3-devel-ubuntu18.04 . 40 | 41 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.2+cu102 --build-arg IMAGE_NAME=nvidia/cuda:10.2-devel-ubuntu18.04 . 42 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.2+cu111 --build-arg IMAGE_NAME=nvidia/cuda:11.1-devel-ubuntu18.04 . 43 | sudo docker build -f ubuntu18.04-gpu.Dockerfile --build-arg TORCH_VERSION=1.10.2+cu113 --build-arg IMAGE_NAME=nvidia/cuda:11.3-devel-ubuntu18.04 . 44 | # ---------- GPU end ---------- 45 | # ========== ubuntu18.04 end ========== 46 | 47 | sudo docker build -f ubuntu20.04.Dockerfile . 48 | sudo docker build -f ubuntu22.04.Dockerfile . 49 | sudo docker build -f fedora-latest.Dockerfile . 50 | -------------------------------------------------------------------------------- /run-format.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eu 2 | 3 | cd "$(git rev-parse --show-toplevel)" 4 | git ls-files -- '**/*.h' '**/*.cc' '**/*.c'| xargs -P4 clang-format -i 5 | git ls-files -- '**/CMakeLists.txt' | xargs -P4 cmake-format -i 6 | git diff --exit-code -- . 7 | -------------------------------------------------------------------------------- /shdr_builder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "utils.h" 21 | 22 | class ShdrBuilder { 23 | public: 24 | enum ShdrType { GnuHash, Dynsym, GnuVersion, GnuVersionR, Dynstr, RelaDyn, InitArray, FiniArray, Strtab, Shstrtab, Dynamic, Text, TLS }; 25 | void EmitShstrtab(FILE* fp); 26 | void EmitShdrs(FILE* fp); 27 | uintptr_t ShstrtabSize() const; 28 | Elf_Half CountShdrs() const { return shdrs.size(); } 29 | void RegisterShdr(Elf_Off offset, uint64_t size, ShdrType type, uint64_t entsize = 0, Elf_Word info = 0); 30 | Elf_Half Shstrndx() const { return shdrs.size() - 1; } 31 | 32 | // After register all shdrs, you must call Freeze. 33 | void Freeze(); 34 | 35 | private: 36 | const std::map type_to_str = { 37 | {GnuHash, ".gnu.hash"}, {Dynsym, ".dynsym"}, {GnuVersion, ".gnu.version"}, {GnuVersionR, ".gnu.version_r"}, 38 | {Dynstr, ".dynstr"}, {RelaDyn, ".rela.dyn"}, {InitArray, ".init_array"}, {FiniArray, ".fini_array"}, 39 | {Strtab, ".strtab"}, {Shstrtab, ".shstrtab"}, {Dynamic, ".dynamic"}, {Text, ".text"}, 40 | {TLS, ".tls"}}; 41 | 42 | // The first section header must be NULL. 43 | std::vector shdrs = {Elf_Shdr{0}}; 44 | uint32_t GetShName(ShdrType type) const; 45 | uint32_t GetIndex(ShdrType type) const; 46 | }; 47 | -------------------------------------------------------------------------------- /strtab_builder.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "strtab_builder.h" 17 | 18 | #include "utils.h" 19 | 20 | uintptr_t StrtabBuilder::Add(const std::string& s) { 21 | std::string t = s; 22 | auto it = rename_mapping_.find(s); 23 | if (it != rename_mapping_.end()) t = it->second; 24 | 25 | CHECK(!is_freezed_); 26 | if (cache.find(t) != cache.end()) { 27 | return cache[t]; 28 | } 29 | uintptr_t pos = static_cast(strtab_.size()); 30 | strtab_ += t; 31 | strtab_ += '\0'; 32 | cache[t] = pos; 33 | return pos; 34 | } 35 | 36 | uintptr_t StrtabBuilder::GetPos(const std::string& s) { 37 | std::string t = s; 38 | auto it = rename_mapping_.find(s); 39 | if (it != rename_mapping_.end()) t = it->second; 40 | 41 | if (cache.find(t) != cache.end()) { 42 | return cache[t]; 43 | } else { 44 | LOG(FATAL) << t << " is not in StrtabBuilder."; 45 | exit(1); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /strtab_builder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | class StrtabBuilder { 23 | public: 24 | StrtabBuilder() {} 25 | StrtabBuilder(std::map rename_mapping) : rename_mapping_(rename_mapping) {} 26 | 27 | uintptr_t Add(const std::string& s); 28 | 29 | uintptr_t GetPos(const std::string& s); 30 | 31 | void Freeze() { is_freezed_ = true; } 32 | 33 | size_t size() const { return strtab_.size(); } 34 | 35 | const void* data() const { return strtab_.data(); } 36 | 37 | private: 38 | std::string strtab_; 39 | std::map cache; 40 | bool is_freezed_{false}; 41 | const std::map rename_mapping_; 42 | }; 43 | -------------------------------------------------------------------------------- /symtab_builder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "hash.h" 23 | #include "strtab_builder.h" 24 | #include "utils.h" 25 | #include "version_builder.h" 26 | 27 | class SymtabBuilder { 28 | public: 29 | SymtabBuilder(); 30 | 31 | void SetSrcSyms(std::vector syms); 32 | 33 | bool Resolve(const std::string& name, const std::string& filename, const std::string version_name, uintptr_t& val_or_index); 34 | 35 | uintptr_t ResolveCopy(const std::string& name, const std::string& filename, const std::string version_name); 36 | 37 | void Build(StrtabBuilder& strtab, VersionBuilder& version); 38 | 39 | void MergePublicSymbols(StrtabBuilder& strtab, VersionBuilder& version); 40 | 41 | void AddPublicSymbol(Syminfo s) { public_syms_.push_back(s); } 42 | 43 | uintptr_t size() const { return symtab_.size() + public_syms_.size(); } 44 | 45 | const Elf_GnuHash& gnu_hash() const { return gnu_hash_; } 46 | 47 | uintptr_t GnuHashSize() const; 48 | 49 | const std::vector& Get() { return symtab_; } 50 | 51 | const std::vector& GetExposedSyms() const { return exposed_syms_; } 52 | 53 | private: 54 | struct Symbol { 55 | Elf_Sym sym; 56 | uintptr_t index; 57 | }; 58 | 59 | // map from (name, soname, version) to (Versym, Sym*) 60 | std::map, std::pair > src_syms_; 61 | // map from name to (Versym, Sym*) 62 | // We use src_fallback_syms_ when we don't have version information. 63 | std::map > src_fallback_syms_; 64 | std::map, Symbol> syms_; 65 | 66 | std::vector exposed_syms_; 67 | std::vector symtab_; 68 | std::vector public_syms_; 69 | 70 | Elf_GnuHash gnu_hash_; 71 | 72 | uintptr_t AddSym(const Syminfo& sym); 73 | }; 74 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_SKIP_RPATH ON) 2 | 3 | add_library(test_base SHARED base.cc) 4 | 5 | add_library(test_lib SHARED lib.cc) 6 | target_link_libraries(test_lib PRIVATE test_base "-Wl,-R,'$$ORIGIN'") 7 | 8 | add_executable(test_exe exe.cc) 9 | target_link_libraries(test_exe test_lib "-Wl,-R,'$$ORIGIN'") 10 | 11 | add_executable(test_hash exe.cc) 12 | target_link_libraries(test_hash test_lib -Wl,--hash-style=sysv 13 | "-Wl,-R,'$$ORIGIN'") 14 | -------------------------------------------------------------------------------- /tests/base.cc: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | #include 4 | #include 5 | 6 | static int g_init; 7 | __attribute__((constructor)) static void init() { 8 | puts("Constructor in base"); 9 | g_init = 44; 10 | } 11 | 12 | __attribute__((destructor)) static void quit() { 13 | puts("Destructor in base"); 14 | } 15 | 16 | int base_init_value() { 17 | return g_init; 18 | } 19 | 20 | int base_42() { 21 | printf("called %s\n", __func__); 22 | return 42; 23 | } 24 | 25 | int base_add_42(int x) { 26 | printf("called %s\n", __func__); 27 | return x + 42; 28 | } 29 | 30 | int in_both_lib_and_base() { 31 | fprintf(stderr, "Must have been overriden\n"); 32 | abort(); 33 | } 34 | 35 | void base_use_stderr() { 36 | fprintf(stderr, "Use stderr from base\n"); 37 | } 38 | 39 | int base_global = 98; 40 | 41 | class BaseImpl : public Base { 42 | public: 43 | int vf() override { return 1234; } 44 | }; 45 | 46 | Base* MakeBase() { 47 | return new BaseImpl(); 48 | } 49 | 50 | thread_local int g_base_thread_var = 190; 51 | thread_local int g_base_thread_var2 = 70; 52 | thread_local int g_base_thread_bss; 53 | thread_local int g_base_thread_bss2; 54 | static int g_buf[] = {42}; 55 | thread_local int* g_base_thread_buf = g_buf; 56 | 57 | int base_thread_var() { 58 | return (g_base_thread_var - g_base_thread_var2 - --g_base_thread_bss) * ++g_base_thread_bss2; 59 | } 60 | 61 | int base_thread_var_reloc() { 62 | return g_base_thread_buf[0]; 63 | } 64 | -------------------------------------------------------------------------------- /tests/base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int base_42(); 4 | int base_add_42(int x); 5 | void base_use_stderr(); 6 | int base_init_value(); 7 | 8 | extern int base_global; 9 | 10 | class Base { 11 | public: 12 | virtual ~Base() {} 13 | virtual int vf() = 0; 14 | }; 15 | 16 | Base* MakeBase(); 17 | 18 | int base_thread_var(); 19 | int base_thread_var_reloc(); 20 | -------------------------------------------------------------------------------- /tests/exe.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "lib.h" 5 | 6 | static int g_init; 7 | __attribute__((constructor)) static void init() { 8 | puts("Constructor in exe"); 9 | g_init = 42; 10 | } 11 | 12 | __attribute__((destructor)) static void quit() { 13 | puts("Destructor in exe"); 14 | } 15 | 16 | int main(int argc, char** argv) { 17 | int is_exe = (argc == 1); 18 | 19 | puts("Start main"); 20 | if (lib_add_42_via_base(10) != 52) abort(); 21 | if (in_both_lib_and_base() != 100) abort(); 22 | 23 | fprintf(stderr, "Use stderr from main\n"); 24 | lib_use_stderr(); 25 | 26 | if (g_init != 42) abort(); 27 | // TODO(hamaji): Fix .init_array for the main binary. 28 | if (!is_exe) { 29 | if (lib_init_value() != 43) abort(); 30 | if (lib_base_init_value() != 44) abort(); 31 | puts("Constructors are OK"); 32 | } 33 | 34 | if (lib_base_global() != 98) abort(); 35 | 36 | if (lib_base_vf() != 1234) abort(); 37 | 38 | if (lib_base_thread_var() != 121) abort(); 39 | if (lib_base_thread_var_reloc() != 42) abort(); 40 | if (lib_thread_var() != 111) abort(); 41 | if (lib_thread_var_reloc() != 32) abort(); 42 | 43 | puts("OK"); 44 | } 45 | -------------------------------------------------------------------------------- /tests/lib.cc: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "base.h" 8 | 9 | static int g_init; 10 | __attribute__((constructor)) static void init() { 11 | puts("Constructor in lib"); 12 | g_init = 43; 13 | } 14 | 15 | __attribute__((destructor)) static void quit() { 16 | puts("Destructor in lib"); 17 | } 18 | 19 | int lib_init_value() { 20 | return g_init; 21 | } 22 | 23 | int lib_base_init_value() { 24 | return base_init_value(); 25 | } 26 | 27 | int lib_42() { 28 | printf("called %s\n", __func__); 29 | return 42; 30 | } 31 | 32 | int lib_add_42_via_base(int v) { 33 | printf("called %s\n", __func__); 34 | return base_add_42(v); 35 | } 36 | 37 | int in_both_lib_and_base() { 38 | printf("called %s\n", __func__); 39 | return 100; 40 | } 41 | 42 | void lib_use_stderr() { 43 | fprintf(stderr, "Use stderr from lib\n"); 44 | } 45 | 46 | int lib_base_global() { 47 | return base_global; 48 | } 49 | 50 | int* lib_base_global_ptr() { 51 | return &base_global; 52 | } 53 | 54 | int lib_base_vf() { 55 | printf("called %s\n", __func__); 56 | std::unique_ptr base(MakeBase()); 57 | return base->vf(); 58 | } 59 | 60 | int lib_base_thread_var() { 61 | return base_thread_var(); 62 | } 63 | 64 | int lib_base_thread_var_reloc() { 65 | return base_thread_var_reloc(); 66 | } 67 | 68 | thread_local int g_lib_thread_var = 180; 69 | thread_local int g_lib_thread_var2 = 70; 70 | thread_local int g_lib_thread_bss; 71 | thread_local int g_lib_thread_bss2; 72 | static int g_buf[] = {32}; 73 | thread_local int* g_lib_thread_buf = g_buf; 74 | 75 | int lib_thread_var() { 76 | return (g_lib_thread_var - g_lib_thread_var2 - --g_lib_thread_bss) * ++g_lib_thread_bss2; 77 | } 78 | 79 | int lib_thread_var_reloc() { 80 | return g_lib_thread_buf[0]; 81 | } 82 | -------------------------------------------------------------------------------- /tests/lib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int lib_42(); 4 | int lib_add_42_via_base(int v); 5 | int in_both_lib_and_base(); 6 | void lib_use_stderr(); 7 | int lib_init_value(); 8 | int lib_base_init_value(); 9 | int lib_base_global(); 10 | int lib_base_vf(); 11 | int lib_base_thread_var(); 12 | int lib_base_thread_var_reloc(); 13 | int lib_thread_var(); 14 | int lib_thread_var_reloc(); 15 | -------------------------------------------------------------------------------- /tests/runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ ! -z $1 ]; then 6 | cd "$1" 7 | fi 8 | 9 | out=out 10 | mkdir -p "${out}" 11 | 12 | sotest="${out}/sotest" 13 | mkdir -p "${sotest}" 14 | ./sold tests/libtest_lib.so "${sotest}/libtest_lib.so" 15 | cp tests/test_exe "${sotest}/test_exe" 16 | "${sotest}/test_exe" lib 17 | -------------------------------------------------------------------------------- /third_party/glog.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | project(glog-download NONE) 3 | 4 | include(ExternalProject) 5 | ExternalProject_Add(glog 6 | GIT_REPOSITORY https://github.com/google/glog.git 7 | GIT_TAG v0.4.0 8 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/glog" 9 | BINARY_DIR "" 10 | CONFIGURE_COMMAND "" 11 | BUILD_COMMAND "" 12 | INSTALL_COMMAND "" 13 | TEST_COMMAND "" 14 | CMAKE_ARGS 15 | -DCMAKE_INSTALL_MESSAGE=LAZY 16 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 17 | ) 18 | -------------------------------------------------------------------------------- /third_party/pybind11.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | project(glog-download NONE) 3 | 4 | include(ExternalProject) 5 | ExternalProject_Add(pybind11 6 | GIT_REPOSITORY https://github.com/pybind/pybind11 7 | GIT_TAG v2.6.2 8 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/pybind11" 9 | BINARY_DIR "" 10 | CONFIGURE_COMMAND "" 11 | BUILD_COMMAND "" 12 | INSTALL_COMMAND "" 13 | TEST_COMMAND "" 14 | CMAKE_ARGS 15 | -DCMAKE_INSTALL_MESSAGE=LAZY 16 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 17 | ) 18 | -------------------------------------------------------------------------------- /tools/listup_duplicated_syms.py: -------------------------------------------------------------------------------- 1 | # How to use 2 | # readelf --dyn-syms --wide hoge.so | python3 listup_duplicated_syms.py 3 | 4 | import sys 5 | 6 | alllines = sys.stdin.readlines() 7 | head = alllines[:3] 8 | lines = alllines[4:] 9 | symcount = dict() 10 | 11 | for l in lines: 12 | ws = l.split() 13 | name = ws[7].split('@')[0] 14 | if name in symcount: 15 | symcount[name] += 1 16 | else: 17 | symcount[name] = 1 18 | 19 | for l in head: 20 | print(l, end="") 21 | 22 | for l in lines: 23 | ws = l.split() 24 | name = ws[7].split('@')[0] 25 | if symcount[name] >= 2: 26 | print(l,end="") 27 | -------------------------------------------------------------------------------- /tools/relocation-list-up.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # List up all relocation entries for the given shared object. 3 | # When you give the second argument, this script filter the output with it. 4 | # ./relocation-check.sh SHARED_OBJECT [RELOCATION_ENTRY] 5 | 6 | depends=$(ldd $1 | awk 'NR>1' | awk '{print $3}') 7 | 8 | for d in $1 ${depends} 9 | do 10 | if [ -z $2 ] 11 | then 12 | relos=$(readelf -r ${d}) 13 | else 14 | relos=$(readelf -r ${d} | grep $2) 15 | fi 16 | IFS=$'\n' 17 | for r in ${relos} 18 | do 19 | echo ${d} ${r} 20 | done 21 | done 22 | -------------------------------------------------------------------------------- /tools/resolve_addr.py: -------------------------------------------------------------------------------- 1 | # Usage: 2 | # 3 | # $ python3 resolve_addr.py sold.INFO /proc/27136/maps 0x7f41080088c9 4 | # 5 | 6 | 7 | import argparse 8 | import re 9 | 10 | 11 | def parse_log(log_filename): 12 | loads = [] 13 | for line in open(log_filename): 14 | matched = re.search(r'\] PT_LOAD mapping: (.*)', line) 15 | if not matched: 16 | continue 17 | load = {} 18 | for tok in matched[1].split(" "): 19 | key, value = tok.split("=", 1) 20 | if key != 'name': 21 | value = int(value) 22 | load[key] = value 23 | loads.append(load) 24 | return loads 25 | 26 | 27 | def parse_maps(maps_filename): 28 | base_addrs = {} 29 | maps = [] 30 | for line in open(maps_filename): 31 | toks = line.split() 32 | if len(toks) == 6: 33 | addrs, perms, off, dev, inode, path = toks 34 | else: 35 | assert len(toks) == 5 36 | addrs, perms, off, dev, inode = toks 37 | path = '' 38 | begin, end = [int(a, 16) for a in addrs.split('-')] 39 | if path not in base_addrs: 40 | base_addrs[path] = begin 41 | base = base_addrs[path] 42 | maps.append({ 43 | 'path': path, 44 | 'addr': begin, 45 | 'end': end, 46 | 'size': end - begin, 47 | 'base': base, 48 | }) 49 | return maps 50 | 51 | 52 | def show_addr(maps, addr, loads=None): 53 | print('Loaded address: %x' % addr) 54 | map_found = None 55 | for map in maps: 56 | if map['addr'] <= addr and addr < map['end']: 57 | map_found = map 58 | break 59 | else: 60 | print('Not found in maps') 61 | return 62 | 63 | print('Loaded path: %s' % map_found['path']) 64 | vaddr = addr - map['base'] 65 | print('Virtual address before reloc: %x' % vaddr) 66 | 67 | for load in loads: 68 | if load['vaddr'] > vaddr or vaddr >= load['vaddr'] + load['memsz']: 69 | continue 70 | orig_vaddr = vaddr - load['vaddr'] + load['orig_vaddr'] 71 | print('Address in %s: %x' % (load['name'], orig_vaddr)) 72 | 73 | 74 | def main(): 75 | parser = argparse.ArgumentParser() 76 | parser.add_argument('log', type=str, help="Path to the log file") 77 | parser.add_argument('maps', type=str, help="Path to the /proc//maps file") 78 | parser.add_argument('addr', type=str, help="Address to be resolved") 79 | args = parser.parse_args() 80 | 81 | loads = parse_log(args.log) 82 | maps = parse_maps(args.maps) 83 | addr = eval(args.addr) 84 | 85 | show_addr(maps, addr, loads=loads) 86 | 87 | 88 | if __name__ == "__main__": 89 | main() 90 | -------------------------------------------------------------------------------- /tools/search-symbol.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # This shellscript find all shared object which contains the specified 3 | # symbol. 4 | 5 | if [ -z $1 ] 6 | then 7 | echo You must specify the name of the symbol. 8 | exit 1 9 | fi 10 | 11 | sym=$1 12 | sos=`ldconfig -p | awk -F '=>' '{print $2}' | grep so | sort | uniq` 13 | 14 | for s in ${sos} 15 | do 16 | PRE_IFS=$IFS 17 | IFS=$'\n' 18 | for l in `readelf -s $s | grep -e ${sym} | grep -v UND` 19 | do 20 | echo ${l} in ${s} 21 | done 22 | IFS=$PRE_IFS 23 | done 24 | -------------------------------------------------------------------------------- /tools/tracer.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(__apple__) 11 | #define PTRACE_TRACEME PT_TRACE_ME 12 | #define PT_STEP PTRACE_SINGLESTEP 13 | #endif 14 | 15 | #ifdef __x86_64__ 16 | #define BP regs.rbp 17 | #define SP regs.rsp 18 | #define IP regs.rip 19 | #else 20 | #define BP regs.ebp 21 | #define SP regs.esp 22 | #define IP regs.eip 23 | #endif 24 | 25 | long checked_ptrace(enum __ptrace_request req, pid_t pid, long addr, long data, const char* req_str, const char* file, int line) { 26 | long r = ptrace(req, pid, addr, data); 27 | if (r == -1) { 28 | fprintf(stderr, "%s:%d: ptrace(%s): ", file, line, req_str); 29 | perror(""); 30 | // exit(1); 31 | } 32 | return r; 33 | } 34 | 35 | #define CHECKED_PTRACE(req, pid, addr, data) checked_ptrace(req, pid, addr, data, #req, __FILE__, __LINE__) 36 | 37 | int main(int argc, char* argv[]) { 38 | argc--; 39 | argv++; 40 | 41 | pid_t pid; 42 | if (!strcmp(argv[0], "-p")) { 43 | pid = strtol(argv[1], 0, 10); 44 | CHECKED_PTRACE(PTRACE_ATTACH, pid, 0, 0); 45 | } else { 46 | pid = fork(); 47 | if (!pid) { 48 | CHECKED_PTRACE(PTRACE_TRACEME, 0, 0, 0); 49 | execv(argv[0], argv); 50 | abort(); 51 | } 52 | } 53 | 54 | long prev = 0; 55 | while (true) { 56 | int status; 57 | wait(&status); 58 | if (!WIFSTOPPED(status)) break; 59 | 60 | struct user regs; 61 | CHECKED_PTRACE(PTRACE_GETREGS, pid, 0, (long)®s); 62 | if (prev != regs.IP) printf("%p\n", (void*)regs.IP); 63 | prev = regs.IP; 64 | 65 | CHECKED_PTRACE(PTRACE_SINGLESTEP, pid, 0, 0); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /ubuntu18.04-gpu.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMAGE_NAME 2 | FROM ${IMAGE_NAME} 3 | 4 | # See https://github.com/NVIDIA/nvidia-docker/issues/1631 5 | RUN rm -f /etc/apt/sources.list.d/cuda.list && \ 6 | rm -f /etc/apt/sources.list.d/nvidia-ml.list && \ 7 | apt-key del 7fa2af80 8 | RUN apt-get update 9 | RUN apt-get install -y ninja-build cmake gcc g++ git python3 python3-distutils python3-dev python3-pip g++-aarch64-linux-gnu qemu qemu-system-aarch64 qemu-user rsync software-properties-common wget 10 | 11 | RUN wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-keyring_1.0-1_all.deb 12 | RUN dpkg -i cuda-keyring_1.0-1_all.deb 13 | RUN add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /" 14 | RUN apt-get update 15 | RUN apt-get install -y libcudnn8-dev 16 | 17 | ARG TORCH_VERSION 18 | ENV TORCH_VERSION=${TORCH_VERSION} 19 | RUN pip3 install pytest numpy torch==${TORCH_VERSION} -f https://download.pytorch.org/whl/torch_stable.html 20 | 21 | COPY . /sold 22 | WORKDIR /sold 23 | RUN rm -rf build 24 | RUN mkdir build && cd build && cmake -DTorch_DIR=$(python3 -c "import site; print (site.getsitepackages()[0])")/torch/share/cmake/Torch -GNinja -DSOLD_PYBIND_TEST=ON -DSOLD_LIBTORCH_TEST=ON .. 25 | RUN cmake --build build 26 | RUN cd build && ctest 27 | -------------------------------------------------------------------------------- /ubuntu18.04.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMAGE_NAME 2 | FROM ${IMAGE_NAME} 3 | 4 | RUN apt-get update 5 | RUN apt-get install -y ninja-build cmake gcc g++ git python3 python3-distutils python3-dev python3-pip g++-aarch64-linux-gnu qemu qemu-system-aarch64 qemu-user rsync software-properties-common wget 6 | 7 | ARG TORCH_VERSION 8 | ENV TORCH_VERSION=${TORCH_VERSION} 9 | RUN pip3 install pytest numpy torch==${TORCH_VERSION} -f https://download.pytorch.org/whl/torch_stable.html 10 | 11 | COPY . /sold 12 | WORKDIR /sold 13 | RUN rm -rf build 14 | RUN mkdir build && cd build && cmake -DTorch_DIR=$(python3 -c "import site; print (site.getsitepackages()[0])")/torch/share/cmake/Torch -GNinja -DSOLD_PYBIND_TEST=ON -DSOLD_LIBTORCH_TEST=ON .. 15 | RUN cmake --build build 16 | RUN cd build && ctest 17 | -------------------------------------------------------------------------------- /ubuntu20.04.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | ENV DEBIAN_FRONTEND=noninteractive 3 | RUN apt-get update 4 | RUN apt-get install -y ninja-build cmake gcc g++ git python3 python3-distutils python3-dev python3-pip g++-aarch64-linux-gnu qemu qemu-system-aarch64 qemu-user rsync 5 | RUN pip3 install pytest numpy torch==1.11.0+cpu -f https://download.pytorch.org/whl/torch_stable.html 6 | COPY . /sold 7 | WORKDIR /sold 8 | RUN rm -rf build 9 | RUN mkdir build && cd build && cmake -DTorch_DIR=$(python3 -c "import site; print (site.getsitepackages()[0])")/torch/share/cmake/Torch -GNinja -DSOLD_PYBIND_TEST=ON -DSOLD_LIBTORCH_TEST=ON .. 10 | RUN cmake --build build 11 | RUN cd build && ctest 12 | -------------------------------------------------------------------------------- /ubuntu22.04.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | ENV DEBIAN_FRONTEND=noninteractive 3 | RUN apt-get update 4 | RUN apt-get install -y ninja-build cmake gcc g++ git python3 python3-distutils python3-dev python3-pip g++-aarch64-linux-gnu qemu qemu-system-aarch64 qemu-user rsync 5 | RUN pip3 install pytest numpy torch==1.11.0+cpu -f https://download.pytorch.org/whl/torch_stable.html 6 | COPY . /sold 7 | WORKDIR /sold 8 | RUN rm -rf build 9 | RUN mkdir build && cd build && cmake -DTorch_DIR=$(python3 -c "import site; print (site.getsitepackages()[0])")/torch/share/cmake/Torch -GNinja -DSOLD_PYBIND_TEST=ON -DSOLD_LIBTORCH_TEST=ON .. 10 | RUN cmake --build build 11 | RUN cd build && ctest 12 | -------------------------------------------------------------------------------- /version_builder.cc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #include "version_builder.h" 17 | 18 | void VersionBuilder::Add(Elf_Versym versym, const std::string& soname, const std::string& version, StrtabBuilder& strtab, 19 | const unsigned char st_info) { 20 | // When the corresponding shared object doesn't have version information, 21 | // we cannot help inferring it from st_info. 22 | if (versym == NO_VERSION_INFO) { 23 | versym = ((ELF_ST_BIND(st_info) != STB_LOCAL) ? VER_NDX_GLOBAL : VER_NDX_LOCAL); 24 | } 25 | 26 | if (is_special_ver_ndx(versym)) { 27 | CHECK(soname.empty() && version.empty()) << " excess soname or version information is given."; 28 | LOG(INFO) << "VersionBuilder::" << special_ver_ndx_to_str(versym); 29 | 30 | vers.push_back(versym); 31 | } else { 32 | CHECK(!soname.empty() && !version.empty()) << " versym=" << special_ver_ndx_to_str(versym); 33 | 34 | auto found_filename = soname_to_filename_.find(soname); 35 | CHECK(found_filename != soname_to_filename_.end()) 36 | << soname << " does not exists in soname_to_filename." << SOLD_LOG_KEY(soname) << SOLD_LOG_KEY(version); 37 | std::string filename = found_filename->second; 38 | 39 | strtab.Add(filename); 40 | strtab.Add(version); 41 | 42 | if (data.find(filename) != data.end()) { 43 | if (data[filename].find(version) != data[filename].end()) { 44 | ; 45 | } else { 46 | data[filename][version] = vernum; 47 | vernum++; 48 | } 49 | } else { 50 | std::map ma; 51 | ma[version] = vernum; 52 | data[filename] = ma; 53 | vernum++; 54 | } 55 | LOG(INFO) << "VersionBuilder::Add(" << data[filename][version] << ", " << soname << ", " << version << ")"; 56 | vers.push_back(data[filename][version]); 57 | } 58 | } 59 | 60 | uintptr_t VersionBuilder::SizeVerneed() const { 61 | uintptr_t s = 0; 62 | for (const auto& m1 : data) { 63 | s += sizeof(Elf_Verneed); 64 | for (const auto& m2 : m1.second) { 65 | s += sizeof(Elf_Vernaux); 66 | } 67 | } 68 | return s; 69 | } 70 | 71 | void VersionBuilder::EmitVersym(FILE* fp) { 72 | if (data.size() > 0) { 73 | for (auto v : vers) { 74 | CHECK(fwrite(&v, sizeof(v), 1, fp) == 1); 75 | } 76 | } 77 | } 78 | 79 | void VersionBuilder::EmitVerneed(FILE* fp, StrtabBuilder& strtab) { 80 | int n_verneed = 0; 81 | for (const auto& m1 : data) { 82 | n_verneed++; 83 | 84 | Elf_Verneed v; 85 | v.vn_version = VER_NEED_CURRENT; 86 | v.vn_cnt = m1.second.size(); 87 | v.vn_file = strtab.GetPos(m1.first); 88 | v.vn_aux = sizeof(Elf_Verneed); 89 | v.vn_next = (n_verneed == data.size()) ? 0 : sizeof(Elf_Verneed) + m1.second.size() * sizeof(Elf_Vernaux); 90 | 91 | CHECK(fwrite(&v, sizeof(v), 1, fp) == 1); 92 | 93 | int n_vernaux = 0; 94 | for (const auto& m2 : m1.second) { 95 | n_vernaux++; 96 | 97 | Elf_Vernaux a; 98 | a.vna_hash = CalcHash(m2.first); 99 | a.vna_flags = VER_FLG_WEAK; 100 | a.vna_other = m2.second; 101 | a.vna_name = strtab.GetPos(m2.first); 102 | a.vna_next = (n_vernaux == m1.second.size()) ? 0 : sizeof(Elf_Vernaux); 103 | 104 | CHECK(fwrite(&a, sizeof(a), 1, fp) == 1); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /version_builder.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The sold authors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program. If not, see . 15 | 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include "hash.h" 23 | #include "strtab_builder.h" 24 | #include "utils.h" 25 | 26 | class VersionBuilder { 27 | public: 28 | void Add(Elf_Versym versym, const std::string& soname, const std::string& version, StrtabBuilder& strtab, const unsigned char st_info); 29 | 30 | uintptr_t SizeVersym() const { return (data.size() > 0) ? vers.size() * sizeof(Elf_Versym) : 0; } 31 | 32 | uintptr_t SizeVerneed() const; 33 | 34 | int NumVerneed() const { return data.size(); } 35 | 36 | void EmitVersym(FILE* fp); 37 | 38 | void EmitVerneed(FILE* fp, StrtabBuilder& strtab); 39 | 40 | void SetSonameToFilename(const std::map& soname_to_filename) { soname_to_filename_ = soname_to_filename; } 41 | 42 | private: 43 | // vernum starts from 2 because 0 and 1 are used as VER_NDX_LOCAL and VER_NDX_GLOBAL. 44 | int vernum = 2; 45 | std::map> data; 46 | std::vector vers; 47 | std::map soname_to_filename_; 48 | }; 49 | --------------------------------------------------------------------------------