@@ -57,6 +57,7 @@ class ArgsBuilder {
57
57
private:
58
58
virtual void addSanitizers (const llvm::Triple &triple);
59
59
virtual void addASanLinkFlags (const llvm::Triple &triple);
60
+ virtual void addTSanLinkFlags (const llvm::Triple &triple);
60
61
virtual void addFuzzLinkFlags (const llvm::Triple &triple);
61
62
virtual void addCppStdlibLinkFlags (const llvm::Triple &triple);
62
63
virtual void addProfileRuntimeLinkFlags (const llvm::Triple &triple);
@@ -322,6 +323,47 @@ void ArgsBuilder::addASanLinkFlags(const llvm::Triple &triple) {
322
323
args.push_back (" -fsanitize=address" );
323
324
}
324
325
326
+ void ArgsBuilder::addTSanLinkFlags (const llvm::Triple &triple) {
327
+ // Examples: "libclang_rt.tsan-x86_64.a" or "libclang_rt.tsan-arm.a" and
328
+ // "libclang_rt.tsan-x86_64.so"
329
+
330
+ // TODO: let user choose to link with shared lib.
331
+ // In case of shared TSan, I think we also need to statically link with
332
+ // libclang_rt.tsan-preinit-<arch>.a on Linux. On Darwin, the only option is
333
+ // to use the shared library.
334
+ bool linkSharedTSan = triple.isOSDarwin ();
335
+ const auto searchPaths =
336
+ getFullCompilerRTLibPathCandidates (" tsan" , triple, linkSharedTSan);
337
+
338
+ for (const auto &filepath : searchPaths) {
339
+ IF_LOG Logger::println (" Searching TSan lib: %s" , filepath.c_str ());
340
+
341
+ if (llvm::sys::fs::exists (filepath) &&
342
+ !llvm::sys::fs::is_directory (filepath)) {
343
+ IF_LOG Logger::println (" Found, linking with %s" , filepath.c_str ());
344
+ args.push_back (filepath);
345
+
346
+ if (linkSharedTSan) {
347
+ // Add @executable_path to rpath to support having the shared lib copied
348
+ // with the executable.
349
+ args.push_back (" -rpath" );
350
+ args.push_back (" @executable_path" );
351
+
352
+ // Add the path to the resource dir to rpath to support using the shared
353
+ // lib from the default location without copying.
354
+ args.push_back (" -rpath" );
355
+ args.push_back (std::string (llvm::sys::path::parent_path (filepath)));
356
+ }
357
+
358
+ return ;
359
+ }
360
+ }
361
+
362
+ // When we reach here, we did not find the TSan library.
363
+ // Fallback, requires Clang.
364
+ args.push_back (" -fsanitize=thread" );
365
+ }
366
+
325
367
// Adds all required link flags for -fsanitize=fuzzer when libFuzzer library is
326
368
// found.
327
369
void ArgsBuilder::addFuzzLinkFlags (const llvm::Triple &triple) {
@@ -459,10 +501,8 @@ void ArgsBuilder::addSanitizers(const llvm::Triple &triple) {
459
501
args.push_back (" -fsanitize=memory" );
460
502
}
461
503
462
- // TODO: instead of this, we should link with our own sanitizer libraries
463
- // because LDC's LLVM version could be different from the system clang.
464
504
if (opts::isSanitizerEnabled (opts::ThreadSanitizer)) {
465
- args. push_back ( " -fsanitize=thread " );
505
+ addTSanLinkFlags (triple );
466
506
}
467
507
}
468
508
0 commit comments