Support sanitizers in runtime tests (#4622)
This commit is contained in:
committed by
Nikolay Krasko
parent
3ee8d98726
commit
6cc60ad6a2
+11
@@ -30,3 +30,14 @@ fun KonanTarget.supportsThreads(): Boolean =
|
||||
is KonanTarget.ZEPHYR -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
fun KonanTarget.supportedSanitizers(): List<SanitizerKind> =
|
||||
when(this) {
|
||||
is KonanTarget.LINUX_X64 -> listOf(SanitizerKind.ADDRESS)
|
||||
is KonanTarget.MACOS_X64 -> listOf(SanitizerKind.THREAD)
|
||||
// TODO: Enable ASAN on macOS. Currently there's an incompatibility between clang frontend version and clang_rt.asan version.
|
||||
// TODO: Enable TSAN on linux. Currently there's a link error between clang_rt.tsan and libstdc++.
|
||||
// TODO: Consider supporting mingw.
|
||||
// TODO: Support macOS arm64
|
||||
else -> listOf()
|
||||
}
|
||||
|
||||
@@ -76,7 +76,8 @@ abstract class LinkerFlags(val configurables: Configurables) {
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command>
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind? = null): List<Command>
|
||||
|
||||
/**
|
||||
* Returns list of commands that link object files into a single one.
|
||||
@@ -93,7 +94,7 @@ abstract class LinkerFlags(val configurables: Configurables) {
|
||||
return libraries
|
||||
}
|
||||
|
||||
protected open fun provideCompilerRtLibrary(libraryName: String): String? {
|
||||
protected open fun provideCompilerRtLibrary(libraryName: String, isDynamic: Boolean = false): String? {
|
||||
System.err.println("Can't provide $libraryName.")
|
||||
return null
|
||||
}
|
||||
@@ -123,7 +124,11 @@ class AndroidLinker(targetProperties: AndroidConfigurables)
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command> {
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind?): List<Command> {
|
||||
require(sanitizer == null) {
|
||||
"Sanitizers are unsupported"
|
||||
}
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
return staticGnuArCommands(ar, executable, objectFiles, libraries)
|
||||
|
||||
@@ -170,7 +175,12 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
get() = this == KonanTarget.TVOS_X64 || this == KonanTarget.IOS_X64 ||
|
||||
this == KonanTarget.WATCHOS_X86 || this == KonanTarget.WATCHOS_X64
|
||||
|
||||
override fun provideCompilerRtLibrary(libraryName: String): String? {
|
||||
private val compilerRtDir: String? by lazy {
|
||||
val dir = File("$absoluteTargetToolchain/usr/lib/clang/").listFiles.firstOrNull()?.absolutePath
|
||||
if (dir != null) "$dir/lib/darwin/" else null
|
||||
}
|
||||
|
||||
override fun provideCompilerRtLibrary(libraryName: String, isDynamic: Boolean): String? {
|
||||
val prefix = when (target.family) {
|
||||
Family.IOS -> "ios"
|
||||
Family.WATCHOS -> "watchos"
|
||||
@@ -184,10 +194,11 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
""
|
||||
}
|
||||
|
||||
val dir = File("$absoluteTargetToolchain/usr/lib/clang/").listFiles.firstOrNull()?.absolutePath
|
||||
val dir = compilerRtDir
|
||||
val mangledLibraryName = if (libraryName.isEmpty()) "" else "${libraryName}_"
|
||||
val extension = if (isDynamic) "_dynamic.dylib" else ".a"
|
||||
|
||||
return if (dir != null) "$dir/lib/darwin/libclang_rt.$mangledLibraryName$prefix$suffix.a" else null
|
||||
return if (dir != null) "$dir/libclang_rt.$mangledLibraryName$prefix$suffix$extension" else null
|
||||
}
|
||||
|
||||
private val osVersionMinFlags: List<String> by lazy {
|
||||
@@ -210,14 +221,19 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean, kind: LinkerOutputKind,
|
||||
outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind?): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY) {
|
||||
require(sanitizer == null) {
|
||||
"Sanitizers are unsupported"
|
||||
}
|
||||
return listOf(Command(libtool).apply {
|
||||
+"-static"
|
||||
+listOf("-o", executable)
|
||||
+objectFiles
|
||||
+libraries
|
||||
})
|
||||
}
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
|
||||
val result = mutableListOf<Command>()
|
||||
@@ -237,7 +253,12 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
if (needsProfileLibrary) +profileLibrary!!
|
||||
+libraries
|
||||
+linkerArgs
|
||||
+rpath(dynamic)
|
||||
+rpath(dynamic, sanitizer)
|
||||
when (sanitizer) {
|
||||
null -> {}
|
||||
SanitizerKind.ADDRESS -> +provideCompilerRtLibrary("asan", isDynamic=true)!!
|
||||
SanitizerKind.THREAD -> +provideCompilerRtLibrary("tsan", isDynamic=true)!!
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: revise debug information handling.
|
||||
@@ -255,7 +276,7 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
provideCompilerRtLibrary("")
|
||||
}
|
||||
|
||||
private fun rpath(dynamic: Boolean): List<String> = listOfNotNull(
|
||||
private fun rpath(dynamic: Boolean, sanitizer: SanitizerKind?): List<String> = listOfNotNull(
|
||||
when (target.family) {
|
||||
Family.OSX -> "@executable_path/../Frameworks"
|
||||
Family.IOS,
|
||||
@@ -263,7 +284,8 @@ class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
Family.TVOS -> "@executable_path/Frameworks"
|
||||
else -> error(target)
|
||||
},
|
||||
"@loader_path/Frameworks".takeIf { dynamic }
|
||||
"@loader_path/Frameworks".takeIf { dynamic },
|
||||
compilerRtDir.takeIf { sanitizer != null },
|
||||
).flatMap { listOf("-rpath", it) }
|
||||
|
||||
fun dsymUtilCommand(executable: ExecutableFile, outputDsymBundle: String) =
|
||||
@@ -319,7 +341,10 @@ class GccBasedLinker(targetProperties: GccConfigurables)
|
||||
|
||||
private val specificLibs = abiSpecificLibraries.map { "-L${absoluteTargetSysRoot}/$it" }
|
||||
|
||||
override fun provideCompilerRtLibrary(libraryName: String): String? {
|
||||
override fun provideCompilerRtLibrary(libraryName: String, isDynamic: Boolean): String? {
|
||||
require(!isDynamic) {
|
||||
"Dynamic compiler rt librares are unsupported"
|
||||
}
|
||||
val targetSuffix = when (target) {
|
||||
KonanTarget.LINUX_X64 -> "x86_64"
|
||||
else -> error("$target is not supported.")
|
||||
@@ -334,9 +359,14 @@ class GccBasedLinker(targetProperties: GccConfigurables)
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind?): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY) {
|
||||
require(sanitizer == null) {
|
||||
"Sanitizers are unsupported"
|
||||
}
|
||||
return staticGnuArCommands(ar, executable, objectFiles, libraries)
|
||||
}
|
||||
val isMips = target == KonanTarget.LINUX_MIPS32 || target == KonanTarget.LINUX_MIPSEL32
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
val crtPrefix = "$absoluteTargetSysRoot/$crtFilesLocation"
|
||||
@@ -373,6 +403,19 @@ class GccBasedLinker(targetProperties: GccConfigurables)
|
||||
+linkerGccFlags
|
||||
+if (dynamic) "$libGcc/crtendS.o" else "$libGcc/crtend.o"
|
||||
+"$crtPrefix/crtn.o"
|
||||
when (sanitizer) {
|
||||
null -> {}
|
||||
SanitizerKind.ADDRESS -> {
|
||||
+"-lrt"
|
||||
+provideCompilerRtLibrary("asan")!!
|
||||
+provideCompilerRtLibrary("asan_cxx")!!
|
||||
}
|
||||
SanitizerKind.THREAD -> {
|
||||
+"-lrt"
|
||||
+provideCompilerRtLibrary("tsan")!!
|
||||
+provideCompilerRtLibrary("tsan_cxx")!!
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -387,7 +430,10 @@ class MingwLinker(targetProperties: MingwConfigurables)
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib }
|
||||
|
||||
override fun provideCompilerRtLibrary(libraryName: String): String? {
|
||||
override fun provideCompilerRtLibrary(libraryName: String, isDynamic: Boolean): String? {
|
||||
require(!isDynamic) {
|
||||
"Dynamic compiler rt librares are unsupported"
|
||||
}
|
||||
val targetSuffix = when (target) {
|
||||
KonanTarget.MINGW_X64 -> "x86_64"
|
||||
else -> error("$target is not supported.")
|
||||
@@ -400,7 +446,11 @@ class MingwLinker(targetProperties: MingwConfigurables)
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command> {
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind?): List<Command> {
|
||||
require(sanitizer == null) {
|
||||
"Sanitizers are unsupported"
|
||||
}
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
return staticGnuArCommands(ar, executable, objectFiles, libraries)
|
||||
|
||||
@@ -437,8 +487,12 @@ class WasmLinker(targetProperties: WasmConfigurables)
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command> {
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind?): List<Command> {
|
||||
if (kind != LinkerOutputKind.EXECUTABLE) throw Error("Unsupported linker output kind")
|
||||
require(sanitizer == null) {
|
||||
"Sanitizers are unsupported"
|
||||
}
|
||||
|
||||
val linkage = Command("$llvmBin/wasm-ld").apply {
|
||||
+objectFiles
|
||||
@@ -489,8 +543,12 @@ open class ZephyrLinker(targetProperties: ZephyrConfigurables)
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String,
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean): List<Command> {
|
||||
needsProfileLibrary: Boolean, mimallocEnabled: Boolean,
|
||||
sanitizer: SanitizerKind?): List<Command> {
|
||||
if (kind != LinkerOutputKind.EXECUTABLE) throw Error("Unsupported linker output kind: $kind")
|
||||
require(sanitizer == null) {
|
||||
"Sanitizers are unsupported"
|
||||
}
|
||||
return listOf(Command(linker).apply {
|
||||
+listOf("-r", "--gc-sections", "--entry", "main")
|
||||
+listOf("-o", executable)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
enum class SanitizerKind {
|
||||
ADDRESS,
|
||||
THREAD,
|
||||
}
|
||||
Reference in New Issue
Block a user