Skip to content

Implement -verify-debug-info #46

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

Merged
merged 1 commit into from
Dec 29, 2019
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
28 changes: 21 additions & 7 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ public struct Driver {
/// Path to the optimization record.
public let optimizationRecordPath: VirtualPath?

/// Whether 'dwarfdump' should be used to verify debug info.
public let shouldVerifyDebugInfo: Bool

/// If the driver should force emit module in a single invocation.
///
/// This will force the driver to first emit the module and then run compile jobs.
Expand Down Expand Up @@ -263,7 +266,8 @@ public struct Driver {
self.numParallelJobs = Self.determineNumParallelJobs(&parsedOptions, diagnosticsEngine: diagnosticEngine, env: env)

// Compute debug information output.
(self.debugInfoLevel, self.debugInfoFormat) = Self.computeDebugInfo(&parsedOptions, diagnosticsEngine: diagnosticEngine)
(self.debugInfoLevel, self.debugInfoFormat, shouldVerifyDebugInfo: self.shouldVerifyDebugInfo) =
Self.computeDebugInfo(&parsedOptions, diagnosticsEngine: diagnosticEngine)

// Determine the module we're building and whether/how the module file itself will be emitted.
(self.moduleOutput, self.moduleName) = try Self.computeModuleInfo(
Expand Down Expand Up @@ -948,10 +952,12 @@ extension Diagnostic.Message {
// Debug information
extension Driver {
/// Compute the level of debug information we are supposed to produce.
private static func computeDebugInfo(_ parsedOptions: inout ParsedOptions, diagnosticsEngine: DiagnosticsEngine) -> (DebugInfoLevel?, DebugInfoFormat) {
private static func computeDebugInfo(_ parsedOptions: inout ParsedOptions, diagnosticsEngine: DiagnosticsEngine) -> (DebugInfoLevel?, DebugInfoFormat, shouldVerifyDebugInfo: Bool) {
var shouldVerify = parsedOptions.hasArgument(.verifyDebugInfo)

// Determine the debug level.
let level: DebugInfoLevel?
if let levelOption = parsedOptions.getLast(in: .g) {
if let levelOption = parsedOptions.getLast(in: .g), levelOption.option != .gnone {
switch levelOption.option {
case .g:
level = .astTypes
Expand All @@ -962,14 +968,16 @@ extension Driver {
case .gdwarfTypes:
level = .dwarfTypes

case .gnone:
level = nil

default:
fatalError("Unhandle option in the '-g' group")
}
} else {
// -gnone, or no debug level specified
level = nil
if shouldVerify {
shouldVerify = false
diagnosticsEngine.emit(.verify_debug_info_requires_debug_option)
}
}

// Determine the debug info format.
Expand All @@ -995,7 +1003,7 @@ extension Driver {
diagnosticsEngine.emit(.error_argument_not_allowed_with(arg: format.rawValue, other: levelOption.spelling))
}

return (level, format)
return (level, format, shouldVerifyDebugInfo: shouldVerify)
}

/// Parses the set of `-sanitize={sanitizer}` arguments and returns all the
Expand Down Expand Up @@ -1074,6 +1082,12 @@ extension Driver {

}

extension Diagnostic.Message {
static var verify_debug_info_requires_debug_option: Diagnostic.Message {
.warning("ignoring '-verify-debug-info'; no debug info is being generated")
}
}

// Module computation.
extension Driver {
/// Compute the base name of the given path without an extension.
Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftDriver/Jobs/Job.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public struct Job: Codable, Equatable {
case emitModule = "emit-module"
case interpret
case repl
case verifyDebugInfo = "verify-debug-info"
}

public enum ArgTemplate: Equatable {
Expand Down
6 changes: 5 additions & 1 deletion Sources/SwiftDriver/Jobs/Planning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,11 @@ extension Driver {

// If we should generate a dSYM, do so.
if let linkJob = link, targetTriple.isDarwin, debugInfoLevel != nil {
jobs.append(try generateDSYMJob(inputs: linkJob.outputs))
let dsymJob = try generateDSYMJob(inputs: linkJob.outputs)
jobs.append(dsymJob)
if shouldVerifyDebugInfo {
jobs.append(try verifyDebugInfoJob(inputs: dsymJob.outputs))
}
}

// FIXME: Lots of follow-up actions for merging modules, etc.
Expand Down
32 changes: 32 additions & 0 deletions Sources/SwiftDriver/Jobs/VerifyDebugInfoJob.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===------- VerifyDebugInfoJob.swift - Swift Debug Info Verification -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

extension Driver {
func verifyDebugInfoJob(inputs: [TypedVirtualPath]) throws -> Job {
assert(inputs.count == 1)
let input = inputs[0]

// This mirrors the clang driver's --verify-debug-info option.
var commandLine = [Job.ArgTemplate]()
commandLine.appendFlags("--verify", "--debug-info", "--eh-frame", "--quiet")
commandLine.appendPath(input.file)

return Job(
kind: .verifyDebugInfo,
tool: .absolute(try toolchain.getToolPath(.dwarfdump)),
commandLine: commandLine,
displayInputs: [],
inputs: inputs,
outputs: []
)
}
}
2 changes: 2 additions & 0 deletions Sources/SwiftDriver/Toolchains/DarwinToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public final class DarwinToolchain: Toolchain {
return try lookup(executable: "swift-autolink-extract")
case .lldb:
return try lookup(executable: "lldb")
case .dwarfdump:
return try lookup(executable: "dwarfdump")
}
}

Expand Down
2 changes: 2 additions & 0 deletions Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public final class GenericUnixToolchain: Toolchain {
return try lookup(executable: "dsymutil")
case .lldb:
return try lookup(executable: "lldb")
case .dwarfdump:
return try lookup(executable: "dwarfdump")
}
}

Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftDriver/Toolchains/Toolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public enum Tool {
case swiftAutolinkExtract
case dsymutil
case lldb
case dwarfdump
}

/// Describes a toolchain, which includes information about compilers, linkers
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftDriverTests/Helpers/AssertDiagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import XCTest
import SwiftDriver
import TSCBasic

fileprivate func assertDriverDiagnostics(
func assertDriverDiagnostics(
args: [String],
env: [String: String],
env: [String: String] = ProcessEnv.vars,
file: StaticString = #file, line: UInt = #line,
do body: (inout Driver, DiagnosticVerifier) throws -> Void
) throws {
Expand Down
44 changes: 44 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,50 @@ final class SwiftDriverTests: XCTestCase {
}
}

func testVerifyDebugInfo() throws {
let commonArgs = [
"swiftc", "foo.swift", "bar.swift",
"-emit-executable", "-module-name", "Test", "-verify-debug-info"
]

// No dSYM generation (no -g), therefore no verification
try assertDriverDiagnostics(args: commonArgs) { driver, verifier in
verifier.expect(.warning("ignoring '-verify-debug-info'; no debug info is being generated"))
let plannedJobs = try driver.planBuild()
XCTAssertEqual(plannedJobs.count, 3)
XCTAssertFalse(plannedJobs.contains { $0.kind == .verifyDebugInfo })
}

// No dSYM generation (-gnone), therefore no verification
try assertDriverDiagnostics(args: commonArgs + ["-gnone"]) { driver, verifier in
verifier.expect(.warning("ignoring '-verify-debug-info'; no debug info is being generated"))
let plannedJobs = try driver.planBuild()
XCTAssertEqual(plannedJobs.count, 3)
XCTAssertFalse(plannedJobs.contains { $0.kind == .verifyDebugInfo })
}

do {
// dSYM generation and verification (-g + -verify-debug-info)
var driver = try Driver(args: commonArgs + ["-g"])
let plannedJobs = try driver.planBuild()

let verifyDebugInfoJob = plannedJobs.last!
let cmd = verifyDebugInfoJob.commandLine

if driver.targetTriple.isDarwin {
XCTAssertEqual(plannedJobs.count, 6)
XCTAssertEqual(verifyDebugInfoJob.inputs.first?.file, try VirtualPath(path: "Test.dSYM"))
XCTAssertTrue(cmd.contains(.flag("--verify")))
XCTAssertTrue(cmd.contains(.flag("--debug-info")))
XCTAssertTrue(cmd.contains(.flag("--eh-frame")))
XCTAssertTrue(cmd.contains(.flag("--quiet")))
XCTAssertTrue(cmd.contains(.path(try VirtualPath(path: "Test.dSYM"))))
} else {
XCTAssertEqual(plannedJobs.count, 4)
}
}
}

func testDOTFileEmission() throws {
var driver = try Driver(args: [
"swiftc", "-emit-executable", "test.swift", "-emit-module"
Expand Down