├── .github └── workflows │ ├── ci.yml │ └── coverity.yml ├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── scripts ├── system_test.sh └── travis.sh ├── src ├── common.h ├── driver.c ├── hider.c └── hider.h └── tests ├── basic ├── a.c ├── run.sh └── tester.c ├── relocatable ├── a.c └── run.sh └── unhide ├── a.c └── run.sh /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # TODO: 2 | # * proper deploy (with dependencies, etc.) 3 | 4 | name: CI 5 | on: 6 | push: 7 | paths-ignore: 8 | - 'LICENSE.txt' 9 | - 'README.md' 10 | - '.gitignore' 11 | pull_request: 12 | paths-ignore: 13 | - 'LICENSE.txt' 14 | - 'README.md' 15 | - '.gitignore' 16 | jobs: 17 | Baseline: 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | os: [ubuntu-18.04, ubuntu-20.04, ubuntu-latest] 22 | cc: [gcc, clang] 23 | runs-on: ${{ matrix.os }} 24 | env: 25 | CC: ${{ matrix.cc }} 26 | steps: 27 | - uses: actions/checkout@v2 28 | - name: Run tests 29 | run: scripts/travis.sh 30 | CSA: 31 | runs-on: ubuntu-latest 32 | env: 33 | CC: clang 34 | steps: 35 | - uses: actions/checkout@v2 36 | - name: Install deps 37 | run: sudo apt-get install clang-tools 38 | - name: Run tests 39 | run: scan-build --keep-going --status-bugs scripts/travis.sh 40 | Asan: 41 | runs-on: ubuntu-latest 42 | env: 43 | CC: clang 44 | ASAN: 1 45 | steps: 46 | - uses: actions/checkout@v2 47 | - name: Run tests 48 | run: scripts/travis.sh 49 | UBsan: 50 | runs-on: ubuntu-latest 51 | env: 52 | CC: clang 53 | UBSAN: 1 54 | steps: 55 | - uses: actions/checkout@v2 56 | - name: Run tests 57 | run: scripts/travis.sh 58 | Valgrind: 59 | runs-on: ubuntu-latest 60 | env: 61 | VALGRIND: 1 62 | steps: 63 | - uses: actions/checkout@v2 64 | - name: Install deps 65 | run: sudo apt-get install valgrind 66 | - name: Run tests 67 | run: scripts/travis.sh 68 | Coverage: 69 | needs: Baseline 70 | runs-on: ubuntu-latest 71 | environment: secrets 72 | env: 73 | COVERAGE: 1 74 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 75 | steps: 76 | - uses: actions/checkout@v2 77 | - name: Run tests and upload coverage 78 | run: scripts/travis.sh 79 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | name: Coverity 2 | on: 3 | schedule: 4 | # Run on Mondays 5 | - cron: '0 5 * * MON' 6 | jobs: 7 | Coverity: 8 | runs-on: ubuntu-latest 9 | environment: secrets 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: vapier/coverity-scan-action@v0 13 | with: 14 | project: yugr%2FSymbolHider 15 | token: ${{ secrets.COVERITY_SCAN_TOKEN }} 16 | email: ${{ secrets.EMAIL }} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Vim 2 | .*swp 3 | 4 | # Binaries 5 | bin/* 6 | 7 | # GDB temp files 8 | .gdb_history 9 | 10 | # Test files 11 | a.out* 12 | lib*.so 13 | *.o 14 | libs.txt 15 | *.gcda 16 | *.gcno 17 | *.gcov 18 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Yury Gribov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Yury Gribov 2 | # 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE.txt file. 5 | 6 | CC ?= gcc 7 | DESTDIR ?= /usr/local 8 | 9 | CFLAGS = -g -Wall -Wextra -Werror 10 | LDFLAGS = -g -Wl,--warn-common 11 | 12 | ifneq (,$(COVERAGE)) 13 | DEBUG = 1 14 | CFLAGS += --coverage -DNDEBUG 15 | LDFLAGS += --coverage 16 | endif 17 | ifeq (,$(DEBUG)) 18 | CFLAGS += -O2 19 | LDFLAGS += -Wl,-O2 20 | else 21 | CFLAGS += -O0 22 | endif 23 | ifneq (,$(ASAN)) 24 | CFLAGS += -fsanitize=address -fsanitize-address-use-after-scope -U_FORTIFY_SOURCE -fno-common -D_GLIBCXX_DEBUG -D_GLIBCXX_SANITIZE_VECTOR 25 | LDFLAGS += -fsanitize=address 26 | endif 27 | ifneq (,$(UBSAN)) 28 | ifneq (,$(shell $(CXX) --version | grep clang)) 29 | # Isan is clang-only... 30 | CFLAGS += -fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer 31 | LDFLAGS += -fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer 32 | else 33 | CFLAGS += -fsanitize=undefined -fno-sanitize-recover=undefined 34 | LDFLAGS += -fsanitize=undefined -fno-sanitize-recover=undefined 35 | endif 36 | endif 37 | 38 | OBJS = bin/hider.o bin/driver.o 39 | 40 | $(shell mkdir -p bin) 41 | 42 | all: bin/sym-hider 43 | 44 | check: 45 | tests/basic/run.sh 46 | tests/relocatable/run.sh 47 | tests/unhide/run.sh 48 | @echo SUCCESS 49 | 50 | bin/sym-hider: $(OBJS) Makefile bin/FLAGS 51 | $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ 52 | 53 | bin/%.o: src/%.c Makefile bin/FLAGS 54 | $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ 55 | 56 | bin/FLAGS: FORCE 57 | if test x"$(CFLAGS) $(CXXFLAGS) $(LDFLAGS)" != x"$$(cat $@)"; then \ 58 | echo "$(CFLAGS) $(CXXFLAGS) $(LDFLAGS)" > $@; \ 59 | fi 60 | 61 | clean: 62 | rm -f bin/* 63 | find -name \*.gcov -o -name \*.gcno -o -name \*.gcda | xargs rm -rf 64 | 65 | install: 66 | mkdir -p $(DESTDIR) 67 | install bin/sym-hider $(DESTDIR)/bin 68 | 69 | .PHONY: clean all check install FORCE 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![License](http://img.shields.io/:license-MIT-blue.svg)](https://github.com/yugr/SymbolHider/blob/master/LICENSE.txt) 2 | [![Build Status](https://github.com/yugr/SymbolHider/actions/workflows/ci.yml/badge.svg)](https://github.com/yugr/SymbolHider/actions) 3 | [![codecov](https://codecov.io/gh/yugr/SymbolHider/branch/master/graph/badge.svg)](https://codecov.io/gh/yugr/SymbolHider) 4 | [![Total alerts](https://img.shields.io/lgtm/alerts/g/yugr/SymbolHider.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/yugr/SymbolHider/alerts/) 5 | [![Coverity Scan](https://scan.coverity.com/projects/yugr-SymbolHider/badge.svg)](https://scan.coverity.com/projects/yugr-SymbolHider) 6 | 7 | # What's this? 8 | 9 | SymbolHider is a simple tool which hides symbols in ELF shared library's public interface 10 | (by rewriting their visibility to `hidden`). 11 | 12 | The tool is inspired by @EmployedRussian suggestion in [Is there any way to override the -fvisibility=hidden at link time?](https://stackoverflow.com/questions/36273404/is-there-any-way-to-override-the-fvisibility-hidden-at-link-time) although I also enabled it for a more common case of fully linked binaries. 13 | 14 | # How to use 15 | 16 | To hide some symbols in a library, run tool like 17 | ``` 18 | $ sym-hider libxyz.so foo bar 19 | ``` 20 | 21 | To instead _unhide_ some symbols, run tool like 22 | ``` 23 | $ sym-hider --unhide file.o foo bar 24 | ``` 25 | (usually this will not work for already linked files i.e. executables and shlibs). 26 | 27 | For more details run 28 | ``` 29 | $ sym-hider -h 30 | ``` 31 | 32 | # TODO 33 | 34 | * Support 32-bit ELFs 35 | * Support DLL and Mach-O (is it possible?) 36 | * Hide by wildcards 37 | * More tests 38 | * Support static libs (?) 39 | * Warn on missing symbols 40 | -------------------------------------------------------------------------------- /scripts/system_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2022 Yury Gribov 4 | # 5 | # Use of this source code is governed by MIT license that can be 6 | # found in the LICENSE.txt file. 7 | # 8 | # Wrapper for ld which automatically calls implib-gen. 9 | # To enable, add it to PATH. 10 | # Flags are passed via env variable IMPLIBSO_LD_OPTIONS. 11 | 12 | # Runs hider on all installed libraries 13 | 14 | set -eu 15 | 16 | cd $(dirname $0)/.. 17 | 18 | if test "${1:-}" != noscan; then 19 | rm -f libs.txt 20 | for lib in $(find /lib /usr/lib /usr/local/lib -name \*.so\*); do 21 | if file $lib | grep -q 'ELF .* LSB shared object'; then 22 | echo $lib >> libs.txt 23 | fi 24 | done 25 | fi 26 | 27 | tmp=$(mktemp) 28 | trap "rm -f $tmp" EXIT INT 29 | 30 | for lib in $(cat libs.txt); do 31 | echo "Checking $lib..." 32 | first_sym=$(readelf --dyn-syms -W $lib | awk '/DEFAULT/{if ($8) print $8}' | head -n1) 33 | test -n "$first_sym" || continue 34 | bin/sym-hider $lib $first_sym -w -o $tmp || true 35 | bin/sym-hider $tmp $first_sym -w --unhide || true 36 | done 37 | -------------------------------------------------------------------------------- /scripts/travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2022 Yury Gribov 6 | # 7 | # Use of this source code is governed by The MIT License (MIT) 8 | # that can be found in the LICENSE.txt file. 9 | 10 | set -eu 11 | set -x 12 | 13 | cd $(dirname $0)/.. 14 | 15 | # Build 16 | 17 | make clean all 18 | 19 | # Run tests 20 | 21 | if test -n "${VALGRIND:-}"; then 22 | cp -r bin bin-real 23 | for f in $(find bin -type f -a -executable); do 24 | cat > $f < codecov.bash 42 | bash codecov.bash -Z -X gcov 43 | fi 44 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | #ifndef COMMON_H 9 | #define COMMON_H 10 | 11 | #define PREFIX "sym-hider: " 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | #include "hider.h" 9 | #include "common.h" 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | int verbose; 18 | int warn = 1; 19 | 20 | static void usage(const char *prog) { 21 | printf("\ 22 | Usage: %s [OPT]... SOFILE SYM...\n\ 23 | Hide symbols in shared library.\n\ 24 | \n\ 25 | Options:\n\ 26 | -o OFILE, --output OFILE Output result to another file.\n\ 27 | --hide Hide symbols (default).\n\ 28 | --unhide Un-hide symbols.\n\ 29 | -h, --help Print this help and exit.\n\ 30 | -v, --verbose Enable debug prints.\n\ 31 | -w, --no-warnings Disable warnings.\n\ 32 | ", prog); 33 | exit(0); 34 | } 35 | 36 | int main(int argc, char *argv[]) { 37 | const char *me = basename((char *)argv[0]); 38 | 39 | const char *out_file = NULL; 40 | int hide = 1; 41 | while (1) { 42 | static struct option long_opts[] = { 43 | {"help", no_argument, 0, 'h'}, 44 | #define OPT_HIDE 1 45 | {"hide", no_argument, 0, OPT_HIDE}, 46 | {"no-warnings", no_argument, 0, 'w'}, 47 | {"output", required_argument, 0, 'o'}, 48 | #define OPT_UNHIDE 2 49 | {"unhide", no_argument, 0, OPT_UNHIDE}, 50 | {"verbose", no_argument, 0, 'v'}, 51 | }; 52 | 53 | int opt_index = 0; 54 | int c = getopt_long(argc, argv, "ho:vw", long_opts, &opt_index); 55 | 56 | if (c == -1) 57 | break; 58 | 59 | switch (c) { 60 | case 'o': 61 | out_file = optarg; 62 | break; 63 | case 'v': 64 | ++verbose; 65 | break; 66 | case 'h': 67 | usage(me); 68 | break; 69 | case OPT_HIDE: 70 | hide = 1; 71 | break; 72 | case OPT_UNHIDE: 73 | hide = 0; 74 | break; 75 | case 'w': 76 | warn = 0; 77 | break; 78 | default: 79 | abort(); 80 | } 81 | } 82 | 83 | if (optind >= argc) { 84 | fprintf(stderr, "error: ELF file not specified in command line...\n"); 85 | return 0; 86 | } 87 | 88 | const char *file = argv[optind++]; 89 | 90 | if (optind >= argc) { 91 | fprintf(stderr, "error: no symbols specified in command line...\n"); 92 | return 0; 93 | } 94 | 95 | size_t nsyms = argc - optind; 96 | const char **syms = malloc(sizeof(const char *) * nsyms); 97 | memcpy(syms, argv + optind, sizeof(const char *) * nsyms); 98 | 99 | if (!out_file) 100 | out_file = file; 101 | 102 | hide_symbols(file, out_file, syms, nsyms, hide); 103 | 104 | free(syms); 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /src/hider.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | #include "common.h" 9 | #include "hider.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | extern int warn; 24 | 25 | void hide_symbols(const char *file, const char *out_file, 26 | const char **hidden_syms, size_t num_hidden_syms, 27 | int hide_or_unhide) { 28 | int fd = open(file, O_RDONLY); 29 | if (fd < 0) { 30 | fprintf(stderr, PREFIX "failed to open %s: %s\n", file, strerror(errno)); 31 | exit(1); 32 | } 33 | 34 | struct stat st; 35 | if (fstat(fd, &st) < 0) { 36 | fprintf(stderr, PREFIX "failed to determine size of %s: %s\n", file, strerror(errno)); 37 | exit(1); 38 | } 39 | 40 | const off_t file_size = st.st_size; 41 | char *start = malloc(file_size); 42 | ssize_t nread = read(fd, start, file_size); 43 | if (nread < 0 || nread != file_size) { 44 | fprintf(stderr, PREFIX "failed to read contents of %s\n", file); 45 | exit(1); 46 | } 47 | 48 | close(fd); 49 | 50 | // Read header 51 | 52 | const Elf64_Ehdr *ehdr = (const Elf64_Ehdr *)start; 53 | 54 | switch (ehdr->e_ident[EI_CLASS]) { 55 | case ELFCLASS64: 56 | break; 57 | default: 58 | fprintf(stderr, PREFIX "32-bit ELFs are not yet supported\n"); 59 | exit(1); 60 | } 61 | 62 | switch (ehdr->e_type) { 63 | case ET_REL: 64 | break; 65 | case ET_DYN: 66 | case ET_EXEC: 67 | if (!hide_or_unhide && warn) 68 | fprintf(stderr, PREFIX "warning: --unhide will likely not work for already linked files\n"); 69 | break; 70 | default: 71 | fprintf(stderr, PREFIX "bad ELF type in %s: only ET_{REL,DYN,EXEC} are supported\n", file); 72 | exit(1); 73 | } 74 | const int is_reloc = ehdr->e_type == ET_REL; 75 | 76 | // Find symtab 77 | 78 | const Elf64_Shdr *shdr = (const Elf64_Shdr *)(start + ehdr->e_shoff); 79 | Elf64_Half shnum = ehdr->e_shnum; 80 | 81 | Elf64_Sym *symtab = NULL; 82 | const char *strtab = NULL; 83 | Elf64_Xword sym_count = 0; 84 | 85 | for (Elf64_Half i = 0; i < shnum; ++i) { 86 | if (shdr[i].sh_type != (is_reloc ? SHT_SYMTAB : SHT_DYNSYM)) 87 | continue; 88 | 89 | if (symtab) { 90 | fprintf(stderr, PREFIX "multiple .dynsym/.symtab sections in %s\n", file); 91 | exit(1); 92 | } 93 | 94 | strtab = start + shdr[shdr[i].sh_link].sh_offset; 95 | 96 | symtab = (Elf64_Sym *)(start + shdr[i].sh_offset); 97 | sym_count = shdr[i].sh_size / shdr[i].sh_entsize; 98 | assert(shdr[i].sh_entsize == sizeof(Elf64_Sym)); 99 | } 100 | 101 | if (!symtab) { 102 | fprintf(stderr, PREFIX "failed to locate .dynsym/.symtab section in %s\n", file); 103 | exit(1); 104 | } 105 | 106 | // Locate target symbols and change visibility 107 | 108 | for (Elf64_Xword i = 0; i < sym_count; ++i) { 109 | Elf64_Sym *sym = &symtab[i]; 110 | if (! (start <= (char *)sym && (char *)sym < start + file_size)) { 111 | fprintf(stderr, PREFIX "invalid symbol table offset in %s at symbol %d\n", file, (int)i); 112 | exit(1); 113 | } 114 | const char *name = &strtab[sym->st_name]; 115 | for (size_t j = 0; j < num_hidden_syms; ++j) { 116 | if (0 == strcmp(hidden_syms[j], name)) { 117 | sym->st_other &= ~0x3; 118 | sym->st_other |= hide_or_unhide ? STV_HIDDEN : STV_DEFAULT; 119 | // sym->st_info = ELF64_ST_INFO(STB_LOCAL, ELF64_ST_TYPE(sym->st_info)); TODO: do we need this ?! 120 | break; 121 | } 122 | } 123 | } 124 | 125 | // Write results 126 | 127 | int out_fd = open(out_file, O_WRONLY | O_CREAT, 0755); 128 | if (out_fd < 0) { 129 | fprintf(stderr, PREFIX "failed to open %s for writing: %s\n", out_file, strerror(errno)); 130 | exit(1); 131 | } 132 | 133 | ssize_t written = write(out_fd, start, file_size); 134 | if (written < 0 || written < file_size) { 135 | fprintf(stderr, PREFIX "failed to write data to output file %s: %s\n", out_file, strerror(errno)); 136 | exit(1); 137 | } 138 | 139 | close(out_fd); 140 | 141 | free(start); 142 | } 143 | -------------------------------------------------------------------------------- /src/hider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | #ifndef HIDER_H 9 | #define HIDER_H 10 | 11 | #include 12 | 13 | void hide_symbols(const char *file, const char *out_file, 14 | const char **syms, size_t nsyms, int hide_or_unhide); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /tests/basic/a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | void foo() {} 9 | -------------------------------------------------------------------------------- /tests/basic/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | if test -n "${TRAVIS:-}" -o -n "${GITHUB_ACTIONS:-}"; then 6 | set -x 7 | fi 8 | 9 | cd $(dirname $0) 10 | 11 | CC=${CC:-gcc} 12 | 13 | $CC a.c -fPIC -shared -o liba.so 14 | $CC tester.c -Wl,--no-as-needed liba.so -D_GNU_SOURCE -ldl 15 | 16 | export LD_LIBRARY_PATH=$PWD:${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} 17 | 18 | readelf -W --dyn-syms liba.so | grep 'DEFAULT.*foo' 19 | ./a.out | grep "Found foo" 20 | 21 | ../../bin/sym-hider liba.so foo 22 | readelf -W --dyn-syms liba.so | grep 'HIDDEN.*foo' 23 | ! ./a.out | grep "Found foo" 24 | -------------------------------------------------------------------------------- /tests/basic/tester.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | int main() { 13 | void *ptr = dlsym(RTLD_DEFAULT, "foo"); 14 | if (ptr) { 15 | puts("Found foo"); 16 | } 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /tests/relocatable/a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | void foo() {} 9 | -------------------------------------------------------------------------------- /tests/relocatable/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | if test -n "${TRAVIS:-}" -o -n "${GITHUB_ACTIONS:-}"; then 6 | set -x 7 | fi 8 | 9 | cd $(dirname $0) 10 | 11 | CC=${CC:-gcc} 12 | 13 | $CC a.c -c -fPIC 14 | 15 | readelf -sW a.o | grep 'DEFAULT.*foo' 16 | 17 | ../../bin/sym-hider a.o foo 18 | readelf -sW a.o | grep 'HIDDEN.*foo' 19 | -------------------------------------------------------------------------------- /tests/unhide/a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Yury Gribov 3 | * 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE.txt file. 6 | */ 7 | 8 | void foo() {} 9 | -------------------------------------------------------------------------------- /tests/unhide/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | if test -n "${TRAVIS:-}" -o -n "${GITHUB_ACTIONS:-}"; then 6 | set -x 7 | fi 8 | 9 | cd $(dirname $0) 10 | 11 | CC=${CC:-gcc} 12 | 13 | $CC a.c -c -fPIC -fvisibility=hidden 14 | 15 | readelf -sW a.o | grep 'HIDDEN.*foo' 16 | 17 | ../../bin/sym-hider --unhide a.o foo 18 | readelf -sW a.o | grep 'DEFAULT.*foo' 19 | --------------------------------------------------------------------------------