Skip to content

Commit 3cf9189

Browse files
committed
SwiftDriver: enable -sanitize= on Windows selectively
ASAN, UBSAN are available on Windows while TSAN is not. The toolchain has started building the runtimes and will be distributing them with the toolchain builds. This change enables the support in the driver for the santizers on Windows.
1 parent cac0be2 commit 3cf9189

File tree

4 files changed

+37
-44
lines changed

4 files changed

+37
-44
lines changed

Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@ extension Toolchain {
3232
if platform == "android" {
3333
platform = "linux"
3434
}
35+
36+
// NOTE(compnerd) Windows uses the per-target runtime directory for the
37+
// Windows runtimes. This should also be done for the other platforms, but
38+
// is not critical. This is done to allow for the Windows runtimes to be
39+
// co-located for all the currently supported architectures: x86, x64, arm64.
40+
let bIsWindows = targetInfo.target.triple.isWindows
3541
return VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
36-
.appending(components: "clang", "lib", platform)
42+
.appending(components: "clang", "lib", bIsWindows ? targetInfo.target.triple.triple : platform)
3743
}
3844

3945
func runtimeLibraryPaths(

Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ extension WindowsToolchain {
223223
commandLine.appendFlag(optArg)
224224
}
225225

226-
// FIXME(compnerd) render asan/ubsan runtime link for executables
226+
if !sanitizers.isEmpty {
227+
let sanitize = sanitizers.map(\.rawValue).sorted().joined(separator: ",")
228+
commandLine.appendFlag("-fsanitize=\(sanitize)")
229+
}
227230

228231
if parsedOptions.contains(.profileGenerate) {
229232
assert(bForceLLD,

Sources/SwiftDriver/Toolchains/WindowsToolchain.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ extension WindowsToolchain.ToolchainValidationError {
130130
public func runtimeLibraryName(for sanitizer: Sanitizer, targetTriple: Triple,
131131
isShared: Bool) throws -> String {
132132
// TODO(compnerd) handle shared linking
133+
134+
// FIXME(compnerd) when should `clang_rt.ubsan_standalone_cxx` be used?
135+
if sanitizer == .undefinedBehavior {
136+
return "clang_rt.ubsan_standalone.lib"
137+
}
133138
return "clang_rt.\(sanitizer.libraryName).lib"
134139
}
135140

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,56 +2708,40 @@ final class SwiftDriverTests: XCTestCase {
27082708

27092709
func testSanitizerArgs() throws {
27102710
let commonArgs = [
2711-
"swiftc", "foo.swift", "bar.swift",
2712-
"-emit-executable", "-target", "x86_64-apple-macosx10.9",
2713-
"-module-name", "Test"
2711+
"swiftc", "foo.swift", "bar.swift", "-emit-executable", "-module-name", "Test", "-use-ld=lld"
27142712
]
2715-
// FIXME: This doesn't work on Linux.
2716-
#if os(macOS)
2713+
2714+
#if os(macOS) || os(Windows)
27172715
do {
27182716
// address sanitizer
27192717
var driver = try Driver(args: commonArgs + ["-sanitize=address"])
2720-
let plannedJobs = try driver.planBuild()
2721-
2722-
XCTAssertEqual(plannedJobs.count, 3)
2723-
2724-
let compileJob = plannedJobs[0]
2725-
let compileCmd = compileJob.commandLine
2726-
XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address")))
2718+
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
27272719

2728-
let linkJob = plannedJobs[2]
2729-
let linkCmd = linkJob.commandLine
2730-
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address")))
2720+
XCTAssertEqual(jobs.count, 3)
2721+
XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=address"))
2722+
XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=address"))
27312723
}
27322724

27332725
do {
27342726
// address sanitizer on a dylib
27352727
var driver = try Driver(args: commonArgs + ["-sanitize=address", "-emit-library"])
2736-
let plannedJobs = try driver.planBuild()
2737-
2738-
XCTAssertEqual(plannedJobs.count, 3)
2739-
2740-
let compileJob = plannedJobs[0]
2741-
let compileCmd = compileJob.commandLine
2742-
XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address")))
2728+
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
27432729

2744-
let linkJob = plannedJobs[2]
2745-
let linkCmd = linkJob.commandLine
2746-
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address")))
2730+
XCTAssertEqual(jobs.count, 3)
2731+
XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=address"))
2732+
XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=address"))
27472733
}
27482734

27492735
do {
27502736
// *no* address sanitizer on a static lib
27512737
var driver = try Driver(args: commonArgs + ["-sanitize=address", "-emit-library", "-static"])
2752-
let plannedJobs = try driver.planBuild()
2753-
2754-
XCTAssertEqual(plannedJobs.count, 3)
2738+
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
27552739

2756-
let linkJob = plannedJobs[2]
2757-
let linkCmd = linkJob.commandLine
2758-
XCTAssertFalse(linkCmd.contains(.flag("-fsanitize=address")))
2740+
XCTAssertEqual(jobs.count, 3)
2741+
XCTAssertFalse(jobs[2].commandLine.contains(.flag("-fsanitize=address")))
27592742
}
27602743

2744+
#if !os(Windows)
27612745
do {
27622746
// thread sanitizer
27632747
var driver = try Driver(args: commonArgs + ["-sanitize=thread"])
@@ -2773,21 +2757,16 @@ final class SwiftDriverTests: XCTestCase {
27732757
let linkCmd = linkJob.commandLine
27742758
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=thread")))
27752759
}
2760+
#endif
27762761

27772762
do {
27782763
// undefined behavior sanitizer
27792764
var driver = try Driver(args: commonArgs + ["-sanitize=undefined"])
2780-
let plannedJobs = try driver.planBuild()
2781-
2782-
XCTAssertEqual(plannedJobs.count, 3)
2783-
2784-
let compileJob = plannedJobs[0]
2785-
let compileCmd = compileJob.commandLine
2786-
XCTAssertTrue(compileCmd.contains(.flag("-sanitize=undefined")))
2765+
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
27872766

2788-
let linkJob = plannedJobs[2]
2789-
let linkCmd = linkJob.commandLine
2790-
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=undefined")))
2767+
XCTAssertEqual(jobs.count, 3)
2768+
XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=undefined"))
2769+
XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=undefined"))
27912770
}
27922771

27932772
// FIXME: This test will fail when run on macOS, because the driver uses
@@ -7221,7 +7200,7 @@ final class SwiftDriverTests: XCTestCase {
72217200
}
72227201

72237202
func testSanitizerArgsForTargets() throws {
7224-
let targets = ["x86_64-unknown-freebsd", "x86_64-unknown-linux", "x86_64-apple-macosx10.9"]
7203+
let targets = ["x86_64-unknown-freebsd", "x86_64-unknown-linux", "x86_64-apple-macosx10.9", "x86_64-unknown-windows-msvc"]
72257204
try targets.forEach {
72267205
var driver = try Driver(args: ["swiftc", "-emit-module", "-target", $0, "foo.swift"])
72277206
_ = try driver.planBuild()

0 commit comments

Comments
 (0)