Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SwiftDriver: enable -sanitize= on Windows selectively #1804

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ extension Toolchain {
if platform == "android" {
platform = "linux"
}

// NOTE(compnerd) Windows uses the per-target runtime directory for the
// Windows runtimes. This should also be done for the other platforms, but
// is not critical. This is done to allow for the Windows runtimes to be
// co-located for all the currently supported architectures: x86, x64, arm64.
let bIsWindows = targetInfo.target.triple.isWindows
return VirtualPath.lookup(targetInfo.runtimeResourcePath.path)
.appending(components: "clang", "lib", platform)
.appending(components: "clang", "lib", bIsWindows ? targetInfo.target.triple.triple : platform)
}

func runtimeLibraryPaths(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ extension WindowsToolchain {
commandLine.appendFlag(optArg)
}

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

if parsedOptions.contains(.profileGenerate) {
assert(bForceLLD,
Expand Down
5 changes: 5 additions & 0 deletions Sources/SwiftDriver/Toolchains/WindowsToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ extension WindowsToolchain.ToolchainValidationError {
public func runtimeLibraryName(for sanitizer: Sanitizer, targetTriple: Triple,
isShared: Bool) throws -> String {
// TODO(compnerd) handle shared linking

// FIXME(compnerd) when should `clang_rt.ubsan_standalone_cxx` be used?
if sanitizer == .undefinedBehavior {
return "clang_rt.ubsan_standalone.lib"
}
return "clang_rt.\(sanitizer.libraryName).lib"
}

Expand Down
63 changes: 20 additions & 43 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2708,56 +2708,39 @@ final class SwiftDriverTests: XCTestCase {

func testSanitizerArgs() throws {
let commonArgs = [
"swiftc", "foo.swift", "bar.swift",
"-emit-executable", "-target", "x86_64-apple-macosx10.9",
"-module-name", "Test"
"swiftc", "foo.swift", "bar.swift", "-emit-executable", "-module-name", "Test", "-use-ld=lld"
]
// FIXME: This doesn't work on Linux.
#if os(macOS)

do {
// address sanitizer
var driver = try Driver(args: commonArgs + ["-sanitize=address"])
let plannedJobs = try driver.planBuild()

XCTAssertEqual(plannedJobs.count, 3)

let compileJob = plannedJobs[0]
let compileCmd = compileJob.commandLine
XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address")))
let jobs = try driver.planBuild().removingAutolinkExtractJobs()

let linkJob = plannedJobs[2]
let linkCmd = linkJob.commandLine
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address")))
XCTAssertEqual(jobs.count, 3)
XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=address"))
XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=address"))
}

do {
// address sanitizer on a dylib
var driver = try Driver(args: commonArgs + ["-sanitize=address", "-emit-library"])
let plannedJobs = try driver.planBuild()

XCTAssertEqual(plannedJobs.count, 3)

let compileJob = plannedJobs[0]
let compileCmd = compileJob.commandLine
XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address")))
let jobs = try driver.planBuild().removingAutolinkExtractJobs()

let linkJob = plannedJobs[2]
let linkCmd = linkJob.commandLine
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address")))
XCTAssertEqual(jobs.count, 3)
XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=address"))
XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=address"))
}

do {
// *no* address sanitizer on a static lib
var driver = try Driver(args: commonArgs + ["-sanitize=address", "-emit-library", "-static"])
let plannedJobs = try driver.planBuild()

XCTAssertEqual(plannedJobs.count, 3)
let jobs = try driver.planBuild().removingAutolinkExtractJobs()

let linkJob = plannedJobs[2]
let linkCmd = linkJob.commandLine
XCTAssertFalse(linkCmd.contains(.flag("-fsanitize=address")))
XCTAssertEqual(jobs.count, 3)
XCTAssertFalse(jobs[2].commandLine.contains(.flag("-fsanitize=address")))
}

#if !os(Windows)
do {
// thread sanitizer
var driver = try Driver(args: commonArgs + ["-sanitize=thread"])
Expand All @@ -2773,21 +2756,16 @@ final class SwiftDriverTests: XCTestCase {
let linkCmd = linkJob.commandLine
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=thread")))
}
#endif

do {
// undefined behavior sanitizer
var driver = try Driver(args: commonArgs + ["-sanitize=undefined"])
let plannedJobs = try driver.planBuild()

XCTAssertEqual(plannedJobs.count, 3)

let compileJob = plannedJobs[0]
let compileCmd = compileJob.commandLine
XCTAssertTrue(compileCmd.contains(.flag("-sanitize=undefined")))
let jobs = try driver.planBuild().removingAutolinkExtractJobs()

let linkJob = plannedJobs[2]
let linkCmd = linkJob.commandLine
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=undefined")))
XCTAssertEqual(jobs.count, 3)
XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=undefined"))
XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=undefined"))
}

// FIXME: This test will fail when run on macOS, because the driver uses
Expand Down Expand Up @@ -2838,7 +2816,6 @@ final class SwiftDriverTests: XCTestCase {
XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=scudo")))
}
#endif
#endif

// FIXME: This test will fail when not run on Android, because the driver uses
// the existence of the runtime support libraries to determine if
Expand Down Expand Up @@ -7223,7 +7200,7 @@ final class SwiftDriverTests: XCTestCase {
}

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