GCC : undefined reference to "__asan_init_v1"

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

Answers (1)

Mike Kinghan
Mike Kinghan

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

Related Questions