Skip to content

Commit 5d7848a

Browse files
committed
Codesign w/ debugging entitlement for backtraces on macOS
1 parent 1491d34 commit 5d7848a

File tree

5 files changed

+116
-46
lines changed

5 files changed

+116
-46
lines changed

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
148148
}
149149

150150
/// The arguments to link and create this product.
151-
public func linkArguments() throws -> [String] {
151+
public func linkArguments(outputPathSuffix: String = "") throws -> [String] {
152152
var args = [buildParameters.toolchain.swiftCompilerPath.pathString]
153153
args += self.buildParameters.sanitizers.linkSwiftFlags()
154154
args += self.additionalFlags
@@ -164,7 +164,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
164164
}
165165

166166
args += ["-L", self.buildParameters.buildPath.pathString]
167-
args += try ["-o", binaryPath.pathString]
167+
args += try ["-o", binaryPath.pathString + outputPathSuffix]
168168
args += ["-module-name", self.product.name.spm_mangledToC99ExtendedIdentifier()]
169169
args += self.dylibs.map { "-l" + $0.product.name }
170170

Sources/Build/BuildManifest/LLBuildManifestBuilder+Product.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@ extension LLBuildManifestBuilder {
5656
outputs: [.file(buildProduct.binaryPath)],
5757
arguments: try buildProduct.linkArguments()
5858
)
59+
60+
if buildParameters.debuggingParameters.shouldEnableDebuggingEntitlement {
61+
let basename = try buildProduct.binaryPath.basename
62+
let plistPath = try buildProduct.binaryPath.parentDirectory
63+
.appending(component: "\(basename)-entitlement.plist")
64+
self.manifest.addEntitlementPlistCommand(
65+
entitlement: "com.apple.security.get-task-allow",
66+
outputPath: plistPath
67+
)
68+
69+
let cmdName = try buildProduct.product.getCommandName(config: self.buildConfig)
70+
try self.manifest.addShellCmd(
71+
name: "\(cmdName)-entitlements",
72+
description: "Applying debug entitlements to \(buildProduct.binaryPath.prettyPath())",
73+
inputs: [buildProduct.binaryPath, plistPath].map(Node.file),
74+
outputs: <#T##[Node]#>,
75+
arguments: <#T##[String]#>
76+
)
77+
}
5978
}
6079

6180
// Create a phony node to represent the entire target.

Sources/CoreCommands/Options.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,23 @@ public struct BuildOptions: ParsableArguments {
477477
)
478478
public var linkTimeOptimizationMode: LinkTimeOptimizationMode?
479479

480+
/// Whether to enable debugging capabilities for code built by SwiftPM.
481+
@Flag(
482+
help: """
483+
Whether to enable unsafe debugging and backtraces for code built by SwiftPM. \
484+
Currently has an effect only on macOS.
485+
"""
486+
)
487+
public var enableUnsafeDebugging: Bool = false
488+
489+
/// Whether to disable debugging capabilities for code built by SwiftPM.
490+
@Flag(help: """
491+
Whether to disable unsafe debugging and backtraces for code built by SwiftPM. \
492+
Currently has an effect only on macOS.
493+
"""
494+
)
495+
public var disableUnsafeDebugging: Bool = false
496+
480497
// @Flag works best when there is a default value present
481498
// if true, false aren't enough and a third state is needed
482499
// nil should not be the goto. Instead create an enum
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2020-2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import struct Basics.Triple
14+
15+
extension BuildParameters {
16+
public struct Debugging: Encodable {
17+
public init(
18+
debugInfoFormat: DebugInfoFormat = .dwarf,
19+
targetTriple: Triple,
20+
shouldEnableDebuggingEntitlement: Bool
21+
) {
22+
self.debugInfoFormat = debugInfoFormat
23+
24+
// Per rdar://112065568 for backtraces to work on macOS a special entitlement needs to be granted on the final
25+
// executable.
26+
self.shouldEnableDebuggingEntitlement = targetTriple.isMacOSX && shouldEnableDebuggingEntitlement
27+
}
28+
29+
public var debugInfoFormat: DebugInfoFormat
30+
31+
/// Whether the produced executable
32+
public var shouldEnableDebuggingEntitlement: Bool
33+
}
34+
35+
/// Represents the debugging strategy.
36+
///
37+
/// Swift binaries requires the swiftmodule files in order for lldb to work.
38+
/// On Darwin, linker can directly take the swiftmodule file path using the
39+
/// -add_ast_path flag. On other platforms, we convert the swiftmodule into
40+
/// an object file using Swift's modulewrap tool.
41+
public enum DebuggingStrategy {
42+
case swiftAST
43+
case modulewrap
44+
}
45+
46+
/// The debugging strategy according to the current build parameters.
47+
public var debuggingStrategy: DebuggingStrategy? {
48+
guard configuration == .debug else {
49+
return nil
50+
}
51+
52+
if targetTriple.isApple() {
53+
return .swiftAST
54+
}
55+
return .modulewrap
56+
}
57+
58+
/// Represents the debug information format.
59+
///
60+
/// The debug information format controls the format of the debug information
61+
/// that the compiler generates. Some platforms support debug information
62+
// formats other than DWARF.
63+
public enum DebugInfoFormat: String, Encodable {
64+
/// DWARF debug information format, the default format used by Swift.
65+
case dwarf
66+
/// CodeView debug information format, used on Windows.
67+
case codeview
68+
/// No debug information to be emitted.
69+
case none
70+
}
71+
72+
}

Sources/SPMBuildCore/BuildParameters/BuildParameters.swift

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,6 @@ public struct BuildParameters: Encodable {
2626
case auto
2727
}
2828

29-
/// Represents the debug information format.
30-
///
31-
/// The debug information format controls the format of the debug information
32-
/// that the compiler generates. Some platforms support debug information
33-
// formats other than DWARF.
34-
public enum DebugInfoFormat: String, Encodable {
35-
/// DWARF debug information format, the default format used by Swift.
36-
case dwarf
37-
/// CodeView debug information format, used on Windows.
38-
case codeview
39-
/// No debug information to be emitted.
40-
case none
41-
}
42-
43-
/// Represents the debugging strategy.
44-
///
45-
/// Swift binaries requires the swiftmodule files in order for lldb to work.
46-
/// On Darwin, linker can directly take the swiftmodule file path using the
47-
/// -add_ast_path flag. On other platforms, we convert the swiftmodule into
48-
/// an object file using Swift's modulewrap tool.
49-
public enum DebuggingStrategy {
50-
case swiftAST
51-
case modulewrap
52-
}
53-
5429
/// The path to the data directory.
5530
public var dataPath: AbsolutePath
5631

@@ -125,10 +100,11 @@ public struct BuildParameters: Encodable {
125100
/// Whether the Xcode build system is used.
126101
public var isXcodeBuildSystemEnabled: Bool
127102

128-
public var debugInfoFormat: DebugInfoFormat
129-
130103
public var shouldSkipBuilding: Bool
131104

105+
/// Build parameters related to debugging.
106+
public var debuggingParameters: Debugging
107+
132108
/// Build parameters related to Swift Driver.
133109
public var driverParameters: Driver
134110

@@ -155,8 +131,8 @@ public struct BuildParameters: Encodable {
155131
sanitizers: EnabledSanitizers = EnabledSanitizers(),
156132
indexStoreMode: IndexStoreMode = .auto,
157133
isXcodeBuildSystemEnabled: Bool = false,
158-
debugInfoFormat: DebugInfoFormat = .dwarf,
159134
shouldSkipBuilding: Bool = false,
135+
debuggingParameters: Debugging = .init(),
160136
driverParameters: Driver = .init(),
161137
linkingParameters: Linking = .init(),
162138
outputParameters: Output = .init(),
@@ -169,7 +145,7 @@ public struct BuildParameters: Encodable {
169145
self._toolchain = _Toolchain(toolchain: toolchain)
170146
self.hostTriple = try hostTriple ?? .getHostTriple(usingSwiftCompiler: toolchain.swiftCompilerPath)
171147
self.targetTriple = targetTriple
172-
switch debugInfoFormat {
148+
switch debuggingParameters.debugInfoFormat {
173149
case .dwarf:
174150
var flags = flags
175151
// DWARF requires lld as link.exe expects CodeView debug info.
@@ -205,13 +181,12 @@ public struct BuildParameters: Encodable {
205181
self.sanitizers = sanitizers
206182
self.indexStoreMode = indexStoreMode
207183
self.isXcodeBuildSystemEnabled = isXcodeBuildSystemEnabled
208-
self.debugInfoFormat = debugInfoFormat
209184
self.shouldSkipBuilding = shouldSkipBuilding
185+
self.debuggingParameters = debuggingParameters
210186
self.driverParameters = driverParameters
211187
self.linkingParameters = linkingParameters
212188
self.outputParameters = outputParameters
213189
self.testingParameters = testingParameters ?? .init(configuration: configuration, targetTriple: targetTriple)
214-
215190
}
216191

217192
public func forTriple(_ targetTriple: Triple) throws -> BuildParameters {
@@ -280,19 +255,6 @@ public struct BuildParameters: Encodable {
280255
public var testOutputPath: AbsolutePath {
281256
return buildPath.appending(component: "testOutput.txt")
282257
}
283-
284-
/// The debugging strategy according to the current build parameters.
285-
public var debuggingStrategy: DebuggingStrategy? {
286-
guard configuration == .debug else {
287-
return nil
288-
}
289-
290-
if targetTriple.isApple() {
291-
return .swiftAST
292-
}
293-
return .modulewrap
294-
}
295-
296258
/// Returns the path to the binary of a product for the current build parameters.
297259
public func binaryPath(for product: ResolvedProduct) throws -> AbsolutePath {
298260
return try buildPath.appending(binaryRelativePath(for: product))

0 commit comments

Comments
 (0)