Reputation: 1112
I want to compile my C99 project with the flag -fsanitize=address
. I need to use CMake and to compile with gcc on a Centos 7 distribution.
I currently have gcc 7.3.1 and cmake 3.13.4.
I added the -fsanitize=address
flag in the compilation flags list and in the linker, but it still fails to compile with the following error:
[ 6%] Building C object CMakeFiles/last.dir/src/ast/ast.c.o
[ 13%] Building C object CMakeFiles/last.dir/src/ast/ast_printer.c.o
[ 20%] Building C object CMakeFiles/last.dir/src/ast/cleaner.c.o
[ 26%] Linking C static library liblast.a
[ 26%] Built target last
[ 33%] Building C object CMakeFiles/lexecution.dir/src/execution/exec_parser.c.o
[ 40%] Building C object CMakeFiles/lexecution.dir/src/execution/exec_utils.c.o
[ 46%] Building C object CMakeFiles/lexecution.dir/src/execution/exec_func.c.o
[ 53%] Building C object CMakeFiles/lexecution.dir/src/execution/exec_parser_options.c.o
[ 60%] Linking C static library liblexecution.a
[ 60%] Built target lexecution
[ 66%] Building C object CMakeFiles/lutils.dir/tests/utils/utils.c.o
[ 73%] Linking C static library liblutils.a
[ 73%] Built target lutils
[ 80%] Building C object CMakeFiles/lhist.dir/src/history/history.c.o
[ 86%] Linking C static library liblhist.a
[ 86%] Built target lhist
[ 93%] Building C object CMakeFiles/42sh.dir/src/execution/exec_42sh.c.o
[100%] Linking C executable 42sh
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libasan_preinit.o:(.preinit_array+0x0) : undefined reference to « __asan_init_v1 »
CMakeFiles/42sh.dir/src/execution/exec_42sh.c.o : In function « _GLOBAL__sub_I_00099_1_flag » :
/home/lyro/Documents/customshell/src/execution/exec_42sh.c:304 : undefined reference to « __asan_init_v1 »
liblexecution.a(exec_parser.c.o) : In function « _GLOBAL__sub_I_00099_1_parser_new_from_string » :
/home/lyro/Documents/customshell/src/execution/exec_parser.c:1105 : undefined reference to « __asan_init_v1 »
liblexecution.a(exec_utils.c.o) : In function « _GLOBAL__sub_I_00099_0_get_args_array » :
/home/lyro/Documents/customshell/src/execution/exec_utils.c:242 : undefined reference to « __asan_init_v1 »
liblexecution.a(exec_func.c.o) : In function « _GLOBAL__sub_I_00099_1_exec_ast » :
/home/lyro/Documents/customshell/src/execution/exec_func.c:187 : undefined reference to « __asan_init_v1 »
liblexecution.a(exec_parser_options.c.o):/home/lyro/Documents/customshell/src/execution/exec_parser_options.c:149 : more undefined references to « __asan_init_v1 »
collect2: error: ld returned 1 execution state code
make[2]: *** [42sh] Error 1
make[1]: *** [CMakeFiles/42sh.dir/all] Error 2
make: *** [all] Error 2
Here is my CMakeLists.txt
file, I can't find what I am missing..
cmake_minimum_required(VERSION 3.0)
project(42SH LANGUAGES C)
add_compile_options(-Wall -Wextra -Werror -pedantic -fsanitize=address -g -std=c99)
add_library(last ${CMAKE_SOURCE_DIR}/src/ast/ast.c ${CMAKE_SOURCE_DIR}/src/ast/ast_printer.c ${CMAKE_SOURCE_DIR}/src/ast/cleaner.c)
target_include_directories(last PUBLIC ${CMAKE_SOURCE_DIR}/src/ast)
add_library(lutils ${CMAKE_SOURCE_DIR}/tests/utils/utils.c)
target_include_directories(lutils PUBLIC ${CMAKE_SOURCE_DIR}/tests/utils)
target_link_libraries(lutils -fsanitize=address lexecution)
add_library(lexecution ${CMAKE_SOURCE_DIR}/src/execution/exec_parser.c ${CMAKE_SOURCE_DIR}/src/execution/exec_utils.c ${CMAKE_SOURCE_DIR}/src/execution/exec_func.c ${CMAKE_SOURCE_DIR}/src/execution/exec_parser_options.c)
target_include_directories(lexecution PUBLIC ${CMAKE_SOURCE_DIR}/src/ast)
target_link_libraries(lexecution -fsanitize=address last)
add_library(lhist ${CMAKE_SOURCE_DIR}/src/history/history.c)
target_include_directories(lhist PUBLIC ${CMAKE_SOURCE_DIR}/src/history)
add_executable(42sh src/execution/exec_42sh.c)
target_link_libraries(42sh -fsanitize=address lexecution)
target_link_libraries(42sh -fsanitize=address lutils)
target_link_libraries(42sh -fsanitize=address last)
target_link_libraries(42sh -fsanitize=address lhist)
add_custom_target(submit
COMMENT "Compiled for submission. Sanitizers ON."
COMMENT "Don't use Valgrind on this executable. It will not work."
DEPENDS 42sh
)
add_custom_target(tests
COMMAND pytest ${CMAKE_SOURCE_DIR}/tests
COMMENT "Running testsuite..."
DEPENDS 42sh
)
add_custom_target(doc
COMMENT "Compiling documentation"
COMMAND doxygen ${CMAKE_SOURCE_DIR}/doc/Doxyfile
COMMENT "Compiled documentation"
)
Upvotes: 3
Views: 8160
Reputation: 61575
Your toolchain is somewhat confused about which version of GCC it is and the linkage failure is one consequence of that confusion.
You tell us you are using GCC 7.3.1, but the first of the unresolved references to __asan_init_v1
:
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libasan_preinit.o:(.preinit_array+0x0) : undefined reference to « __asan_init_v1
shows that the gcc
that invoked the linkage with -fsanitize=address
linked the address santitizer initialization code
from your installation of GCC 4.8.5.
In GCC 7, the file libasan_preinit.o
makes no references to __asan_init_v1
, as seen on
the laptop I'm working on just now:
$ nm /usr/lib/gcc/x86_64-linux-gnu/7/libasan_preinit.o
U __asan_init
0000000000000000 D __local_asan_preinit
It calls __asan_init
, which is indeed defined in the toolchain's libasan
:
$ nm -D /usr/lib/gcc/x86_64-linux-gnu/7/libasan.so | grep __asan_init
00000000000ecdb0 T __asan_init
On the other hand, in GCC 4.8.5, libasan
did not define the function __asan_init
and did define __asan_init_v1
:
:~/Downloads/gcc-4.8.5$ grep -r '__asan_init_v'
gcc/ChangeLog: * sanitizer.def: Rename __asan_init to __asan_init_v1.
gcc/sanitizer.def:DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v1",
libsanitizer/asan/asan_interface_internal.h: void __asan_init_v1() SANITIZER_INTERFACE_ATTRIBUTE;
libsanitizer/asan/asan_interface_internal.h: #define __asan_init __asan_init_v1
There, __asan_init
was just an internal #define
aliasing the real function __asan_init_v1
, as
per libsanitizer/asan/asan_interface_internal.h
, but in that file in GCC 7
// This function should be called at the very beginning of the process,
// before any instrumented code is executed and before any call to malloc.
SANITIZER_INTERFACE_ATTRIBUTE void __asan_init();
it is a real function, as reported by nm
.
So the thrust of the evidence is that you are linking against the libasan
of GCC 7.3.1
but also linking the library initialization code of GCC 4.8.5. I have no visibility of
how you've landed in this GCC version mash-up - could be a packaging bug, for all I know - but
you'll have to fix that to solve these linkage failures.
Upvotes: 10