Skip to content

Commit 5bcc711

Browse files
authored
Merge pull request #46 from owenv/verify-debug-info
Implement -verify-debug-info
2 parents 4662bc8 + 2378ed7 commit 5bcc711

File tree

9 files changed

+110
-10
lines changed

9 files changed

+110
-10
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ public struct Driver {
151151
/// Path to the optimization record.
152152
public let optimizationRecordPath: VirtualPath?
153153

154+
/// Whether 'dwarfdump' should be used to verify debug info.
155+
public let shouldVerifyDebugInfo: Bool
156+
154157
/// If the driver should force emit module in a single invocation.
155158
///
156159
/// This will force the driver to first emit the module and then run compile jobs.
@@ -263,7 +266,8 @@ public struct Driver {
263266
self.numParallelJobs = Self.determineNumParallelJobs(&parsedOptions, diagnosticsEngine: diagnosticEngine, env: env)
264267

265268
// Compute debug information output.
266-
(self.debugInfoLevel, self.debugInfoFormat) = Self.computeDebugInfo(&parsedOptions, diagnosticsEngine: diagnosticEngine)
269+
(self.debugInfoLevel, self.debugInfoFormat, shouldVerifyDebugInfo: self.shouldVerifyDebugInfo) =
270+
Self.computeDebugInfo(&parsedOptions, diagnosticsEngine: diagnosticEngine)
267271

268272
// Determine the module we're building and whether/how the module file itself will be emitted.
269273
(self.moduleOutput, self.moduleName) = try Self.computeModuleInfo(
@@ -948,10 +952,12 @@ extension Diagnostic.Message {
948952
// Debug information
949953
extension Driver {
950954
/// Compute the level of debug information we are supposed to produce.
951-
private static func computeDebugInfo(_ parsedOptions: inout ParsedOptions, diagnosticsEngine: DiagnosticsEngine) -> (DebugInfoLevel?, DebugInfoFormat) {
955+
private static func computeDebugInfo(_ parsedOptions: inout ParsedOptions, diagnosticsEngine: DiagnosticsEngine) -> (DebugInfoLevel?, DebugInfoFormat, shouldVerifyDebugInfo: Bool) {
956+
var shouldVerify = parsedOptions.hasArgument(.verifyDebugInfo)
957+
952958
// Determine the debug level.
953959
let level: DebugInfoLevel?
954-
if let levelOption = parsedOptions.getLast(in: .g) {
960+
if let levelOption = parsedOptions.getLast(in: .g), levelOption.option != .gnone {
955961
switch levelOption.option {
956962
case .g:
957963
level = .astTypes
@@ -962,14 +968,16 @@ extension Driver {
962968
case .gdwarfTypes:
963969
level = .dwarfTypes
964970

965-
case .gnone:
966-
level = nil
967-
968971
default:
969972
fatalError("Unhandle option in the '-g' group")
970973
}
971974
} else {
975+
// -gnone, or no debug level specified
972976
level = nil
977+
if shouldVerify {
978+
shouldVerify = false
979+
diagnosticsEngine.emit(.verify_debug_info_requires_debug_option)
980+
}
973981
}
974982

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

998-
return (level, format)
1006+
return (level, format, shouldVerifyDebugInfo: shouldVerify)
9991007
}
10001008

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

10751083
}
10761084

1085+
extension Diagnostic.Message {
1086+
static var verify_debug_info_requires_debug_option: Diagnostic.Message {
1087+
.warning("ignoring '-verify-debug-info'; no debug info is being generated")
1088+
}
1089+
}
1090+
10771091
// Module computation.
10781092
extension Driver {
10791093
/// Compute the base name of the given path without an extension.

Sources/SwiftDriver/Jobs/Job.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public struct Job: Codable, Equatable {
2222
case emitModule = "emit-module"
2323
case interpret
2424
case repl
25+
case verifyDebugInfo = "verify-debug-info"
2526
}
2627

2728
public enum ArgTemplate: Equatable {

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ extension Driver {
144144

145145
// If we should generate a dSYM, do so.
146146
if let linkJob = link, targetTriple.isDarwin, debugInfoLevel != nil {
147-
jobs.append(try generateDSYMJob(inputs: linkJob.outputs))
147+
let dsymJob = try generateDSYMJob(inputs: linkJob.outputs)
148+
jobs.append(dsymJob)
149+
if shouldVerifyDebugInfo {
150+
jobs.append(try verifyDebugInfoJob(inputs: dsymJob.outputs))
151+
}
148152
}
149153

150154
// FIXME: Lots of follow-up actions for merging modules, etc.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===------- VerifyDebugInfoJob.swift - Swift Debug Info Verification -----===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
extension Driver {
14+
func verifyDebugInfoJob(inputs: [TypedVirtualPath]) throws -> Job {
15+
assert(inputs.count == 1)
16+
let input = inputs[0]
17+
18+
// This mirrors the clang driver's --verify-debug-info option.
19+
var commandLine = [Job.ArgTemplate]()
20+
commandLine.appendFlags("--verify", "--debug-info", "--eh-frame", "--quiet")
21+
commandLine.appendPath(input.file)
22+
23+
return Job(
24+
kind: .verifyDebugInfo,
25+
tool: .absolute(try toolchain.getToolPath(.dwarfdump)),
26+
commandLine: commandLine,
27+
displayInputs: [],
28+
inputs: inputs,
29+
outputs: []
30+
)
31+
}
32+
}

Sources/SwiftDriver/Toolchains/DarwinToolchain.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public final class DarwinToolchain: Toolchain {
4646
return try lookup(executable: "swift-autolink-extract")
4747
case .lldb:
4848
return try lookup(executable: "lldb")
49+
case .dwarfdump:
50+
return try lookup(executable: "dwarfdump")
4951
}
5052
}
5153

Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public final class GenericUnixToolchain: Toolchain {
4444
return try lookup(executable: "dsymutil")
4545
case .lldb:
4646
return try lookup(executable: "lldb")
47+
case .dwarfdump:
48+
return try lookup(executable: "dwarfdump")
4749
}
4850
}
4951

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public enum Tool {
2020
case swiftAutolinkExtract
2121
case dsymutil
2222
case lldb
23+
case dwarfdump
2324
}
2425

2526
/// Describes a toolchain, which includes information about compilers, linkers

Tests/SwiftDriverTests/Helpers/AssertDiagnostics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import XCTest
1414
import SwiftDriver
1515
import TSCBasic
1616

17-
fileprivate func assertDriverDiagnostics(
17+
func assertDriverDiagnostics(
1818
args: [String],
19-
env: [String: String],
19+
env: [String: String] = ProcessEnv.vars,
2020
file: StaticString = #file, line: UInt = #line,
2121
do body: (inout Driver, DiagnosticVerifier) throws -> Void
2222
) throws {

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,50 @@ final class SwiftDriverTests: XCTestCase {
10811081
}
10821082
}
10831083

1084+
func testVerifyDebugInfo() throws {
1085+
let commonArgs = [
1086+
"swiftc", "foo.swift", "bar.swift",
1087+
"-emit-executable", "-module-name", "Test", "-verify-debug-info"
1088+
]
1089+
1090+
// No dSYM generation (no -g), therefore no verification
1091+
try assertDriverDiagnostics(args: commonArgs) { driver, verifier in
1092+
verifier.expect(.warning("ignoring '-verify-debug-info'; no debug info is being generated"))
1093+
let plannedJobs = try driver.planBuild()
1094+
XCTAssertEqual(plannedJobs.count, 3)
1095+
XCTAssertFalse(plannedJobs.contains { $0.kind == .verifyDebugInfo })
1096+
}
1097+
1098+
// No dSYM generation (-gnone), therefore no verification
1099+
try assertDriverDiagnostics(args: commonArgs + ["-gnone"]) { driver, verifier in
1100+
verifier.expect(.warning("ignoring '-verify-debug-info'; no debug info is being generated"))
1101+
let plannedJobs = try driver.planBuild()
1102+
XCTAssertEqual(plannedJobs.count, 3)
1103+
XCTAssertFalse(plannedJobs.contains { $0.kind == .verifyDebugInfo })
1104+
}
1105+
1106+
do {
1107+
// dSYM generation and verification (-g + -verify-debug-info)
1108+
var driver = try Driver(args: commonArgs + ["-g"])
1109+
let plannedJobs = try driver.planBuild()
1110+
1111+
let verifyDebugInfoJob = plannedJobs.last!
1112+
let cmd = verifyDebugInfoJob.commandLine
1113+
1114+
if driver.targetTriple.isDarwin {
1115+
XCTAssertEqual(plannedJobs.count, 6)
1116+
XCTAssertEqual(verifyDebugInfoJob.inputs.first?.file, try VirtualPath(path: "Test.dSYM"))
1117+
XCTAssertTrue(cmd.contains(.flag("--verify")))
1118+
XCTAssertTrue(cmd.contains(.flag("--debug-info")))
1119+
XCTAssertTrue(cmd.contains(.flag("--eh-frame")))
1120+
XCTAssertTrue(cmd.contains(.flag("--quiet")))
1121+
XCTAssertTrue(cmd.contains(.path(try VirtualPath(path: "Test.dSYM"))))
1122+
} else {
1123+
XCTAssertEqual(plannedJobs.count, 4)
1124+
}
1125+
}
1126+
}
1127+
10841128
func testDOTFileEmission() throws {
10851129
var driver = try Driver(args: [
10861130
"swiftc", "-emit-executable", "test.swift", "-emit-module"

0 commit comments

Comments
 (0)