I have built pdfium with thread sanitizer enabled. To do this I have followed these instructions:
git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git'
export PATH="${PWD}/depot_tools:${PATH}"
gclient config --unmanaged https://pdfium.googlesource.com/pdfium.git
cd pdfium
gn args out/tsan-release
ninja -C out/tsan-release
I have provided gn
with the following arguments:
pdf_enable_xfa = false
pdf_enable_v8 = false
is_component_build = false
is_debug = false
is_tsan=true
pdf_is_complete_lib=true
The build process succeeds by producing a static libpdfium.a
library. Then, to use this in my project I tested this small CMake example:
cmake_minimum_required(VERSION 3.20)
project(TestPdfium)
# add pdfium library
include(FindPackageHandleStandardArgs)
find_path(PDFium_INCLUDE_DIR
NAMES "fpdfview.h"
PATHS "${CMAKE_CURRENT_SOURCE_DIR}"
PATH_SUFFIXES "include"
)
find_library(PDFium_LIBRARY
NAMES "pdfium"
PATHS "${CMAKE_CURRENT_SOURCE_DIR}"
PATH_SUFFIXES "lib")
add_library(pdfium STATIC IMPORTED)
message(STATUS "Found pdfium library at ${PDFium_LIBRARY}")
set_target_properties(pdfium
PROPERTIES
IMPORTED_LOCATION "${PDFium_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${PDFium_INCLUDE_DIR};${PDFium_INCLUDE_DIR}/cpp"
)
add_executable(Test main.cpp)
target_link_libraries(Test PRIVATE pdfium)
However, when running the build (with cmake -DCMAKE_CXX_FLAGS="-fsanitize=thread"
) I get a lot of linking errors like these:
/usr/bin/ld: ../libpdfium.a(dwt.o):./../../third_party/libopenjpeg/dwt.c:1305: more undefined references to `__tsan_memcpy' follow
/usr/bin/ld: ../libpdfium.a(dwt.o): in function `opj_dwt_fetch_cols_vertical_pass':
./../../third_party/libopenjpeg/dwt.c:1278: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/dwt.c:1266: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/dwt.c:1266: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/dwt.c:1266: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(dwt.o): in function `opj_dwt_deinterleave_v_cols':
./../../third_party/libopenjpeg/dwt.c:1305: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/dwt.c:1305: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(dwt.o):./../../third_party/libopenjpeg/dwt.c:1305: more undefined references to `__tsan_memcpy' follow
/usr/bin/ld: ../libpdfium.a(invert.o): in function `opj_matrix_inversion_f':
./../../third_party/libopenjpeg/invert.c:87: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(invert.o): in function `opj_lupDecompose':
./../../third_party/libopenjpeg/invert.c:165: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/invert.c:166: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/invert.c:167: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(invert.o): in function `opj_lupInvert':
./../../third_party/libopenjpeg/invert.c:284: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(sparse_array.o): in function `opj_sparse_array_int32_read_or_write':
./../../third_party/libopenjpeg/sparse_array.c:175: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:175: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:175: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:175: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:175: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(sparse_array.o):./../../third_party/libopenjpeg/sparse_array.c:255: more undefined references to `__tsan_memcpy' follow
/usr/bin/ld: ../libpdfium.a(sparse_array.o): in function `opj_sparse_array_int32_read_or_write':
./../../third_party/libopenjpeg/sparse_array.c:149: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:149: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:149: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:149: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:149: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(sparse_array.o):./../../third_party/libopenjpeg/sparse_array.c:149: more undefined references to `__tsan_memset' follow
/usr/bin/ld: ../libpdfium.a(sparse_array.o): in function `opj_sparse_array_int32_read_or_write':
./../../third_party/libopenjpeg/sparse_array.c:181: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:181: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:181: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:181: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/sparse_array.c:181: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(sparse_array.o):./../../third_party/libopenjpeg/sparse_array.c:261: more undefined references to `__tsan_memcpy' follow
/usr/bin/ld: ../libpdfium.a(t1.o): in function `opj_t1_clbl_decode_processor':
./../../third_party/libopenjpeg/t1.c:1647: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(t1.o): in function `opj_t1_decode_cblk':
./../../third_party/libopenjpeg/t1.c:2039: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(t1.o): in function `opj_t1_allocate_buffers':
./../../third_party/libopenjpeg/t1.c:1478: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/t1.c:1504: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(t2.o): in function `opj_t2_encode_packet':
./../../third_party/libopenjpeg/t2.c:981: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ../libpdfium.a(t2.o): in function `opj_t2_decode_packets':
./../../third_party/libopenjpeg/t2.c:456: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(t2.o): in function `opj_t2_init_seg':
./../../third_party/libopenjpeg/t2.c:1658: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/t2.c:1658: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/t2.c:1658: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/t2.c:1658: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(cpwl_sbbutton.o):./../../third_party/libc++/src/include/vector:742: more undefined references to `__tsan_memset' follow
/usr/bin/ld: ../libpdfium.a(cpwl_sbbutton.o): in function `CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice*, CFX_Matrix const&)':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: ./../../third_party/libc++/src/include/__memory/construct_at.h:40: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: ../libpdfium.a(cpwl_sbbutton.o): in function `CFX_PTemplate<float>* std::__Cr::vector<CFX_PTemplate<float>, std::__Cr::allocator<CFX_PTemplate<float> > >::__push_back_slow_path<CFX_PTemplate<float> >(CFX_PTemplate<float>&&)':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: ./../../third_party/libc++/src/include/__memory/construct_at.h:40: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: ../libpdfium.a(ht_dec.o): in function `opj_t1_allocate_buffers':
./../../third_party/libopenjpeg/ht_dec.c:1055: undefined reference to `__tsan_memset'
/usr/bin/ld: ./../../third_party/libopenjpeg/ht_dec.c:1077: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(ht_dec.o): in function `opj_t1_ht_decode_cblk':
./../../third_party/libopenjpeg/ht_dec.c:1195: undefined reference to `__tsan_memcpy'
/usr/bin/ld: ./../../third_party/libopenjpeg/ht_dec.c:2336: undefined reference to `__tsan_memset'
/usr/bin/ld: ../libpdfium.a(ht_dec.o): in function `frwd_init':
./../../third_party/libopenjpeg/ht_dec.c:966: undefined reference to `__tsan_memset'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
UPDATE: I have upgraded my compiler to Clang 17 (previously I was using Clang 14) and now the linking errors are different:
/usr/bin/ld: .//libpdfium.a(fpdf_view.o): in function `FPDF_GetXFAPacketCount':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: .//libpdfium.a(fpdf_view.o): in function `(anonymous namespace)::GetXFAPackets(fxcrt::RetainPtr<CPDF_Object const>)':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: .//libpdfium.a(fpdf_view.o): in function `FPDF_GetXFAPacketName':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: .//libpdfium.a(fpdf_view.o): in function `FPDF_GetXFAPacketContent':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: .//libpdfium.a(fpdf_view.o): in function `FPDF_GetTrailerEnds':
./../../third_party/libc++/src/include/__memory/construct_at.h:68: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
/usr/bin/ld: .//libpdfium.a(fpdf_view.o):./../../third_party/libc++/src/include/__memory/construct_at.h:68: more undefined references to `std::__Cr::__libcpp_verbose_abort(char const*, ...)' follow
/usr/bin/ld: .//libpdfium.a(bytestring.o): in function `fxcrt::operator<<(std::__Cr::basic_ostream<char, std::__Cr::char_traits<char> >&, fxcrt::ByteString const&)':
./../../core/fxcrt/bytestring.cpp:781: undefined reference to `std::__Cr::basic_ostream<char, std::__Cr::char_traits<char> >::write(char const*, long)'
/usr/bin/ld: .//libpdfium.a(bytestring.o): in function `fxcrt::operator<<(std::__Cr::basic_ostream<char, std::__Cr::char_traits<char> >&, fxcrt::StringViewTemplate<char>)':
./../../core/fxcrt/bytestring.cpp:785: undefined reference to `std::__Cr::basic_ostream<char, std::__Cr::char_traits<char> >::write(char const*, long)'
/usr/bin/ld: .//libpdfium.a(bytestring.o): in function `std::__Cr::pair<std::__Cr::__hash_iterator<std::__Cr::__hash_node<fxcrt::ByteString, void*>*>, bool> std::__Cr::__hash_table<fxcrt::ByteString, std::__Cr::hash<fxcrt::ByteString>, std::__Cr::equal_to<fxcrt::ByteString>, std::__Cr::allocator<fxcrt::ByteString> >::__emplace_unique_key_args<fxcrt::ByteString, fxcrt::ByteString const&>(fxcrt::ByteString const&, fxcrt::ByteString const&)':
./../../third_party/libc++/src/include/__hash_table:2089: undefined reference to `std::__Cr::__next_prime(unsigned long)'
/usr/bin/ld: .//libpdfium.a(bytestring.o): in function `__rehash<true>':
./../../third_party/libc++/src/include/__hash_table:2099: undefined reference to `std::__Cr::__next_prime(unsigned long)'
/usr/bin/ld: .//libpdfium.a(bytestring.o): in function `std::__Cr::pair<std::__Cr::__hash_iterator<std::__Cr::__hash_node<fxcrt::ByteString, void*>*>, bool> std::__Cr::__hash_table<fxcrt::ByteString, std::__Cr::hash<fxcrt::ByteString>, std::__Cr::equal_to<fxcrt::ByteString>, std::__Cr::allocator<fxcrt::ByteString> >::__emplace_unique_key_args<fxcrt::ByteString, fxcrt::ByteString const&>(fxcrt::ByteString const&, fxcrt::ByteString const&)':
./../../third_party/libc++/src/include/__memory/construct_at.h:40: undefined reference to `std::__Cr::__libcpp_verbose_abort(char const*, ...)'
Now, it seems that the sanitizer symbols are found.