60 Commits

Author SHA1 Message Date
Tim Condon f01e3400ae Update README.md for archiving 2024-10-28 14:16:39 +00:00
Franz Busch 7277ee0e03 Merge pull request #73 from euanh/do-not-build-demangle-after-5.9
Do not build Demangle on Swift 5.9 or above
2024-06-17 11:33:03 +02:00
Euan Harris d4f33e71ca Do not build Demangle on Swift 5.9 or above
Pull request #68 prevents Backtrace from being built on Swift 5.9 and above,
but Demangle is still built and fails when the importing project uses musl.
2024-06-13 17:51:30 +01:00
Konrad `ktoso` Malawski 525d45046b Merge pull request #70 from yim-lee/ci-5.10 2024-06-14 00:34:35 +09:00
Yim Lee adc931806e fix ruby version too old error 2024-01-22 14:22:24 -08:00
Yim Lee defae63094 Add CI for Swift 5.10 2024-01-22 13:06:44 -08:00
Alastair Houghton 80746bdd0a Disable this library for Swift 5.9 and above. (#68) 2023-09-05 06:47:22 -07:00
Yim Lee 2cfddd6892 Update CI (#66)
- Add docker-compose file for Swift 5.8 and 5.9
- Update docker image for Swift 5.7
- Update `main` to Ubuntu 22.04
2023-04-04 14:31:55 -07:00
Yim Lee e9cffd432c Add .spi.yml for Swift Package Index DocC support (#63) 2022-12-05 11:35:05 -08:00
Yim Lee 9f43812fb5 Merge pull request #62 from yim-lee/docc
DocC setup
2022-08-11 10:43:55 -07:00
Yim Lee 9cc8c17785 Fix formatting 2022-08-10 21:56:25 -07:00
Yim Lee a0bfe70c1b Add manifest for Swift 5.0 2022-08-10 21:55:36 -07:00
Yim Lee 1809e7963b DocC setup 2022-08-10 21:53:01 -07:00
Johannes Weiss f25620d5d0 Merge pull request #60 from tomerd/fix/flush
flush stderr after printing backtraces
2022-06-14 20:32:13 +01:00
tom doron 3bd448574b flush stderr after printing back traces
motivation: make sure stderr buffered is printed out before program exits

changes: explicitly call fflush after writing the backtraces
2022-06-13 21:05:40 -07:00
tomer doron c085164685 update vendored copy of libbacktrace (#59)
motivation: catch up to fixes and improvments in underlying library

changes:
* vendor latest version of libbacktrace
* update vendoring script to exclude some new files that are not needed
2022-06-09 11:16:22 -07:00
tomer doron baf9597d12 trap SIGSEGV, SIGBUS and SIGFPE by default, in addition to SIGILL (#58)
motivation: print crash trace on segmentation faults and other common failures beyond illegal instructions

changes:
* include SIGSEGV, SIGBUS and SIGFPE in the default signals trapped
* update and improve tests
2022-06-08 09:06:33 -07:00
Konrad `ktoso` Malawski 7ba397e50d Merge pull request #57 from Fabio1988/patch-1
exit after printing stacktrace #51
2022-04-06 10:45:57 +09:00
Fabio1988 ad485ae151 exit after printing stacktrace #51 2022-03-17 12:17:02 +01:00
tomer doron 662e436989 ci update (#56)
motivation: 5.6 is out

changes:
* use release version of 5.6
* add docker setup for 5.7 (using nightly for now)
2022-03-16 21:15:06 -07:00
Konrad `ktoso` Malawski 923624a26e Merge pull request #53 from swift-server/tomerd-patch-2
update CI setup with new versions of swift
2021-09-23 06:03:22 +09:00
tomer doron e2621e2fa1 Create docker-compose.2004.main.yaml
* add ci setup for nightly toolchain
2021-09-22 12:02:54 -07:00
tomer doron ea4824d488 Update Dockerfile
address jazzy install issues on older ubuntu versions
2021-09-22 12:00:46 -07:00
tomer doron f1db8bf93d update CI setup with new versions of swift
motivation: 5.5 release is available

changes: 
* add docker CI setup to for 5.5
2021-09-22 11:56:43 -07:00
tomer doron 99a6c79fc5 Update README.md (#50)
motivation: highlight the background for this library and incourage use via service-lifecycle 

changes: update readme to reflect these ideas
2021-07-28 16:13:56 -07:00
Johannes Weiss d3e04a9d4b Merge pull request #49 from weissi/jw-other-platforms
forgot other platforms
2021-07-16 19:50:16 +01:00
Johannes Weiss b3b195e0e6 forgot other platforms 2021-07-16 19:34:47 +01:00
Johannes Weiss e434780428 Merge pull request #48 from weissi/jw-signals
allow other signals
2021-07-15 21:24:11 +01:00
Johannes Weiss ceaaf36f0f allow other signals 2021-07-15 19:40:14 +01:00
Konrad `ktoso` Malawski bb3bd2357e Merge pull request #45 from swift-server/tomerd-patch-1
adopt SSWG security guidelines
2021-06-21 11:24:12 +09:00
tomer doron 5f7686a18b Merge branch 'main' into tomerd-patch-1 2021-06-11 09:13:34 -07:00
tomer doron d9655c7867 add 5.4 CI (#46)
motivation: 5.4 was released, add 5.4 CI

changes: add docker-compose setup for 5.4
2021-06-11 09:13:24 -07:00
tomer doron 84bcaad52f Update README.md 2021-06-08 10:38:03 -07:00
tomer doron 7152ac0033 adopt SSWG security guidelines
add SECURITY.md detailing the security process
2021-06-08 10:37:16 -07:00
tomer doron 54a65d6391 recent changes to support windows broke macos (#44)
motivation: unbreak macos

changes: make _stdlib_demangleName only available on macOS and Windows where it is fully supported
2021-04-20 11:04:11 -07:00
Saleem Abdulrasool 1ca1dbd9ff README: add acknowledgement for Windows port (#43) 2021-04-20 10:10:33 -07:00
Johannes Weiss 182caea1a4 Merge pull request #42 from compnerd/windows
Backtrace: enable support for Windows
2021-04-20 14:04:13 +01:00
Saleem Abdulrasool 5b47490c74 Backtrace: adjust style (NFC)
Adjust the style for the linter.
2021-04-19 13:13:09 -07:00
Saleem Abdulrasool b097912943 Backtrace: enable support for Windows
Add an implementation across all architectures supported by Windows:
- x86
- x86_64
- ARM
- ARM64

This relies on DbgHlp32.dll which makes this unfriendly to store
applications.  We can investigate improvements to that in the future.
This sketches out an implementation which allows building and using the
interface for providing backtraces.  This requires that the programs be
built with debug information in CodeView format.  Without the additional
debug information, the stack traces will be limited to symbolication and
resolution to export only symbols.

Resolves: #34
2021-04-18 11:16:45 -07:00
Saleem Abdulrasool a4f7b4204e Backtrace: make _stdlib_demangleName part of all platforms (#41) 2021-04-17 21:45:37 -07:00
Saleem Abdulrasool 9a2ef536ee git: ignore vim swap files (#39) 2021-04-17 19:54:24 -07:00
Johannes Weiss c859218177 Merge pull request #37 from mpdifran/patch-1
Update build flags with Swift version info
2021-03-03 10:24:02 +00:00
Mark DiFranco 1d5fbd8c42 Update build flags with Swift version info
As of Swift 5.2, this build flag is no longer necessary.
2021-03-01 09:11:11 -05:00
Johannes Weiss 93b3d9a764 Merge pull request #35 from weissi/jw-error
better distinguish mmap errors & print errno
2021-02-22 11:10:40 +00:00
Johannes Weiss 4353fd38d5 Merge branch 'main' into jw-error 2021-02-22 11:09:50 +00:00
Johannes Weiss 97a034c8a4 Merge pull request #36 from weissi/jw-exe-name
determine the executable path automatically
2021-02-22 11:09:38 +00:00
Johannes Weiss 566d2454b2 determine the executable path automatically
Motivation:

Previously, we would use
`CommandLine.arguments[0]`/`argv[0]`/`getexecname()` as the preferred
ways to find the main binary. That sounds sensible, especially given
the fact that we'd fall back onto other methods (such as
`/proc/self/exe`) when the previous ones don't work.

There is however an unfortunate edge case. If you for example have your
app binary at `/app/app` and you start it with a relative path `./app`
from within `/app`, then `CommandLine.arguments[0]` will only contain
`./app`. If now the app changes its working directory to `/`, `./app`
would mean `/app` which is the directory. This would mean we will find
the target but instead of the binary we'd find the directory `/app`.
From then on, everything else fails.

A similar problem is if `argv[0]` was actually set incorrectly when
`exec*`ing the process. This has happened at least in one instance.

Modification:

Given that we only target Linux here, we can actually here, we can
change the order in which we try to find the main binary. We can start
by using `/proc/self/exe` which is a very high quality and almost
guaranteed to work way to find the main binary, nevermind the
information in `argv`.

Result:

More robust symbolications, especially in environments like Heroku/Dokku
where we've seen `argv` not being set correctly.
2021-02-21 18:28:38 +00:00
Johannes Weiss c8d8ddd88b better distinguish mmap errors & print errno
Motivation:

In case SwiftBacktrace fails, we get only very little output.
Unfortunately, some crucial information (like the errno) is missing and
in case `mmap` fails, we don't know if the problem is file I/O or
allocating memory.

Modification:

- print errnos
- distinguish the two mmaps

Result:

Easier debugging
2021-02-20 23:12:33 +00:00
tomer doron 4915cdd24e remove symbolicate-linux-fatal from Docker (#33)
motivation: we are not actually using symbolicate-linux-fatal in any meaningful way in CI and it's pinned to the master branch which has been removed

changes: remove symbolicate-linux-fatal fetching from Docker
2020-10-07 17:29:02 -07:00
tomer doron 7a48ec7baa Swift 5.3 was released, use if for CI (#32)
motivation: Swift 5.3 was released, use if for CI

changes: update docker setup to use the release version of 5.3
2020-09-18 12:59:21 -07:00
tomer doron c6559c866c stabilize ci (#31)
motivation: update swift-server ci

changes: 
* remove travis ci definition
* dont install jazzy on 16.04 - its broken on that version and not in use  (stabilize ci)
* using 5.3 nightlies (stabilize ci)
2020-08-19 11:33:07 -07:00
tomer doron 232bd5bdbc update ci setup (#27)
motivation: 5.2 adoption, prepare for 5.3

changes:
* add 5.2 docker-compose setup
* add 5.3 docker-compose setup (placeholder)
2020-04-04 00:20:09 -07:00
tomer doron f2fd8c4845 add testing (#26)
motivation: make sure library works as expected

changes:
* add a Sample target we can use for testing
* add a test to make sure backtraces are printed as expected
* make docker tests use a release version for a more realistic tests
* update linux test generation script to work with release builds
2020-03-25 12:29:57 -07:00
tomer doron 7faa1c401b remove print from public API (#25)
motivation: reduce public API surface area given the plan is to abosrb this library in the language runtime eventually

changes:
* make print function private
* remove explicit swift-server file
2020-03-25 12:06:04 -07:00
tomer doron 1afd60a0bb ci setup (#23)
motivation: setup ci for the project

changes:
* add docker setup for testing 5.0, 5.1 and 5.2
* fix license headers
* add sanity script
* format
* regenerate tests to match convention
2020-03-20 16:20:00 -07:00
Ian Partridge 5074f997bf Fix package url in README.md (#21) 2020-03-05 12:48:10 +00:00
Tanner f5462810b8 Update README.md 2020-02-18 10:48:35 -05:00
Tanner e735696872 Update README.md 2020-02-18 10:48:24 -05:00
Ian Partridge 383950b36a ci: Swift 5.1 testing (#20) 2019-11-01 13:54:05 +01:00
Ian Partridge feaee74aa6 Update README.md 2019-09-11 08:59:31 -04:00
60 changed files with 5538 additions and 1025 deletions
+2
View File
@@ -2,3 +2,5 @@
/.build
/Packages
/*.xcodeproj
.swiftpm
.*.sw[nop]
+3
View File
@@ -0,0 +1,3 @@
Tomer Doron <tomer@apple.com> <tomer@apple.com>
Tomer Doron <tomer@apple.com> <tomerd@apple.com>
Tomer Doron <tomer@apple.com> <tomer.doron@gmail.com>
+4
View File
@@ -0,0 +1,4 @@
version: 1
builder:
configs:
- documentation_targets: [Backtrace]
-1
View File
@@ -1 +0,0 @@
5.0.1
+13
View File
@@ -0,0 +1,13 @@
# file options
--swiftversion 5.0
--exclude .build
# format options
--self insert
--patternlet inline
--stripunusedargs unnamed-only
--ifdef no-indent
# rules
-40
View File
@@ -1,40 +0,0 @@
branches:
only:
- master
# The matrix of builds should cover each combination of Swift version
# and platform that is supported. The version of Swift used is specified
# by .swift-version, unless SWIFT_SNAPSHOT is specified.
matrix:
include:
- os: linux
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:4.2.4 SWIFT_SNAPSHOT=4.2.4
- os: linux
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:5.0-xenial
- os: linux
dist: xenial
sudo: required
services: docker
env: DOCKER_IMAGE=swift:5.0-bionic
- os: osx
osx_image: xcode10.1
sudo: required
env: SWIFT_SNAPSHOT=4.2.1
- os: osx
osx_image: xcode10.2
sudo: required
- os: osx
osx_image: xcode11
sudo: required
before_install:
- git clone https://github.com/IBM-Swift/Package-Builder.git
script:
- ./Package-Builder/build-package.sh -projectDir $TRAVIS_BUILD_DIR
+21
View File
@@ -0,0 +1,21 @@
For the purpose of tracking copyright, this is the list of individuals and
organizations who have contributed source code to SwiftLinuxBacktrace.
For employees of an organization/company where the copyright of work done
by employees of that company is held by the company itself, only the company
needs to be listed here.
## COPYRIGHT HOLDERS
- Apple Inc. (all contributors with '@apple.com')
### Contributors
- Ian Partridge <i.partridge@uk.ibm.com>
- Tanner <me@tanner.xyz>
- Tomer Doron <tomer@apple.com>
- Zsolt Váradi <vzsg@users.noreply.github.com>
**Updating this list**
Please do not edit this file manually. It is generated using `./scripts/generate_contributors_list.sh`. If a name is misspelled or appearing multiple times: add an entry in `./.mailmap`
+9 -4
View File
@@ -1,4 +1,4 @@
// swift-tools-version:5.0
// swift-tools-version:5.6
import PackageDescription
@@ -7,15 +7,20 @@ let package = Package(
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]),
targets: ["Backtrace"]
),
],
dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
],
dependencies: [],
targets: [
.target(name: "Backtrace",
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.executableTarget(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"])
dependencies: ["Backtrace"]),
]
)
@@ -1,4 +1,4 @@
// swift-tools-version:4.2
// swift-tools-version:5.0
import PackageDescription
@@ -7,7 +7,8 @@ let package = Package(
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]),
targets: ["Backtrace"]
),
],
dependencies: [],
targets: [
@@ -15,7 +16,9 @@ let package = Package(
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.target(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"])
]
dependencies: ["Backtrace"]),
]
)
+24
View File
@@ -0,0 +1,24 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "swift-backtrace",
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]
),
],
dependencies: [],
targets: [
.target(name: "Backtrace",
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.target(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"]),
]
)
+24
View File
@@ -0,0 +1,24 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "swift-backtrace",
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]
),
],
dependencies: [],
targets: [
.target(name: "Backtrace",
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.target(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"]),
]
)
+24
View File
@@ -0,0 +1,24 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "swift-backtrace",
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]
),
],
dependencies: [],
targets: [
.target(name: "Backtrace",
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.target(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"]),
]
)
+24
View File
@@ -0,0 +1,24 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "swift-backtrace",
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]
),
],
dependencies: [],
targets: [
.target(name: "Backtrace",
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.target(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"]),
]
)
+24
View File
@@ -0,0 +1,24 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "swift-backtrace",
products: [
.library(
name: "Backtrace",
targets: ["Backtrace"]
),
],
dependencies: [],
targets: [
.target(name: "Backtrace",
dependencies: ["CBacktrace"]),
.target(name: "CBacktrace",
dependencies: []),
.target(name: "Sample",
dependencies: ["Backtrace"]),
.testTarget(name: "BacktraceTests",
dependencies: ["Backtrace"]),
]
)
+23 -4
View File
@@ -1,12 +1,23 @@
> [!IMPORTANT]
> This library is now archived as backtracing is built into Swift 5.9+
# Backtrace
This Swift package provides support for automatically printing crash backtraces of Swift programs.
The library is designed to fill a gap in backtraces support for Swift on non-Darwin platforms.
When this gap is closed at the language runtime level, this library will become redundant and be deprecated.
## Usage
Add `https://github.com/ianpartridge/swift-backtrace.git` as a dependency in your `Package.swift`.
**Note**: You do not need this library on Linux as of Swift 5.9, which has
built-in backtracing support.
Then, in your `main.swift`, do:
Add `https://github.com/swift-server/swift-backtrace.git` as a dependency in your `Package.swift`.
### Crash backtraces
In your `main.swift`, do:
```swift
import Backtrace
@@ -15,7 +26,7 @@ import Backtrace
Backtrace.install()
```
Finally, make sure you build your application with debug symbols enabled:
Finally, for Swift < 5.2, make sure you build your application with debug symbols enabled. Debug symbols are automatically included for Swift 5.2 and above.
```
$ swift build -c release -Xswiftc -g
@@ -23,6 +34,14 @@ $ swift build -c release -Xswiftc -g
When your app crashes, a stacktrace will be printed to `stderr`.
## Security
Please see [SECURITY.md](SECURITY.md) for details on the security process.
## Acknowledgements
@weissi, for the signal handling code!
Ian Partridge ([GitHub](https://github.com/ianpartridge/), [Twitter](https://twitter.com/alfa)) the original author of this package.
Johannes Weiss ([GitHub](https://github.com/weissi), [Twitter](https://twitter.com/johannesweiss)) for the signal handling code.
Saleem Abdulrasool ([GitHub](https://github.com/compnerd), [Twitter](https://twitter.com/compnerd)) for the Windows port.
+43
View File
@@ -0,0 +1,43 @@
# Security
This document specifies the security process for the Backtrace project.
## Disclosures
### Private Disclosure Process
The Backtrace maintainers ask that known and suspected vulnerabilities be
privately and responsibly disclosed by emailing
[sswg-security-reports@forums.swift.org](mailto:sswg-security-reports@forums.swift.org)
with the all the required detail.
**Do not file a public issue.**
#### When to report a vulnerability
* You think you have discovered a potential security vulnerability in Backtrace.
* You are unsure how a vulnerability affects Backtrace.
#### What happens next?
* A member of the team will acknowledge receipt of the report within 3
working days (United States). This may include a request for additional
information about reproducing the vulnerability.
* We will privately inform the Swift Server Work Group ([SSWG][sswg]) of the
vulnerability within 10 days of the report as per their [security
guidelines][sswg-security].
* Once we have identified a fix we may ask you to validate it. We aim to do this
within 30 days. In some cases this may not be possible, for example when the
vulnerability exists at the protocol level and the industry must coordinate on
the disclosure process.
* If a CVE number is required, one will be requested from [MITRE][mitre]
providing you with full credit for the discovery.
* We will decide on a planned release date and let you know when it is.
* Prior to release, we will inform major dependents that a security-related
patch is impending.
* Once the fix has been released we will publish a security advisory on GitHub
and in the Server → Security Updates category on the [Swift forums][swift-forums-sec].
[sswg]: https://github.com/swift-server/sswg
[sswg-security]: https://github.com/swift-server/sswg/blob/main/security/README.md
[swift-forums-sec]: https://forums.swift.org/c/server/security-updates/
[mitre]: https://cveform.mitre.org/
+222 -11
View File
@@ -1,16 +1,44 @@
#if os(Linux)
import Glibc
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2022 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
// Swift 5.9 has its own built-in backtracing support in the runtime;
// we don't want to activate this library if we're using 5.9 or above.
#if swift(>=5.9) && !os(Windows)
public enum Backtrace {
@available(*, deprecated, message: "This is no longer needed in Swift 5.9")
public static func install() {}
@available(*, deprecated, message: "This is no longer needed in Swift 5.9")
public static func install(signals: [CInt]) {}
@available(*, deprecated, message: "This method will be removed in the next major version.")
public static func print() {}
}
#elseif os(Linux)
import CBacktrace
import Glibc
typealias CBacktraceErrorCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ msg: UnsafePointer<CChar>?, _ errnum: CInt) -> Void
typealias CBacktraceFullCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ pc: UInt, _ filename: UnsafePointer<CChar>?, _ lineno: CInt, _ function: UnsafePointer<CChar>?) -> CInt
typealias CBacktraceSimpleCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ pc: UInt) -> CInt
typealias CBacktraceSyminfoCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ pc: UInt, _ filename: UnsafePointer<CChar>?, _ symval: UInt, _ symsize: UInt) -> Void
private let state = backtrace_create_state(CommandLine.arguments[0], /* BACKTRACE_SUPPORTS_THREADS */ 1, nil, nil)
private let state = backtrace_create_state(nil, /* BACKTRACE_SUPPORTS_THREADS */ 1, nil, nil)
private let fullCallback: CBacktraceFullCallback? = {
data, pc, filename, lineno, function in
_, pc, filename, lineno, function in
var str = "0x"
str.append(String(pc, radix: 16))
@@ -39,21 +67,37 @@ private let fullCallback: CBacktraceFullCallback? = {
}
private let errorCallback: CBacktraceErrorCallback? = {
data, msg, errnum in
_, msg, errNo in
if let msg = msg {
_ = withVaList([msg]) { vaList in
vfprintf(stderr, "%s\n", vaList)
_ = withVaList([msg, errNo]) { vaList in
vfprintf(stderr, "SwiftBacktrace ERROR: %s (errno: %d)\n", vaList)
}
}
}
private func printBacktrace(signal: CInt) {
_ = fputs("Received signal \(signal). Backtrace:\n", stderr)
backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil)
fflush(stderr)
}
public enum Backtrace {
/// Install the backtrace handler on default signals: `SIGILL`, `SIGSEGV`, `SIGBUS`, `SIGFPE`.
public static func install() {
setupHandler(signal: SIGILL) { _ in
backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil)
Backtrace.install(signals: [SIGILL, SIGSEGV, SIGBUS, SIGFPE])
}
/// Install the backtrace handler when any of `signals` happen.
public static func install(signals: [CInt]) {
for signal in signals {
self.setupHandler(signal: signal) { signal in
printBacktrace(signal: signal)
raise(signal)
}
}
}
@available(*, deprecated, message: "This method will be removed in the next major version.")
public static func print() {
backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil)
}
@@ -70,12 +114,179 @@ public enum Backtrace {
}
}
}
#elseif os(Windows)
#if swift(<5.4)
#error("unsupported Swift version")
#else
@_implementationOnly import CRT
@_implementationOnly import WinSDK
#endif
public enum Backtrace {
public static func install() {
private static var MachineType: DWORD {
#if arch(arm)
DWORD(IMAGE_FILE_MACHINE_ARMNT)
#elseif arch(arm64)
DWORD(IMAGE_FILE_MACHINE_ARM64)
#elseif arch(i386)
DWORD(IMAGE_FILE_MACHINE_I386)
#elseif arch(x86_64)
DWORD(IMAGE_FILE_MACHINE_AMD64)
#else
#error("unsupported architecture")
#endif
}
public static func print() {
/// Signal selection unavailable on Windows. Use ``install()-484jy``.
@available(*, deprecated, message: "signal selection unavailable on Windows")
public static func install(signals: [CInt]) {
Backtrace.install()
}
/// Install the backtrace handler on default signals.
public static func install() {
// Install a last-chance vectored exception handler to capture the error
// before the termination and report the stack trace. It is unlikely
// that this will be recovered at this point by a SEH handler.
_ = AddVectoredExceptionHandler(0) { _ in
// NOTE: GetCurrentProcess does not increment the reference count on
// the process. This handle should _not_ be closed upon completion.
let hProcess: HANDLE = GetCurrentProcess()
var cxr: CONTEXT = CONTEXT()
cxr.ContextFlags =
DWORD(CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
RtlCaptureContext(&cxr)
_ = SymInitializeW(hProcess, nil, true)
_ = SymSetOptions(DWORD(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME))
var Frame: STACKFRAME64 = STACKFRAME64()
#if arch(arm)
Frame.AddrPC.Offset = cxr.Pc
Frame.AddrFrame.Offset = cxr.R11
Frame.AddrStack.Offset = cxr.Sp
#elseif arch(arm64)
Frame.AddrPC.Offset = cxr.Pc
Frame.AddrFrame.Offset = cxr.Fp
Frame.AddrStack.Offset = cxr.Sp
#elseif arch(i386)
Frame.AddrPC.Offset = cxr.Eip
Frame.AddrFrame.Offset = cxr.Ebp
Frame.AddrStack.Offset = cxr.Esp
#elseif arch(x86_64)
Frame.AddrPC.Offset = cxr.Rip
Frame.AddrFrame.Offset = cxr.Rbp
Frame.AddrStack.Offset = cxr.Rsp
#else
#error("unsupported architecture")
#endif
Frame.AddrPC.Mode = AddrModeFlat
Frame.AddrFrame.Mode = AddrModeFlat
Frame.AddrStack.Mode = AddrModeFlat
// Constant indicating the maximum symbol length that we expect
// during symbolication of the stack trace.
let kMaxSymbolLength: Int = 255
// Heap allocate the buffer as we need to account for the trailing
// storage that we need to provide.
let pSymbolBuffer: UnsafeMutableRawPointer =
UnsafeMutableRawPointer.allocate(byteCount: MemoryLayout<IMAGEHLP_SYMBOL64>.size + kMaxSymbolLength,
alignment: 1)
defer { pSymbolBuffer.deallocate() }
let pSymbol: UnsafeMutablePointer<IMAGEHLP_SYMBOL64> =
pSymbolBuffer.bindMemory(to: IMAGEHLP_SYMBOL64.self,
capacity: 1)
let hThread: HANDLE = GetCurrentThread()
while StackWalk64(Backtrace.MachineType, hProcess, hThread,
&Frame, &cxr, nil, SymFunctionTableAccess64,
SymGetModuleBase64, nil) {
var qwModuleBase: DWORD64 =
SymGetModuleBase64(hProcess, Frame.AddrPC.Offset)
let module: String = withUnsafeMutablePointer(to: &qwModuleBase) {
$0.withMemoryRebound(to: HINSTANCE.self, capacity: 1) { hInstance in
String(decoding: [WCHAR](unsafeUninitializedCapacity: Int(MAX_PATH + 1)) {
$1 = Int(GetModuleFileNameW(hInstance.pointee,
$0.baseAddress,
DWORD($0.count)))
}, as: UTF16.self)
}
}
pSymbol.pointee.SizeOfStruct =
DWORD(MemoryLayout<IMAGEHLP_SYMBOL64>.size)
pSymbol.pointee.MaxNameLength = DWORD(kMaxSymbolLength)
_ = SymGetSymFromAddr64(hProcess, Frame.AddrPC.Offset, nil,
pSymbol)
var symbol: String =
withUnsafePointer(to: &pSymbol.pointee.Name) {
String(cString: $0)
}
// Undecorate Swift 3+ names only. Earlier Swift decorations
// are unsupported. Any MSVC name decoration has been
// unperformed during the DbgHelp operation through the use of
// the `SYMOPT_UNDNAME` option.
if symbol.hasPrefix("$s") || symbol.hasPrefix("$S") {
symbol = _stdlib_demangleName(symbol)
}
var Displacement: DWORD = 0
var Line: IMAGEHLP_LINE64 = IMAGEHLP_LINE64()
Line.SizeOfStruct = DWORD(MemoryLayout<IMAGEHLP_LINE64>.size)
_ = SymGetLineFromAddr64(hProcess, Frame.AddrPC.Offset,
&Displacement, &Line)
var details: String = ""
if !symbol.isEmpty {
// Truncate the module path to the filename. The
// `PathFindFileNameW` call will return the beginning of the
// string if a path separator character is not found.
if let pszModule = module.withCString(encodedAs: UTF16.self,
PathFindFileNameW) {
details.append(", \(String(decodingCString: pszModule, as: UTF16.self))!\(symbol)")
}
}
if let szFileName = Line.FileName {
details.append(" at \(String(cString: szFileName)):\(Line.LineNumber)")
}
_ = details.withCString { pszDetails in
withVaList([Frame.AddrPC.Offset, pszDetails]) {
#if arch(arm64) || arch(x86_64)
vfprintf(stderr, "%#016x%s\n", $0)
#else
vfprintf(stderr, "%#08x%s\n", $0)
#endif
}
}
}
_ = SymCleanup(hProcess)
// We have not handled the exception, continue the search.
return EXCEPTION_CONTINUE_SEARCH
}
}
}
#else
public enum Backtrace {
/// Install the backtrace handler on default signals. Available on Windows and Linux only.
public static func install() {}
/// Install the backtrace handler on specific signals. Available on Linux only.
public static func install(signals: [CInt]) {}
@available(*, deprecated, message: "This method will be removed in the next major version.")
public static func print() {}
}
#endif
+32 -4
View File
@@ -1,9 +1,33 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
// Swift 5.9 has its own built-in backtracing support in the runtime;
// we don't want to activate this library if we're using 5.9 or above.
#if !(swift(>=5.9) && !os(Windows))
#if os(Linux)
import Glibc
#elseif os(Windows)
#if swift(<5.4)
#error("unsupported Swift version")
#else
import Darwin
@_implementationOnly
import ucrt
#endif
#endif
#if os(Linux) || os(Windows)
@_silgen_name("swift_demangle")
public
func _stdlib_demangleImpl(
@@ -12,18 +36,19 @@ func _stdlib_demangleImpl(
outputBuffer: UnsafeMutablePointer<CChar>?,
outputBufferSize: UnsafeMutablePointer<UInt>?,
flags: UInt32
) -> UnsafeMutablePointer<CChar>?
) -> UnsafeMutablePointer<CChar>?
internal func _stdlib_demangleName(_ mangledName: String) -> String {
return mangledName.utf8CString.withUnsafeBufferPointer {
(mangledNameUTF8CStr) in
mangledNameUTF8CStr in
let demangledNamePtr = _stdlib_demangleImpl(
mangledName: mangledNameUTF8CStr.baseAddress,
mangledNameLength: UInt(mangledNameUTF8CStr.count - 1),
outputBuffer: nil,
outputBufferSize: nil,
flags: 0)
flags: 0
)
if let demangledNamePtr = demangledNamePtr {
let demangledName = String(cString: demangledNamePtr)
@@ -33,3 +58,6 @@ internal func _stdlib_demangleName(_ mangledName: String) -> String {
return mangledName
}
}
#endif
#endif
+34
View File
@@ -0,0 +1,34 @@
# ``Backtrace``
Provides support for automatically printing crash backtraces of Swift programs.
## Overview
The Backtrace library is designed to fill a gap in backtraces support for Swift on non-Darwin platforms.
When this gap is closed at the language runtime level, this library will become redundant and be deprecated.
## Getting started
When building web-services and daemons, direct usage of this library is discouraged.
Instead, use [swift-service-lifecycle](https://github.com/swift-server/swift-service-lifecycle) which helps manage the application lifecycle including setting up backtraces hooks when needed.
Add `https://github.com/swift-server/swift-backtrace.git` as a dependency in your `Package.swift`.
### Crash backtraces
In your `main.swift`, do:
```swift
import Backtrace
// Do this first
Backtrace.install()
```
Finally, for Swift < 5.2, make sure you build your application with debug symbols enabled. Debug symbols are automatically included for Swift 5.2 and above.
```
$ swift build -c release -Xswiftc -g
```
When your app crashes, a stacktrace will be printed to `stderr`.
+1 -1
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* atomic.c -- Support for atomic functions if not present.
Copyright (C) 2013-2018 Free Software Foundation, Inc.
Copyright (C) 2013-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* backtrace-supported.h.in -- Whether stack backtrace is supported.
Copyright (C) 2012-2016 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
+2 -2
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* backtrace.c -- Entry point for stack backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,7 @@ unwind (struct _Unwind_Context *context, void *vdata)
/* Get a stack backtrace. */
int
int __attribute__((noinline))
backtrace_full (struct backtrace_state *state, int skip,
backtrace_full_callback callback,
backtrace_error_callback error_callback, void *data)
+23 -3
View File
@@ -14,6 +14,10 @@
/* Define to 1 if you have the `clock_gettime' function. */
#define HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the declaration of `getpagesize', and to 0 if you
don't. */
#define HAVE_DECL_GETPAGESIZE 1
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
don't. */
#define HAVE_DECL_STRNLEN 1
@@ -36,8 +40,16 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `z' library (-lz). */
/* #undef HAVE_LIBZ */
/* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.
*/
/* #undef HAVE_KERN_PROC */
/* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in
<sys/sysctl.h>. */
/* #undef HAVE_KERN_PROC_ARGS */
/* Define if -llzma is available. */
/* #undef HAVE_LIBLZMA */
/* Define to 1 if you have the <link.h> header file. */
#define HAVE_LINK_H 1
@@ -48,6 +60,9 @@
/* Define to 1 if you have the `lstat' function. */
#define HAVE_LSTAT 1
/* Define to 1 if you have the <mach-o/dyld.h> header file. */
/* #undef HAVE_MACH_O_DYLD_H */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
@@ -85,7 +100,7 @@
#define HAVE_UNISTD_H 1
/* Define if -lz is available. */
/* #undef HAVE_ZLIB */
#define HAVE_ZLIB 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
@@ -134,6 +149,11 @@
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
+1953 -677
View File
File diff suppressed because it is too large Load Diff
+1792 -213
View File
File diff suppressed because it is too large Load Diff
+147 -2
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* fileline.c -- Get file and line number information in a backtrace.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,14 @@ POSSIBILITY OF SUCH DAMAGE. */
#include <stdlib.h>
#include <unistd.h>
#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
#include <sys/sysctl.h>
#endif
#ifdef HAVE_MACH_O_DYLD_H
#include <mach-o/dyld.h>
#endif
#include "include/backtrace.h"
#include "internal.h"
@@ -47,6 +55,107 @@ POSSIBILITY OF SUCH DAMAGE. */
#define getexecname() NULL
#endif
#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
#define sysctl_exec_name1(state, error_callback, data) NULL
#define sysctl_exec_name2(state, error_callback, data) NULL
#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
static char *
sysctl_exec_name (struct backtrace_state *state,
int mib0, int mib1, int mib2, int mib3,
backtrace_error_callback error_callback, void *data)
{
int mib[4];
size_t len;
char *name;
size_t rlen;
mib[0] = mib0;
mib[1] = mib1;
mib[2] = mib2;
mib[3] = mib3;
if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
return NULL;
name = (char *) backtrace_alloc (state, len, error_callback, data);
if (name == NULL)
return NULL;
rlen = len;
if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
{
backtrace_free (state, name, len, error_callback, data);
return NULL;
}
return name;
}
#ifdef HAVE_KERN_PROC_ARGS
static char *
sysctl_exec_name1 (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
/* This variant is used on NetBSD. */
return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
KERN_PROC_PATHNAME, error_callback, data);
}
#else
#define sysctl_exec_name1(state, error_callback, data) NULL
#endif
#ifdef HAVE_KERN_PROC
static char *
sysctl_exec_name2 (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
/* This variant is used on FreeBSD. */
return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
error_callback, data);
}
#else
#define sysctl_exec_name2(state, error_callback, data) NULL
#endif
#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
#ifdef HAVE_MACH_O_DYLD_H
static char *
macho_get_executable_path (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
uint32_t len;
char *name;
len = 0;
if (_NSGetExecutablePath (NULL, &len) == 0)
return NULL;
name = (char *) backtrace_alloc (state, len, error_callback, data);
if (name == NULL)
return NULL;
if (_NSGetExecutablePath (name, &len) != 0)
{
backtrace_free (state, name, len, error_callback, data);
return NULL;
}
return name;
}
#else /* !defined (HAVE_MACH_O_DYLD_H) */
#define macho_get_executable_path(state, error_callback, data) NULL
#endif /* !defined (HAVE_MACH_O_DYLD_H) */
/* Initialize the fileline information from the executable. Returns 1
on success, 0 on failure. */
@@ -84,7 +193,7 @@ fileline_initialize (struct backtrace_state *state,
descriptor = -1;
called_error_callback = 0;
for (pass = 0; pass < 5; ++pass)
for (pass = 0; pass < 8; ++pass)
{
int does_not_exist;
@@ -107,6 +216,15 @@ fileline_initialize (struct backtrace_state *state,
(long) getpid ());
filename = buf;
break;
case 5:
filename = sysctl_exec_name1 (state, error_callback, data);
break;
case 6:
filename = sysctl_exec_name2 (state, error_callback, data);
break;
case 7:
filename = macho_get_executable_path (state, error_callback, data);
break;
default:
abort ();
}
@@ -200,4 +318,31 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
state->syminfo_fn (state, pc, callback, error_callback, data);
return 1;
}
/* A backtrace_syminfo_callback that can call into a
backtrace_full_callback, used when we have a symbol table but no
debug info. */
void
backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
const char *symname,
uintptr_t symval ATTRIBUTE_UNUSED,
uintptr_t symsize ATTRIBUTE_UNUSED)
{
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname);
}
/* An error callback that corresponds to
backtrace_syminfo_to_full_callback. */
void
backtrace_syminfo_to_full_error_callback (void *data, const char *msg,
int errnum)
{
struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
bdata->full_error_callback (bdata->full_data, msg, errnum);
}
#endif
+3
View File
@@ -45,7 +45,10 @@ POSSIBILITY OF SUCH DAMAGE. */
#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
# define HAS_DRIVE_SPEC(f) ((f)[0] != '\0' && (f)[1] == ':')
# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f))
#else
# define IS_DIR_SEPARATOR(c) ((c) == '/')
# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))
#endif
#endif
+16 -9
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* backtrace.h -- Public header file for stack backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -55,13 +55,14 @@ struct backtrace_state;
invalid after this function returns.
As a special case, the ERRNUM argument will be passed as -1 if no
debug info can be found for the executable, but the function
requires debug info (e.g., backtrace_full, backtrace_pcinfo). The
MSG in this case will be something along the lines of "no debug
info". Similarly, ERRNUM will be passed as -1 if there is no
symbol table, but the function requires a symbol table (e.g.,
backtrace_syminfo). This may be used as a signal that some other
approach should be tried. */
debug info can be found for the executable, or if the debug info
exists but has an unsupported version, but the function requires
debug info (e.g., backtrace_full, backtrace_pcinfo). The MSG in
this case will be something along the lines of "no debug info".
Similarly, ERRNUM will be passed as -1 if there is no symbol table,
but the function requires a symbol table (e.g., backtrace_syminfo).
This may be used as a signal that some other approach should be
tried. */
typedef void (*backtrace_error_callback) (void *data, const char *msg,
int errnum);
@@ -76,7 +77,13 @@ typedef void (*backtrace_error_callback) (void *data, const char *msg,
use appropriate atomic operations. If THREADED is zero the state
may only be accessed by one thread at a time. This returns a state
pointer on success, NULL on error. If an error occurs, this will
call the ERROR_CALLBACK routine. */
call the ERROR_CALLBACK routine.
Calling this function allocates resources that cannot be freed.
There is no backtrace_free_state function. The state is used to
cache information that is expensive to recompute. Programs are
expected to call this function at most once and to save the return
value for all later calls to backtrace functions. */
extern struct backtrace_state *backtrace_create_state (
const char *filename, int threaded,
+89 -13
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* internal.h -- Internal header file for stack backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,14 @@ POSSIBILITY OF SUCH DAMAGE. */
# endif
#endif
#ifndef ATTRIBUTE_FALLTHROUGH
# if (GCC_VERSION >= 7000)
# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
# else
# define ATTRIBUTE_FALLTHROUGH
# endif
#endif
#ifndef HAVE_SYNC_FUNCTIONS
/* Define out the sync functions. These should never be called if
@@ -180,7 +188,7 @@ struct backtrace_view
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the
result in *VIEW. Returns 1 on success, 0 on error. */
extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
off_t offset, size_t size,
off_t offset, uint64_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view);
@@ -258,6 +266,18 @@ extern int backtrace_vector_release (struct backtrace_state *state,
backtrace_error_callback error_callback,
void *data);
/* Free the space managed by VEC. This will reset VEC. */
static inline void
backtrace_vector_free (struct backtrace_state *state,
struct backtrace_vector *vec,
backtrace_error_callback error_callback, void *data)
{
vec->alc += vec->size;
vec->size = 0;
backtrace_vector_release (state, vec, error_callback, data);
}
/* Read initial debug data from a descriptor, and set the
fileline_data, syminfo_fn, and syminfo_data fields of STATE.
Return the fileln_fn field in *FILELN_FN--this is done this way so
@@ -275,23 +295,70 @@ extern int backtrace_initialize (struct backtrace_state *state,
void *data,
fileline *fileline_fn);
/* An enum for the DWARF sections we care about. */
enum dwarf_section
{
DEBUG_INFO,
DEBUG_LINE,
DEBUG_ABBREV,
DEBUG_RANGES,
DEBUG_STR,
DEBUG_ADDR,
DEBUG_STR_OFFSETS,
DEBUG_LINE_STR,
DEBUG_RNGLISTS,
DEBUG_MAX
};
/* Data for the DWARF sections we care about. */
struct dwarf_sections
{
const unsigned char *data[DEBUG_MAX];
size_t size[DEBUG_MAX];
};
/* DWARF data read from a file, used for .gnu_debugaltlink. */
struct dwarf_data;
/* Add file/line information for a DWARF module. */
extern int backtrace_dwarf_add (struct backtrace_state *state,
uintptr_t base_address,
const unsigned char* dwarf_info,
size_t dwarf_info_size,
const unsigned char *dwarf_line,
size_t dwarf_line_size,
const unsigned char *dwarf_abbrev,
size_t dwarf_abbrev_size,
const unsigned char *dwarf_ranges,
size_t dwarf_range_size,
const unsigned char *dwarf_str,
size_t dwarf_str_size,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *fileline_altlink,
backtrace_error_callback error_callback,
void *data, fileline *fileline_fn);
void *data, fileline *fileline_fn,
struct dwarf_data **fileline_entry);
/* A data structure to pass to backtrace_syminfo_to_full. */
struct backtrace_call_full
{
backtrace_full_callback full_callback;
backtrace_error_callback full_error_callback;
void *full_data;
int ret;
};
/* A backtrace_syminfo_callback that can call into a
backtrace_full_callback, used when we have a symbol table but no
debug info. */
extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
const char *symname,
uintptr_t symval,
uintptr_t symsize);
/* An error callback that corresponds to
backtrace_syminfo_to_full_callback. */
extern void backtrace_syminfo_to_full_error_callback (void *, const char *,
int);
/* A test-only hook for elf_uncompress_zdebug. */
@@ -302,5 +369,14 @@ extern int backtrace_uncompress_zdebug (struct backtrace_state *,
unsigned char **uncompressed,
size_t *uncompressed_size);
/* A test-only hook for elf_uncompress_lzma. */
extern int backtrace_uncompress_lzma (struct backtrace_state *,
const unsigned char *compressed,
size_t compressed_size,
backtrace_error_callback, void *data,
unsigned char **uncompressed,
size_t *uncompressed_size);
#endif
#endif
+7 -1
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* mmap.c -- Memory allocation with mmap.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,10 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "include/backtrace.h"
#include "internal.h"
#ifndef HAVE_DECL_GETPAGESIZE
extern int getpagesize (void);
#endif
/* Memory allocation on systems that provide anonymous mmap. This
permits the backtrace functions to be invoked from a signal
handler, assuming that mmap is async-signal safe. */
@@ -322,6 +326,8 @@ backtrace_vector_release (struct backtrace_state *state,
backtrace_free (state, (char *) vec->base + aligned, alc,
error_callback, data);
vec->alc = 0;
if (vec->size == 0)
vec->base = NULL;
return 1;
}
#endif
+12 -2
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* mmapio.c -- File views using mmap.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,10 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "include/backtrace.h"
#include "internal.h"
#ifndef HAVE_DECL_GETPAGESIZE
extern int getpagesize (void);
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
#endif
@@ -52,7 +56,7 @@ POSSIBILITY OF SUCH DAMAGE. */
int
backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
int descriptor, off_t offset, size_t size,
int descriptor, off_t offset, uint64_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view)
{
@@ -61,6 +65,12 @@ backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
off_t pageoff;
void *map;
if ((uint64_t) (size_t) size != size)
{
error_callback (data, "file size too large", 0);
return 0;
}
pagesize = getpagesize ();
inpage = offset % pagesize;
pageoff = offset - inpage;
+6 -2
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* posix.c -- POSIX file I/O routines for the backtrace library.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -68,7 +68,11 @@ backtrace_open (const char *filename, backtrace_error_callback error_callback,
descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC));
if (descriptor < 0)
{
if (does_not_exist != NULL && errno == ENOENT)
/* If DOES_NOT_EXIST is not NULL, then don't call ERROR_CALLBACK
if the file does not exist. We treat lacking permission to
open the file as the file not existing; this case arises when
running the libgo syscall package tests as root. */
if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES))
*does_not_exist = 1;
else
error_callback (data, filename, errno);
+2 -2
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* print.c -- Print the current backtrace.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,7 @@ error_callback (void *data, const char *msg, int errnum)
/* Print a backtrace. */
void
void __attribute__((noinline))
backtrace_print (struct backtrace_state *state, int skip, FILE *f)
{
struct print_data data;
+3 -3
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* simple.c -- The backtrace_simple function.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@ struct backtrace_simple_data
int ret;
};
/* Unwind library callback routine. This is passd to
/* Unwind library callback routine. This is passed to
_Unwind_Backtrace. */
static _Unwind_Reason_Code
@@ -91,7 +91,7 @@ simple_unwind (struct _Unwind_Context *context, void *vdata)
/* Get a simple stack backtrace. */
int
int __attribute__((noinline))
backtrace_simple (struct backtrace_state *state, int skip,
backtrace_simple_callback callback,
backtrace_error_callback error_callback, void *data)
+1 -1
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* sort.c -- Sort without allocating memory
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
+1 -1
View File
@@ -1,6 +1,6 @@
#ifdef __linux__
/* state.c -- Create the backtrace state.
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
+44
View File
@@ -0,0 +1,44 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import Backtrace
#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Musl)
import Musl
#endif
#if swift(<5.9) || os(Windows)
Backtrace.install()
#endif
func raiseSignal(_ signal: Int32) {
raise(signal)
}
let reason = CommandLine.arguments.count == 2 ? CommandLine.arguments[1] : "unknown"
switch reason.uppercased() {
case "SIGILL":
raiseSignal(SIGILL)
case "SIGSEGV":
raiseSignal(SIGSEGV)
case "SIGBUS":
raiseSignal(SIGBUS)
case "SIGFPE":
raiseSignal(SIGFPE)
default:
fatalError(reason)
}
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//
// BacktraceTests+XCTest.swift
//
import XCTest
///
/// NOTE: This file was generated by generate_linux_tests.rb
///
/// Do NOT edit this file directly as it will be regenerated automatically when needed.
///
extension BacktraceTests {
public static var allTests: [(String, (BacktraceTests) -> () throws -> Void)] {
return [
("testFatalError", testFatalError),
("testSIGILL", testSIGILL),
("testSIGSEGV", testSIGSEGV),
("testSIGBUS", testSIGBUS),
("testSIGFPE", testSIGFPE),
]
}
}
+106 -11
View File
@@ -1,15 +1,110 @@
import XCTest
@testable import Backtrace
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
final class BacktraceTests: XCTestCase {
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
XCTAssert(true)
import XCTest
public final class BacktraceTests: XCTestCase {
func testFatalError() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
#if swift(>=5.9)
try XCTSkipIf(true, "test is not supported on Swift 5.9")
#endif
let expectedError = UUID().uuidString
let stderr = try runSample(reason: expectedError)
print(stderr)
XCTAssert(stderr.contains("Received signal 4. Backtrace:"))
XCTAssert(stderr.contains("Current stack trace:"), "expected stanard error to include backtrace")
XCTAssert(stderr.contains("Fatal error: \(expectedError)"), "expected stanard error to include error information")
}
static var allTests = [
("testExample", testExample),
]
func testSIGILL() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
#if swift(>=5.9)
try XCTSkipIf(true, "test is not supported on Swift 5.9")
#endif
let stderr = try runSample(reason: "SIGILL")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGILL). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func testSIGSEGV() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
#if swift(>=5.9)
try XCTSkipIf(true, "test is not supported on Swift 5.9")
#endif
let stderr = try runSample(reason: "SIGSEGV")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGSEGV). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func testSIGBUS() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
#if swift(>=5.9)
try XCTSkipIf(true, "test is not supported on Swift 5.9")
#endif
let stderr = try runSample(reason: "SIGBUS")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGBUS). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func testSIGFPE() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
#if swift(>=5.9)
try XCTSkipIf(true, "test is not supported on Swift 5.9")
#endif
let stderr = try runSample(reason: "SIGFPE")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGFPE). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func runSample(reason: String) throws -> String {
let pipe = Pipe()
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/swift")
process.arguments = ["run", "Sample", reason]
process.standardError = pipe
try process.run()
process.waitUntilExit()
return String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
}
}
@@ -1,9 +0,0 @@
import XCTest
#if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(BacktraceTests.allTests),
]
}
#endif
+27 -3
View File
@@ -1,7 +1,31 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//
// LinuxMain.swift
//
import XCTest
///
/// NOTE: This file was generated by generate_linux_tests.rb
///
/// Do NOT edit this file directly as it will be regenerated automatically when needed.
///
#if os(Linux) || os(FreeBSD)
import BacktraceTests
var tests = [XCTestCaseEntry]()
tests += BacktraceTests.allTests()
XCTMain(tests)
XCTMain([
testCase(BacktraceTests.allTests),
])
#endif
+34
View File
@@ -0,0 +1,34 @@
ARG swift_version=5.0
ARG ubuntu_version=bionic
ARG base_image=swift:$swift_version-$ubuntu_version
FROM $base_image
# needed to do again after FROM due to docker limitation
ARG swift_version
ARG ubuntu_version
# set as UTF-8
RUN apt-get update && apt-get install -y locales locales-all
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
# dependencies
RUN apt-get update && apt-get install -y wget
RUN apt-get update && apt-get install -y lsof dnsutils netcat-openbsd net-tools curl jq # used by integration tests
# ruby and jazzy for docs generation
RUN apt-get update && apt-get install -y ruby ruby-dev libsqlite3-dev build-essential
# jazzy no longer works on older version of ubuntu as ruby is too old.
RUN if [ "${ubuntu_version}" = "jammy" ] ; then echo "gem: --no-document" > ~/.gemrc ; fi
RUN if [ "${ubuntu_version}" = "jammy" ] ; then gem install jazzy ; fi
# tools
RUN mkdir -p $HOME/.tools
RUN echo 'export PATH="$HOME/.tools:$PATH"' >> $HOME/.profile
# swiftformat (until part of the toolchain)
ARG swiftformat_version=0.44.6
RUN git clone --branch $swiftformat_version --depth 1 https://github.com/nicklockwood/SwiftFormat $HOME/.tools/swift-format
RUN cd $HOME/.tools/swift-format && swift build -c release
RUN ln -s $HOME/.tools/swift-format/.build/release/swiftformat $HOME/.tools/swiftformat
+18
View File
@@ -0,0 +1,18 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:16.04-5.1
build:
args:
ubuntu_version: "xenial"
swift_version: "5.1"
test:
image: swift-linux-backtrace:16.04-5.1
environment:
- SANITIZER_ARG=--sanitize=thread
shell:
image: swift-linux-backtrace:16.04-5.1
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:18.04-5.0
build:
args:
ubuntu_version: "bionic"
swift_version: "5.0"
test:
image: swift-linux-backtrace:18.04-5.0
shell:
image: swift-linux-backtrace:18.04-5.0
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:18.04-5.2
build:
args:
ubuntu_version: "bionic"
swift_version: "5.2"
test:
image: swift-linux-backtrace:18.04-5.2
shell:
image: swift-linux-backtrace:18.04-5.2
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:18.04-5.3
build:
args:
ubuntu_version: "bionic"
swift_version: "5.3"
test:
image: swift-linux-backtrace:18.04-5.3
shell:
image: swift-linux-backtrace:18.04-5.3
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.4
build:
args:
ubuntu_version: "focal"
swift_version: "5.4"
test:
image: swift-linux-backtrace:20.04-5.4
shell:
image: swift-linux-backtrace:20.04-5.4
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.5
build:
args:
ubuntu_version: "focal"
swift_version: "5.5"
test:
image: swift-linux-backtrace:20.04-5.5
shell:
image: swift-linux-backtrace:20.04-5.5
+18
View File
@@ -0,0 +1,18 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.6
build:
args:
ubuntu_version: "focal"
swift_version: "5.6"
test:
image: swift-linux-backtrace:20.04-5.6
environment:
- FORCE_TEST_DISCOVERY=--enable-test-discovery
shell:
image: swift-linux-backtrace:20.04-5.6
+18
View File
@@ -0,0 +1,18 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.7
build:
args:
ubuntu_version: "focal"
swift_version: "5.7"
test:
image: swift-linux-backtrace:20.04-5.7
environment:
- FORCE_TEST_DISCOVERY=--enable-test-discovery
shell:
image: swift-linux-backtrace:20.04-5.7
+17
View File
@@ -0,0 +1,17 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:22.04-5.10
build:
args:
base_image: "swiftlang/swift:nightly-5.10-jammy"
test:
image: swift-linux-backtrace:22.04-5.10
environment:
- FORCE_TEST_DISCOVERY=--enable-test-discovery
shell:
image: swift-linux-backtrace:22.04-5.10
+18
View File
@@ -0,0 +1,18 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:22.04-5.8
build:
args:
ubuntu_version: "jammy"
swift_version: "5.8"
test:
image: swift-linux-backtrace:22.04-5.8
environment:
- FORCE_TEST_DISCOVERY=--enable-test-discovery
shell:
image: swift-linux-backtrace:22.04-5.8
+18
View File
@@ -0,0 +1,18 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:22.04-5.9
build:
args:
ubuntu_version: "jammy"
swift_version: "5.9"
test:
image: swift-linux-backtrace:22.04-5.9
environment:
- FORCE_TEST_DISCOVERY=--enable-test-discovery
shell:
image: swift-linux-backtrace:22.04-5.9
+17
View File
@@ -0,0 +1,17 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:22.04-main
build:
args:
base_image: "swiftlang/swift:nightly-main-jammy"
test:
image: swift-linux-backtrace:22.04-main
environment:
- FORCE_TEST_DISCOVERY=--enable-test-discovery
shell:
image: swift-linux-backtrace:22.04-main
+37
View File
@@ -0,0 +1,37 @@
# this file is not designed to be run directly
# instead, use the docker-compose.<os>.<swift> files
# eg docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.1804.50.yaml run test
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:default
build:
context: .
dockerfile: Dockerfile
common: &common
image: swift-linux-backtrace:default
depends_on: [runtime-setup]
volumes:
- ~/.ssh:/root/.ssh
- ..:/code:z
working_dir: /code
cap_drop:
- CAP_NET_RAW
- CAP_NET_BIND_SERVICE
soundness:
<<: *common
command: /bin/bash -cl "./scripts/soundness.sh"
test:
<<: *common
command: /bin/bash -cl "swift test -c release -Xswiftc -g -Xswiftc -warnings-as-errors $${FORCE_TEST_DISCOVERY-} $${SANITIZER_ARG-}"
# util
shell:
<<: *common
entrypoint: /bin/bash -l
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftLinuxBacktrace open source project
##
## Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
set -eu
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
contributors=$( cd "$here"/.. && git shortlog -es | cut -f2 | sed 's/^/- /' )
cat > "$here/../CONTRIBUTORS.txt" <<- EOF
For the purpose of tracking copyright, this is the list of individuals and
organizations who have contributed source code to SwiftLinuxBacktrace.
For employees of an organization/company where the copyright of work done
by employees of that company is held by the company itself, only the company
needs to be listed here.
## COPYRIGHT HOLDERS
- Apple Inc. (all contributors with '@apple.com')
### Contributors
$contributors
**Updating this list**
Please do not edit this file manually. It is generated using \`./scripts/generate_contributors_list.sh\`. If a name is misspelled or appearing multiple times: add an entry in \`./.mailmap\`
EOF
+231
View File
@@ -0,0 +1,231 @@
#!/usr/bin/env ruby
#
# process_test_files.rb
#
# Copyright 2016 Tony Stone
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Created by Tony Stone on 5/4/16.
#
require 'getoptlong'
require 'fileutils'
require 'pathname'
include FileUtils
#
# This ruby script will auto generate LinuxMain.swift and the +XCTest.swift extension files for Swift Package Manager on Linux platforms.
#
# See https://github.com/apple/swift-corelibs-xctest/blob/master/Documentation/Linux.md
#
def header(fileName)
string = <<-eos
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//
// <FileName>
//
import XCTest
///
/// NOTE: This file was generated by generate_linux_tests.rb
///
/// Do NOT edit this file directly as it will be regenerated automatically when needed.
///
eos
string
.sub('<FileName>', File.basename(fileName))
.sub('<Date>', Time.now.to_s)
end
def createExtensionFile(fileName, classes)
extensionFile = fileName.sub! '.swift', '+XCTest.swift'
print 'Creating file: ' + extensionFile + "\n"
File.open(extensionFile, 'w') do |file|
file.write header(extensionFile)
file.write "\n"
for classArray in classes
file.write 'extension ' + classArray[0] + " {\n"
file.write ' public static var allTests: [(String, (' + classArray[0] + ") -> () throws -> Void)] {\n"
file.write " return [\n"
for funcName in classArray[1]
file.write ' ("' + funcName + '", ' + funcName + "),\n"
end
file.write " ]\n"
file.write " }\n"
file.write "}\n"
end
end
end
def createLinuxMain(testsDirectory, allTestSubDirectories, files)
fileName = testsDirectory + '/LinuxMain.swift'
print 'Creating file: ' + fileName + "\n"
File.open(fileName, 'w') do |file|
file.write header(fileName)
file.write "\n"
file.write "#if os(Linux) || os(FreeBSD)\n"
for testSubDirectory in allTestSubDirectories.sort { |x, y| x <=> y }
file.write 'import ' + testSubDirectory + "\n"
end
file.write "\n"
file.write "XCTMain([\n"
testCases = []
for classes in files
for classArray in classes
testCases << classArray[0]
end
end
for testCase in testCases.sort { |x, y| x <=> y }
file.write ' testCase(' + testCase + ".allTests),\n"
end
file.write "])\n"
file.write "#endif\n"
end
end
def parseSourceFile(fileName)
puts 'Parsing file: ' + fileName + "\n"
classes = []
currentClass = nil
inIfLinux = false
inElse = false
ignore = false
#
# Read the file line by line
# and parse to find the class
# names and func names
#
File.readlines(fileName).each do |line|
if inIfLinux
if /\#else/.match(line)
inElse = true
ignore = true
else
if /\#end/.match(line)
inElse = false
inIfLinux = false
ignore = false
end
end
else
if /\#if[ \t]+os\(Linux\)/.match(line)
inIfLinux = true
ignore = false
end
end
next if ignore
# Match class or func
match = line[/class[ \t]+[a-zA-Z0-9_]*(?=[ \t]*:[ \t]*XCTestCase)|func[ \t]+test[a-zA-Z0-9_]*(?=[ \t]*\(\))/, 0]
if match
if match[/class/, 0] == 'class'
className = match.sub(/^class[ \t]+/, '')
#
# Create a new class / func structure
# and add it to the classes array.
#
currentClass = [className, []]
classes << currentClass
else # Must be a func
funcName = match.sub(/^func[ \t]+/, '')
#
# Add each func name the the class / func
# structure created above.
#
currentClass[1] << funcName
end
end
end
classes
end
#
# Main routine
#
#
testsDirectory = 'Tests'
options = GetoptLong.new(['--tests-dir', GetoptLong::OPTIONAL_ARGUMENT])
options.quiet = true
begin
options.each do |option, value|
case option
when '--tests-dir'
testsDirectory = value
end
end
rescue GetoptLong::InvalidOption
end
allTestSubDirectories = []
allFiles = []
Dir[testsDirectory + '/*'].each do |subDirectory|
next unless File.directory?(subDirectory)
directoryHasClasses = false
Dir[subDirectory + '/*Test{s,}.swift'].each do |fileName|
next unless File.file? fileName
fileClasses = parseSourceFile(fileName)
#
# If there are classes in the
# test source file, create an extension
# file for it.
#
next unless fileClasses.count > 0
createExtensionFile(fileName, fileClasses)
directoryHasClasses = true
allFiles << fileClasses
end
if directoryHasClasses
allTestSubDirectories << Pathname.new(subDirectory).split.last.to_s
end
end
#
# Last step is the create a LinuxMain.swift file that
# references all the classes and funcs in the source files.
#
if allFiles.count > 0
createLinuxMain(testsDirectory, allTestSubDirectories, allFiles)
end
# eof
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftLinuxBacktrace open source project
##
## Copyright (c) 2022 Apple Inc. and the SwiftLinuxBacktrace project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
##===----------------------------------------------------------------------===##
##
## This source file is part of the Swift Distributed Actors open source project
##
## Copyright (c) 2018-2019 Apple Inc. and the Swift Distributed Actors project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.md for the list of Swift Distributed Actors project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
swift package --disable-sandbox preview-documentation --target $1
+140
View File
@@ -0,0 +1,140 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftLinuxBacktrace open source project
##
## Copyright (c) 2017-2022 Apple Inc. and the SwiftLinuxBacktrace project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
set -eu
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
function replace_acceptable_years() {
# this needs to replace all acceptable forms with 'YEARS'
sed -e 's/20[12][78901]-20[12][89012]/YEARS/' -e 's/2019/YEARS/' -e 's/202[012]/YEARS/'
}
printf "=> Checking linux tests... "
FIRST_OUT="$(git status --porcelain)"
ruby "$here/../scripts/generate_linux_tests.rb" > /dev/null
SECOND_OUT="$(git status --porcelain)"
if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then
printf "\033[0;31mmissing changes!\033[0m\n"
git --no-pager diff
exit 1
else
printf "\033[0;32mokay.\033[0m\n"
fi
printf "=> Checking format... "
FIRST_OUT="$(git status --porcelain)"
swiftformat . > /dev/null 2>&1
SECOND_OUT="$(git status --porcelain)"
if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then
printf "\033[0;31mformatting issues!\033[0m\n"
git --no-pager diff
exit 1
else
printf "\033[0;32mokay.\033[0m\n"
fi
printf "=> Checking license headers\n"
tmp=$(mktemp /tmp/.swift-aws-lambda-sanity_XXXXXX)
for language in swift-or-c bash dtrace; do
printf " * $language... "
declare -a matching_files
declare -a exceptions
expections=( )
matching_files=( -name '*' )
case "$language" in
swift-or-c)
exceptions=( -name Package.swift -o -name 'Package@*.swift' -o -path './Sources/CBacktrace/*' )
matching_files=( -name '*.swift' -o -name '*.c' -o -name '*.h' )
cat > "$tmp" <<"EOF"
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLinuxBacktrace open source project
//
// Copyright (c) YEARS Apple Inc. and the SwiftLinuxBacktrace project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
EOF
;;
bash)
matching_files=( -name '*.sh' )
cat > "$tmp" <<"EOF"
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftLinuxBacktrace open source project
##
## Copyright (c) YEARS Apple Inc. and the SwiftLinuxBacktrace project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
EOF
;;
dtrace)
matching_files=( -name '*.d' )
cat > "$tmp" <<"EOF"
#!/usr/sbin/dtrace -q -s
/*===----------------------------------------------------------------------===*
*
* This source file is part of the SwiftLinuxBacktrace open source project
*
* Copyright (c) YEARS Apple Inc. and the SwiftLinuxBacktrace project authors
* Licensed under Apache License v2.0
*
* See LICENSE.txt for license information
* See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
*
* SPDX-License-Identifier: Apache-2.0
*
*===----------------------------------------------------------------------===*/
EOF
;;
*)
echo >&2 "ERROR: unknown language '$language'"
;;
esac
expected_lines=$(cat "$tmp" | wc -l)
expected_sha=$(cat "$tmp" | shasum)
(
cd "$here/.."
find . \
\( \! -path './.build/*' -a \
\( "${matching_files[@]}" \) -a \
\( \! \( "${exceptions[@]}" \) \) \) | while read line; do
if [[ "$(cat "$line" | replace_acceptable_years | head -n $expected_lines | shasum)" != "$expected_sha" ]]; then
printf "\033[0;31mmissing headers in file '$line'!\033[0m\n"
diff -u <(cat "$line" | replace_acceptable_years | head -n $expected_lines) "$tmp"
exit 1
fi
done
printf "\033[0;32mokay.\033[0m\n"
)
done
rm "$tmp"
+19 -1
View File
@@ -1,3 +1,18 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftLinuxBacktrace open source project
##
## Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
#!/bin/bash
# This script creates a vendored copy of libbacktrace that is
@@ -48,12 +63,15 @@ done
EXCLUDES=(
'*test*'
'alloc.c'
'nounwind.c'
'pecoff.c'
'read.c'
'unknown.c'
'xcoff.c'
'macho.c'
'alloc.c'
'allocfail.c'
'instrumented_alloc.c'
)
for exclude in "${EXCLUDES[@]}"