GCC: неопределенная ссылка на "__asan_init_v1" - PullRequest
0 голосов
/ 25 марта 2019

Я хочу скомпилировать свой проект C99 с флагом -fsanitize=address. Мне нужно использовать CMake и скомпилировать с gcc в дистрибутиве Centos 7.

В настоящее время у меня есть gcc 7.3.1 и cmake 3.13.4 .

Я добавил флаг -fsanitize=address в список флагов компиляции и в компоновщик, но он все равно не может скомпилироваться со следующей ошибкой:

[ 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

Вот мой CMakeLists.txt файл, я не могу найти то, что мне не хватает ..

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"
)

1 Ответ

2 голосов
/ 26 марта 2019

Ваш инструментарий несколько озадачен тем, какая версия GCC и сбой связи является одним из следствий этой путаницы.

Вы говорите нам, что используете GCC 7.3.1, но первая из неразрешенных ссылок на __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

показывает, что gcc, который вызвал связь с -fsanitize=address, связал код инициализации сантитизатора адреса с вашей установки GCC 4.8.5.

В GCC 7 файл libasan_preinit.o не содержит ссылок на __asan_init_v1, как видно на ноутбук, над которым я сейчас работаю:

$ nm /usr/lib/gcc/x86_64-linux-gnu/7/libasan_preinit.o
                 U __asan_init
0000000000000000 D __local_asan_preinit

Он вызывает __asan_init, что действительно определено в libasan цепочки инструментов:

$ nm -D /usr/lib/gcc/x86_64-linux-gnu/7/libasan.so | grep __asan_init
00000000000ecdb0 T __asan_init

С другой стороны, в GCC 4.8.5 libasan сделал не определил функцию __asan_init и сделал определить __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

Там, __asan_init был просто внутренний #define, который совмещал действительную функцию __asan_init_v1, как за libsanitizer/asan/asan_interface_internal.h, но в этот файл в 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();

это реальная функция, как сообщает nm.

Таким образом, основа доказательства состоит в том, что вы связываетесь с libasan GCC 7.3.1. но также связывание кода инициализации библиотеки GCC 4.8.5. У меня нет видимости как вы попали в эту версию GCC - насколько я знаю, может быть ошибкой упаковки - но вам нужно будет исправить это, чтобы устранить эти ошибки связи.

...