├── .gitignore ├── .mailmap ├── .spi.yml ├── .swiftformat ├── CONTRIBUTORS.txt ├── LICENSE.txt ├── NOTICE.txt ├── Package.swift ├── Package@swift-5.0.swift ├── Package@swift-5.1.swift ├── Package@swift-5.2.swift ├── Package@swift-5.3.swift ├── Package@swift-5.4.swift ├── Package@swift-5.5.swift ├── README.md ├── SECURITY.md ├── Sources ├── Backtrace │ ├── Backtrace.swift │ ├── Demangle.swift │ └── Docs.docc │ │ └── index.md ├── CBacktrace │ ├── LICENSE │ ├── atomic.c │ ├── backtrace-supported.h │ ├── backtrace.c │ ├── config.h │ ├── dwarf.c │ ├── elf.c │ ├── fileline.c │ ├── filenames.h │ ├── include │ │ └── backtrace.h │ ├── internal.h │ ├── mmap.c │ ├── mmapio.c │ ├── posix.c │ ├── print.c │ ├── simple.c │ ├── sort.c │ └── state.c └── Sample │ └── main.swift ├── Tests ├── BacktraceTests │ ├── BacktraceTests+XCTest.swift │ └── BacktraceTests.swift └── LinuxMain.swift ├── docker ├── Dockerfile ├── docker-compose.1604.51.yaml ├── docker-compose.1804.50.yaml ├── docker-compose.1804.52.yaml ├── docker-compose.1804.53.yaml ├── docker-compose.2004.54.yaml ├── docker-compose.2004.55.yaml ├── docker-compose.2004.56.yaml ├── docker-compose.2004.57.yaml ├── docker-compose.2204.510.yaml ├── docker-compose.2204.58.yaml ├── docker-compose.2204.59.yaml ├── docker-compose.2204.main.yaml └── docker-compose.yaml └── scripts ├── generate_contributors_list.sh ├── generate_linux_tests.rb ├── preview_docc.sh ├── soundness.sh └── vendor-libbacktrace.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | .swiftpm 6 | .*.sw[nop] 7 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Tomer Doron 2 | Tomer Doron 3 | Tomer Doron 4 | -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - documentation_targets: [Backtrace] 5 | -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | # file options 2 | 3 | --swiftversion 5.0 4 | --exclude .build 5 | 6 | # format options 7 | 8 | --self insert 9 | --patternlet inline 10 | --stripunusedargs unnamed-only 11 | --ifdef no-indent 12 | 13 | # rules 14 | -------------------------------------------------------------------------------- /CONTRIBUTORS.txt: -------------------------------------------------------------------------------- 1 | For the purpose of tracking copyright, this is the list of individuals and 2 | organizations who have contributed source code to SwiftLinuxBacktrace. 3 | 4 | For employees of an organization/company where the copyright of work done 5 | by employees of that company is held by the company itself, only the company 6 | needs to be listed here. 7 | 8 | ## COPYRIGHT HOLDERS 9 | 10 | - Apple Inc. (all contributors with '@apple.com') 11 | 12 | ### Contributors 13 | 14 | - Ian Partridge 15 | - Tanner 16 | - Tomer Doron 17 | - Zsolt Váradi 18 | 19 | **Updating this list** 20 | 21 | 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` 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | This product contains a derivation of "libbacktrace" from Ian Lance Taylor. 2 | 3 | * LICENSE (BSD-3-Clause): 4 | * https://github.com/ianlancetaylor/libbacktrace/blob/master/LICENSE 5 | * HOMEPAGE: 6 | * https://github.com/ianlancetaylor/libbacktrace 7 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.6 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [ 14 | .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), 15 | ], 16 | targets: [ 17 | .target(name: "Backtrace", 18 | dependencies: ["CBacktrace"]), 19 | .target(name: "CBacktrace", 20 | dependencies: []), 21 | .executableTarget(name: "Sample", 22 | dependencies: ["Backtrace"]), 23 | .testTarget(name: "BacktraceTests", 24 | dependencies: ["Backtrace"]), 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /Package@swift-5.0.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [], 14 | targets: [ 15 | .target(name: "Backtrace", 16 | dependencies: ["CBacktrace"]), 17 | .target(name: "CBacktrace", 18 | dependencies: []), 19 | .target(name: "Sample", 20 | dependencies: ["Backtrace"]), 21 | .testTarget(name: "BacktraceTests", 22 | dependencies: ["Backtrace"]), 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /Package@swift-5.1.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [], 14 | targets: [ 15 | .target(name: "Backtrace", 16 | dependencies: ["CBacktrace"]), 17 | .target(name: "CBacktrace", 18 | dependencies: []), 19 | .target(name: "Sample", 20 | dependencies: ["Backtrace"]), 21 | .testTarget(name: "BacktraceTests", 22 | dependencies: ["Backtrace"]), 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /Package@swift-5.2.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [], 14 | targets: [ 15 | .target(name: "Backtrace", 16 | dependencies: ["CBacktrace"]), 17 | .target(name: "CBacktrace", 18 | dependencies: []), 19 | .target(name: "Sample", 20 | dependencies: ["Backtrace"]), 21 | .testTarget(name: "BacktraceTests", 22 | dependencies: ["Backtrace"]), 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /Package@swift-5.3.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [], 14 | targets: [ 15 | .target(name: "Backtrace", 16 | dependencies: ["CBacktrace"]), 17 | .target(name: "CBacktrace", 18 | dependencies: []), 19 | .target(name: "Sample", 20 | dependencies: ["Backtrace"]), 21 | .testTarget(name: "BacktraceTests", 22 | dependencies: ["Backtrace"]), 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /Package@swift-5.4.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [], 14 | targets: [ 15 | .target(name: "Backtrace", 16 | dependencies: ["CBacktrace"]), 17 | .target(name: "CBacktrace", 18 | dependencies: []), 19 | .target(name: "Sample", 20 | dependencies: ["Backtrace"]), 21 | .testTarget(name: "BacktraceTests", 22 | dependencies: ["Backtrace"]), 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /Package@swift-5.5.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-backtrace", 7 | products: [ 8 | .library( 9 | name: "Backtrace", 10 | targets: ["Backtrace"] 11 | ), 12 | ], 13 | dependencies: [], 14 | targets: [ 15 | .target(name: "Backtrace", 16 | dependencies: ["CBacktrace"]), 17 | .target(name: "CBacktrace", 18 | dependencies: []), 19 | .target(name: "Sample", 20 | dependencies: ["Backtrace"]), 21 | .testTarget(name: "BacktraceTests", 22 | dependencies: ["Backtrace"]), 23 | ] 24 | ) 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!IMPORTANT] 2 | > This library is now archived as backtracing is built into Swift 5.9+ 3 | 4 | # Backtrace 5 | 6 | This Swift package provides support for automatically printing crash backtraces of Swift programs. 7 | 8 | The library is designed to fill a gap in backtraces support for Swift on non-Darwin platforms. 9 | When this gap is closed at the language runtime level, this library will become redundant and be deprecated. 10 | 11 | ## Usage 12 | 13 | **Note**: You do not need this library on Linux as of Swift 5.9, which has 14 | built-in backtracing support. 15 | 16 | Add `https://github.com/swift-server/swift-backtrace.git` as a dependency in your `Package.swift`. 17 | 18 | ### Crash backtraces 19 | 20 | In your `main.swift`, do: 21 | 22 | ```swift 23 | import Backtrace 24 | 25 | // Do this first 26 | Backtrace.install() 27 | ``` 28 | 29 | 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. 30 | 31 | ``` 32 | $ swift build -c release -Xswiftc -g 33 | ``` 34 | 35 | When your app crashes, a stacktrace will be printed to `stderr`. 36 | 37 | ## Security 38 | 39 | Please see [SECURITY.md](SECURITY.md) for details on the security process. 40 | 41 | ## Acknowledgements 42 | 43 | Ian Partridge ([GitHub](https://github.com/ianpartridge/), [Twitter](https://twitter.com/alfa)) the original author of this package. 44 | 45 | Johannes Weiss ([GitHub](https://github.com/weissi), [Twitter](https://twitter.com/johannesweiss)) for the signal handling code. 46 | 47 | Saleem Abdulrasool ([GitHub](https://github.com/compnerd), [Twitter](https://twitter.com/compnerd)) for the Windows port. 48 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | This document specifies the security process for the Backtrace project. 4 | 5 | ## Disclosures 6 | 7 | ### Private Disclosure Process 8 | 9 | The Backtrace maintainers ask that known and suspected vulnerabilities be 10 | privately and responsibly disclosed by emailing 11 | [sswg-security-reports@forums.swift.org](mailto:sswg-security-reports@forums.swift.org) 12 | with the all the required detail. 13 | **Do not file a public issue.** 14 | 15 | #### When to report a vulnerability 16 | 17 | * You think you have discovered a potential security vulnerability in Backtrace. 18 | * You are unsure how a vulnerability affects Backtrace. 19 | 20 | #### What happens next? 21 | 22 | * A member of the team will acknowledge receipt of the report within 3 23 | working days (United States). This may include a request for additional 24 | information about reproducing the vulnerability. 25 | * We will privately inform the Swift Server Work Group ([SSWG][sswg]) of the 26 | vulnerability within 10 days of the report as per their [security 27 | guidelines][sswg-security]. 28 | * Once we have identified a fix we may ask you to validate it. We aim to do this 29 | within 30 days. In some cases this may not be possible, for example when the 30 | vulnerability exists at the protocol level and the industry must coordinate on 31 | the disclosure process. 32 | * If a CVE number is required, one will be requested from [MITRE][mitre] 33 | providing you with full credit for the discovery. 34 | * We will decide on a planned release date and let you know when it is. 35 | * Prior to release, we will inform major dependents that a security-related 36 | patch is impending. 37 | * Once the fix has been released we will publish a security advisory on GitHub 38 | and in the Server → Security Updates category on the [Swift forums][swift-forums-sec]. 39 | 40 | [sswg]: https://github.com/swift-server/sswg 41 | [sswg-security]: https://github.com/swift-server/sswg/blob/main/security/README.md 42 | [swift-forums-sec]: https://forums.swift.org/c/server/security-updates/ 43 | [mitre]: https://cveform.mitre.org/ 44 | -------------------------------------------------------------------------------- /Sources/Backtrace/Backtrace.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the SwiftLinuxBacktrace open source project 4 | // 5 | // Copyright (c) 2019-2022 Apple Inc. and the SwiftLinuxBacktrace project authors 6 | // Licensed under Apache License v2.0 7 | // 8 | // See LICENSE.txt for license information 9 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 10 | // 11 | // SPDX-License-Identifier: Apache-2.0 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | // Swift 5.9 has its own built-in backtracing support in the runtime; 16 | // we don't want to activate this library if we're using 5.9 or above. 17 | #if swift(>=5.9) && !os(Windows) 18 | public enum Backtrace { 19 | @available(*, deprecated, message: "This is no longer needed in Swift 5.9") 20 | public static func install() {} 21 | 22 | @available(*, deprecated, message: "This is no longer needed in Swift 5.9") 23 | public static func install(signals: [CInt]) {} 24 | 25 | @available(*, deprecated, message: "This method will be removed in the next major version.") 26 | public static func print() {} 27 | } 28 | 29 | #elseif os(Linux) 30 | import CBacktrace 31 | import Glibc 32 | 33 | typealias CBacktraceErrorCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ msg: UnsafePointer?, _ errnum: CInt) -> Void 34 | typealias CBacktraceFullCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ pc: UInt, _ filename: UnsafePointer?, _ lineno: CInt, _ function: UnsafePointer?) -> CInt 35 | typealias CBacktraceSimpleCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ pc: UInt) -> CInt 36 | typealias CBacktraceSyminfoCallback = @convention(c) (_ data: UnsafeMutableRawPointer?, _ pc: UInt, _ filename: UnsafePointer?, _ symval: UInt, _ symsize: UInt) -> Void 37 | 38 | private let state = backtrace_create_state(nil, /* BACKTRACE_SUPPORTS_THREADS */ 1, nil, nil) 39 | 40 | private let fullCallback: CBacktraceFullCallback? = { 41 | _, pc, filename, lineno, function in 42 | 43 | var str = "0x" 44 | str.append(String(pc, radix: 16)) 45 | if let function = function { 46 | str.append(", ") 47 | var fn = String(cString: function) 48 | if fn.hasPrefix("$s") || fn.hasPrefix("$S") { 49 | fn = _stdlib_demangleName(fn) 50 | } 51 | str.append(fn) 52 | } 53 | if let filename = filename { 54 | str.append(" at ") 55 | str.append(String(cString: filename)) 56 | str.append(":") 57 | str.append(String(lineno)) 58 | } 59 | str.append("\n") 60 | 61 | str.withCString { ptr in 62 | _ = withVaList([ptr]) { vaList in 63 | vfprintf(stderr, "%s", vaList) 64 | } 65 | } 66 | return 0 67 | } 68 | 69 | private let errorCallback: CBacktraceErrorCallback? = { 70 | _, msg, errNo in 71 | if let msg = msg { 72 | _ = withVaList([msg, errNo]) { vaList in 73 | vfprintf(stderr, "SwiftBacktrace ERROR: %s (errno: %d)\n", vaList) 74 | } 75 | } 76 | } 77 | 78 | private func printBacktrace(signal: CInt) { 79 | _ = fputs("Received signal \(signal). Backtrace:\n", stderr) 80 | backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil) 81 | fflush(stderr) 82 | } 83 | 84 | public enum Backtrace { 85 | /// Install the backtrace handler on default signals: `SIGILL`, `SIGSEGV`, `SIGBUS`, `SIGFPE`. 86 | public static func install() { 87 | Backtrace.install(signals: [SIGILL, SIGSEGV, SIGBUS, SIGFPE]) 88 | } 89 | 90 | /// Install the backtrace handler when any of `signals` happen. 91 | public static func install(signals: [CInt]) { 92 | for signal in signals { 93 | self.setupHandler(signal: signal) { signal in 94 | printBacktrace(signal: signal) 95 | raise(signal) 96 | } 97 | } 98 | } 99 | 100 | @available(*, deprecated, message: "This method will be removed in the next major version.") 101 | public static func print() { 102 | backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil) 103 | } 104 | 105 | private static func setupHandler(signal: Int32, handler: @escaping @convention(c) (CInt) -> Void) { 106 | typealias sigaction_t = sigaction 107 | let sa_flags = CInt(SA_NODEFER) | CInt(bitPattern: CUnsignedInt(SA_RESETHAND)) 108 | var sa = sigaction_t(__sigaction_handler: unsafeBitCast(handler, to: sigaction.__Unnamed_union___sigaction_handler.self), 109 | sa_mask: sigset_t(), 110 | sa_flags: sa_flags, 111 | sa_restorer: nil) 112 | withUnsafePointer(to: &sa) { ptr -> Void in 113 | sigaction(signal, ptr, nil) 114 | } 115 | } 116 | } 117 | 118 | #elseif os(Windows) 119 | #if swift(<5.4) 120 | #error("unsupported Swift version") 121 | #else 122 | @_implementationOnly import CRT 123 | @_implementationOnly import WinSDK 124 | #endif 125 | 126 | public enum Backtrace { 127 | private static var MachineType: DWORD { 128 | #if arch(arm) 129 | DWORD(IMAGE_FILE_MACHINE_ARMNT) 130 | #elseif arch(arm64) 131 | DWORD(IMAGE_FILE_MACHINE_ARM64) 132 | #elseif arch(i386) 133 | DWORD(IMAGE_FILE_MACHINE_I386) 134 | #elseif arch(x86_64) 135 | DWORD(IMAGE_FILE_MACHINE_AMD64) 136 | #else 137 | #error("unsupported architecture") 138 | #endif 139 | } 140 | 141 | /// Signal selection unavailable on Windows. Use ``install()-484jy``. 142 | @available(*, deprecated, message: "signal selection unavailable on Windows") 143 | public static func install(signals: [CInt]) { 144 | Backtrace.install() 145 | } 146 | 147 | /// Install the backtrace handler on default signals. 148 | public static func install() { 149 | // Install a last-chance vectored exception handler to capture the error 150 | // before the termination and report the stack trace. It is unlikely 151 | // that this will be recovered at this point by a SEH handler. 152 | _ = AddVectoredExceptionHandler(0) { _ in 153 | // NOTE: GetCurrentProcess does not increment the reference count on 154 | // the process. This handle should _not_ be closed upon completion. 155 | let hProcess: HANDLE = GetCurrentProcess() 156 | 157 | var cxr: CONTEXT = CONTEXT() 158 | cxr.ContextFlags = 159 | DWORD(CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) 160 | RtlCaptureContext(&cxr) 161 | 162 | _ = SymInitializeW(hProcess, nil, true) 163 | _ = SymSetOptions(DWORD(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME)) 164 | 165 | var Frame: STACKFRAME64 = STACKFRAME64() 166 | #if arch(arm) 167 | Frame.AddrPC.Offset = cxr.Pc 168 | Frame.AddrFrame.Offset = cxr.R11 169 | Frame.AddrStack.Offset = cxr.Sp 170 | #elseif arch(arm64) 171 | Frame.AddrPC.Offset = cxr.Pc 172 | Frame.AddrFrame.Offset = cxr.Fp 173 | Frame.AddrStack.Offset = cxr.Sp 174 | #elseif arch(i386) 175 | Frame.AddrPC.Offset = cxr.Eip 176 | Frame.AddrFrame.Offset = cxr.Ebp 177 | Frame.AddrStack.Offset = cxr.Esp 178 | #elseif arch(x86_64) 179 | Frame.AddrPC.Offset = cxr.Rip 180 | Frame.AddrFrame.Offset = cxr.Rbp 181 | Frame.AddrStack.Offset = cxr.Rsp 182 | #else 183 | #error("unsupported architecture") 184 | #endif 185 | Frame.AddrPC.Mode = AddrModeFlat 186 | Frame.AddrFrame.Mode = AddrModeFlat 187 | Frame.AddrStack.Mode = AddrModeFlat 188 | 189 | // Constant indicating the maximum symbol length that we expect 190 | // during symbolication of the stack trace. 191 | let kMaxSymbolLength: Int = 255 192 | 193 | // Heap allocate the buffer as we need to account for the trailing 194 | // storage that we need to provide. 195 | let pSymbolBuffer: UnsafeMutableRawPointer = 196 | UnsafeMutableRawPointer.allocate(byteCount: MemoryLayout.size + kMaxSymbolLength, 197 | alignment: 1) 198 | defer { pSymbolBuffer.deallocate() } 199 | 200 | let pSymbol: UnsafeMutablePointer = 201 | pSymbolBuffer.bindMemory(to: IMAGEHLP_SYMBOL64.self, 202 | capacity: 1) 203 | 204 | let hThread: HANDLE = GetCurrentThread() 205 | while StackWalk64(Backtrace.MachineType, hProcess, hThread, 206 | &Frame, &cxr, nil, SymFunctionTableAccess64, 207 | SymGetModuleBase64, nil) { 208 | var qwModuleBase: DWORD64 = 209 | SymGetModuleBase64(hProcess, Frame.AddrPC.Offset) 210 | 211 | let module: String = withUnsafeMutablePointer(to: &qwModuleBase) { 212 | $0.withMemoryRebound(to: HINSTANCE.self, capacity: 1) { hInstance in 213 | String(decoding: [WCHAR](unsafeUninitializedCapacity: Int(MAX_PATH + 1)) { 214 | $1 = Int(GetModuleFileNameW(hInstance.pointee, 215 | $0.baseAddress, 216 | DWORD($0.count))) 217 | }, as: UTF16.self) 218 | } 219 | } 220 | 221 | pSymbol.pointee.SizeOfStruct = 222 | DWORD(MemoryLayout.size) 223 | pSymbol.pointee.MaxNameLength = DWORD(kMaxSymbolLength) 224 | _ = SymGetSymFromAddr64(hProcess, Frame.AddrPC.Offset, nil, 225 | pSymbol) 226 | 227 | var symbol: String = 228 | withUnsafePointer(to: &pSymbol.pointee.Name) { 229 | String(cString: $0) 230 | } 231 | 232 | // Undecorate Swift 3+ names only. Earlier Swift decorations 233 | // are unsupported. Any MSVC name decoration has been 234 | // unperformed during the DbgHelp operation through the use of 235 | // the `SYMOPT_UNDNAME` option. 236 | if symbol.hasPrefix("$s") || symbol.hasPrefix("$S") { 237 | symbol = _stdlib_demangleName(symbol) 238 | } 239 | 240 | var Displacement: DWORD = 0 241 | var Line: IMAGEHLP_LINE64 = IMAGEHLP_LINE64() 242 | Line.SizeOfStruct = DWORD(MemoryLayout.size) 243 | _ = SymGetLineFromAddr64(hProcess, Frame.AddrPC.Offset, 244 | &Displacement, &Line) 245 | 246 | var details: String = "" 247 | 248 | if !symbol.isEmpty { 249 | // Truncate the module path to the filename. The 250 | // `PathFindFileNameW` call will return the beginning of the 251 | // string if a path separator character is not found. 252 | if let pszModule = module.withCString(encodedAs: UTF16.self, 253 | PathFindFileNameW) { 254 | details.append(", \(String(decodingCString: pszModule, as: UTF16.self))!\(symbol)") 255 | } 256 | } 257 | 258 | if let szFileName = Line.FileName { 259 | details.append(" at \(String(cString: szFileName)):\(Line.LineNumber)") 260 | } 261 | 262 | _ = details.withCString { pszDetails in 263 | withVaList([Frame.AddrPC.Offset, pszDetails]) { 264 | #if arch(arm64) || arch(x86_64) 265 | vfprintf(stderr, "%#016x%s\n", $0) 266 | #else 267 | vfprintf(stderr, "%#08x%s\n", $0) 268 | #endif 269 | } 270 | } 271 | } 272 | 273 | _ = SymCleanup(hProcess) 274 | 275 | // We have not handled the exception, continue the search. 276 | return EXCEPTION_CONTINUE_SEARCH 277 | } 278 | } 279 | } 280 | 281 | #else 282 | public enum Backtrace { 283 | /// Install the backtrace handler on default signals. Available on Windows and Linux only. 284 | public static func install() {} 285 | 286 | /// Install the backtrace handler on specific signals. Available on Linux only. 287 | public static func install(signals: [CInt]) {} 288 | 289 | @available(*, deprecated, message: "This method will be removed in the next major version.") 290 | public static func print() {} 291 | } 292 | #endif 293 | -------------------------------------------------------------------------------- /Sources/Backtrace/Demangle.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the SwiftLinuxBacktrace open source project 4 | // 5 | // Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 6 | // Licensed under Apache License v2.0 7 | // 8 | // See LICENSE.txt for license information 9 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 10 | // 11 | // SPDX-License-Identifier: Apache-2.0 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | // Swift 5.9 has its own built-in backtracing support in the runtime; 16 | // we don't want to activate this library if we're using 5.9 or above. 17 | #if !(swift(>=5.9) && !os(Windows)) 18 | 19 | #if os(Linux) 20 | import Glibc 21 | #elseif os(Windows) 22 | #if swift(<5.4) 23 | #error("unsupported Swift version") 24 | #else 25 | @_implementationOnly 26 | import ucrt 27 | #endif 28 | #endif 29 | 30 | #if os(Linux) || os(Windows) 31 | @_silgen_name("swift_demangle") 32 | public 33 | func _stdlib_demangleImpl( 34 | mangledName: UnsafePointer?, 35 | mangledNameLength: UInt, 36 | outputBuffer: UnsafeMutablePointer?, 37 | outputBufferSize: UnsafeMutablePointer?, 38 | flags: UInt32 39 | ) -> UnsafeMutablePointer? 40 | 41 | internal func _stdlib_demangleName(_ mangledName: String) -> String { 42 | return mangledName.utf8CString.withUnsafeBufferPointer { 43 | mangledNameUTF8CStr in 44 | 45 | let demangledNamePtr = _stdlib_demangleImpl( 46 | mangledName: mangledNameUTF8CStr.baseAddress, 47 | mangledNameLength: UInt(mangledNameUTF8CStr.count - 1), 48 | outputBuffer: nil, 49 | outputBufferSize: nil, 50 | flags: 0 51 | ) 52 | 53 | if let demangledNamePtr = demangledNamePtr { 54 | let demangledName = String(cString: demangledNamePtr) 55 | free(demangledNamePtr) 56 | return demangledName 57 | } 58 | return mangledName 59 | } 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Sources/Backtrace/Docs.docc/index.md: -------------------------------------------------------------------------------- 1 | # ``Backtrace`` 2 | 3 | Provides support for automatically printing crash backtraces of Swift programs. 4 | 5 | ## Overview 6 | 7 | The Backtrace library is designed to fill a gap in backtraces support for Swift on non-Darwin platforms. 8 | When this gap is closed at the language runtime level, this library will become redundant and be deprecated. 9 | 10 | ## Getting started 11 | 12 | When building web-services and daemons, direct usage of this library is discouraged. 13 | 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. 14 | 15 | Add `https://github.com/swift-server/swift-backtrace.git` as a dependency in your `Package.swift`. 16 | 17 | ### Crash backtraces 18 | 19 | In your `main.swift`, do: 20 | 21 | ```swift 22 | import Backtrace 23 | 24 | // Do this first 25 | Backtrace.install() 26 | ``` 27 | 28 | 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. 29 | 30 | ``` 31 | $ swift build -c release -Xswiftc -g 32 | ``` 33 | 34 | When your app crashes, a stacktrace will be printed to `stderr`. 35 | -------------------------------------------------------------------------------- /Sources/CBacktrace/LICENSE: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2012-2016 Free Software Foundation, Inc. 2 | 3 | # Redistribution and use in source and binary forms, with or without 4 | # modification, are permitted provided that the following conditions are 5 | # met: 6 | 7 | # (1) Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | 10 | # (2) Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in 12 | # the documentation and/or other materials provided with the 13 | # distribution. 14 | 15 | # (3) The name of the author may not be used to 16 | # endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | 19 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 23 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 | # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | # POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Sources/CBacktrace/atomic.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* atomic.c -- Support for atomic functions if not present. 3 | Copyright (C) 2013-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | 38 | #include "include/backtrace.h" 39 | #include "backtrace-supported.h" 40 | #include "internal.h" 41 | 42 | /* This file holds implementations of the atomic functions that are 43 | used if the host compiler has the sync functions but not the atomic 44 | functions, as is true of versions of GCC before 4.7. */ 45 | 46 | #if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS) 47 | 48 | /* Do an atomic load of a pointer. */ 49 | 50 | void * 51 | backtrace_atomic_load_pointer (void *arg) 52 | { 53 | void **pp; 54 | void *p; 55 | 56 | pp = (void **) arg; 57 | p = *pp; 58 | while (!__sync_bool_compare_and_swap (pp, p, p)) 59 | p = *pp; 60 | return p; 61 | } 62 | 63 | /* Do an atomic load of an int. */ 64 | 65 | int 66 | backtrace_atomic_load_int (int *p) 67 | { 68 | int i; 69 | 70 | i = *p; 71 | while (!__sync_bool_compare_and_swap (p, i, i)) 72 | i = *p; 73 | return i; 74 | } 75 | 76 | /* Do an atomic store of a pointer. */ 77 | 78 | void 79 | backtrace_atomic_store_pointer (void *arg, void *p) 80 | { 81 | void **pp; 82 | void *old; 83 | 84 | pp = (void **) arg; 85 | old = *pp; 86 | while (!__sync_bool_compare_and_swap (pp, old, p)) 87 | old = *pp; 88 | } 89 | 90 | /* Do an atomic store of a size_t value. */ 91 | 92 | void 93 | backtrace_atomic_store_size_t (size_t *p, size_t v) 94 | { 95 | size_t old; 96 | 97 | old = *p; 98 | while (!__sync_bool_compare_and_swap (p, old, v)) 99 | old = *p; 100 | } 101 | 102 | /* Do an atomic store of a int value. */ 103 | 104 | void 105 | backtrace_atomic_store_int (int *p, int v) 106 | { 107 | size_t old; 108 | 109 | old = *p; 110 | while (!__sync_bool_compare_and_swap (p, old, v)) 111 | old = *p; 112 | } 113 | 114 | #endif 115 | #endif 116 | -------------------------------------------------------------------------------- /Sources/CBacktrace/backtrace-supported.h: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* backtrace-supported.h.in -- Whether stack backtrace is supported. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | /* The file backtrace-supported.h.in is used by configure to generate 35 | the file backtrace-supported.h. The file backtrace-supported.h may 36 | be #include'd to see whether the backtrace library will be able to 37 | get a backtrace and produce symbolic information. */ 38 | 39 | 40 | /* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library 41 | should work, 0 if it will not. Libraries may #include this to make 42 | other arrangements. */ 43 | 44 | #define BACKTRACE_SUPPORTED 1 45 | 46 | /* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace 47 | library will call malloc as it works, 0 if it will call mmap 48 | instead. This may be used to determine whether it is safe to call 49 | the backtrace functions from a signal handler. In general this 50 | only applies to calls like backtrace and backtrace_pcinfo. It does 51 | not apply to backtrace_simple, which never calls malloc. It does 52 | not apply to backtrace_print, which always calls fprintf and 53 | therefore malloc. */ 54 | 55 | #define BACKTRACE_USES_MALLOC 0 56 | 57 | /* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace 58 | library is configured with threading support, 0 if not. If this is 59 | 0, the threaded parameter to backtrace_create_state must be passed 60 | as 0. */ 61 | 62 | #define BACKTRACE_SUPPORTS_THREADS 1 63 | 64 | /* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo 65 | will work for variables. It will always work for functions. */ 66 | 67 | #define BACKTRACE_SUPPORTS_DATA 1 68 | #endif 69 | -------------------------------------------------------------------------------- /Sources/CBacktrace/backtrace.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* backtrace.c -- Entry point for stack backtrace library. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | 38 | #include "unwind.h" 39 | #include "include/backtrace.h" 40 | #include "internal.h" 41 | 42 | /* The main backtrace_full routine. */ 43 | 44 | /* Data passed through _Unwind_Backtrace. */ 45 | 46 | struct backtrace_data 47 | { 48 | /* Number of frames to skip. */ 49 | int skip; 50 | /* Library state. */ 51 | struct backtrace_state *state; 52 | /* Callback routine. */ 53 | backtrace_full_callback callback; 54 | /* Error callback routine. */ 55 | backtrace_error_callback error_callback; 56 | /* Data to pass to callback routines. */ 57 | void *data; 58 | /* Value to return from backtrace_full. */ 59 | int ret; 60 | /* Whether there is any memory available. */ 61 | int can_alloc; 62 | }; 63 | 64 | /* Unwind library callback routine. This is passed to 65 | _Unwind_Backtrace. */ 66 | 67 | static _Unwind_Reason_Code 68 | unwind (struct _Unwind_Context *context, void *vdata) 69 | { 70 | struct backtrace_data *bdata = (struct backtrace_data *) vdata; 71 | uintptr_t pc; 72 | int ip_before_insn = 0; 73 | 74 | #ifdef HAVE_GETIPINFO 75 | pc = _Unwind_GetIPInfo (context, &ip_before_insn); 76 | #else 77 | pc = _Unwind_GetIP (context); 78 | #endif 79 | 80 | if (bdata->skip > 0) 81 | { 82 | --bdata->skip; 83 | return _URC_NO_REASON; 84 | } 85 | 86 | if (!ip_before_insn) 87 | --pc; 88 | 89 | if (!bdata->can_alloc) 90 | bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL); 91 | else 92 | bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, 93 | bdata->error_callback, bdata->data); 94 | if (bdata->ret != 0) 95 | return _URC_END_OF_STACK; 96 | 97 | return _URC_NO_REASON; 98 | } 99 | 100 | /* Get a stack backtrace. */ 101 | 102 | int __attribute__((noinline)) 103 | backtrace_full (struct backtrace_state *state, int skip, 104 | backtrace_full_callback callback, 105 | backtrace_error_callback error_callback, void *data) 106 | { 107 | struct backtrace_data bdata; 108 | void *p; 109 | 110 | bdata.skip = skip + 1; 111 | bdata.state = state; 112 | bdata.callback = callback; 113 | bdata.error_callback = error_callback; 114 | bdata.data = data; 115 | bdata.ret = 0; 116 | 117 | /* If we can't allocate any memory at all, don't try to produce 118 | file/line information. */ 119 | p = backtrace_alloc (state, 4096, NULL, NULL); 120 | if (p == NULL) 121 | bdata.can_alloc = 0; 122 | else 123 | { 124 | backtrace_free (state, p, 4096, NULL, NULL); 125 | bdata.can_alloc = 1; 126 | } 127 | 128 | _Unwind_Backtrace (unwind, &bdata); 129 | return bdata.ret; 130 | } 131 | #endif 132 | -------------------------------------------------------------------------------- /Sources/CBacktrace/config.h: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* config.h. Generated from config.h.in by configure. */ 3 | /* config.h.in. Generated from configure.ac by autoheader. */ 4 | 5 | /* ELF size: 32 or 64 */ 6 | #define BACKTRACE_ELF_SIZE 64 7 | 8 | /* XCOFF size: 32 or 64 */ 9 | #define BACKTRACE_XCOFF_SIZE unused 10 | 11 | /* Define to 1 if you have the __atomic functions */ 12 | #define HAVE_ATOMIC_FUNCTIONS 1 13 | 14 | /* Define to 1 if you have the `clock_gettime' function. */ 15 | #define HAVE_CLOCK_GETTIME 1 16 | 17 | /* Define to 1 if you have the declaration of `getpagesize', and to 0 if you 18 | don't. */ 19 | #define HAVE_DECL_GETPAGESIZE 1 20 | 21 | /* Define to 1 if you have the declaration of `strnlen', and to 0 if you 22 | don't. */ 23 | #define HAVE_DECL_STRNLEN 1 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #define HAVE_DLFCN_H 1 27 | 28 | /* Define if dl_iterate_phdr is available. */ 29 | #define HAVE_DL_ITERATE_PHDR 1 30 | 31 | /* Define to 1 if you have the fcntl function */ 32 | #define HAVE_FCNTL 1 33 | 34 | /* Define if getexecname is available. */ 35 | /* #undef HAVE_GETEXECNAME */ 36 | 37 | /* Define if _Unwind_GetIPInfo is available. */ 38 | #define HAVE_GETIPINFO 1 39 | 40 | /* Define to 1 if you have the header file. */ 41 | #define HAVE_INTTYPES_H 1 42 | 43 | /* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in . 44 | */ 45 | /* #undef HAVE_KERN_PROC */ 46 | 47 | /* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in 48 | . */ 49 | /* #undef HAVE_KERN_PROC_ARGS */ 50 | 51 | /* Define if -llzma is available. */ 52 | /* #undef HAVE_LIBLZMA */ 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #define HAVE_LINK_H 1 56 | 57 | /* Define if AIX loadquery is available. */ 58 | /* #undef HAVE_LOADQUERY */ 59 | 60 | /* Define to 1 if you have the `lstat' function. */ 61 | #define HAVE_LSTAT 1 62 | 63 | /* Define to 1 if you have the header file. */ 64 | /* #undef HAVE_MACH_O_DYLD_H */ 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_MEMORY_H 1 68 | 69 | /* Define to 1 if you have the `readlink' function. */ 70 | #define HAVE_READLINK 1 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #define HAVE_STDINT_H 1 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #define HAVE_STDLIB_H 1 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #define HAVE_STRINGS_H 1 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #define HAVE_STRING_H 1 83 | 84 | /* Define to 1 if you have the __sync functions */ 85 | #define HAVE_SYNC_FUNCTIONS 1 86 | 87 | /* Define to 1 if you have the header file. */ 88 | /* #undef HAVE_SYS_LDR_H */ 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #define HAVE_SYS_MMAN_H 1 92 | 93 | /* Define to 1 if you have the header file. */ 94 | #define HAVE_SYS_STAT_H 1 95 | 96 | /* Define to 1 if you have the header file. */ 97 | #define HAVE_SYS_TYPES_H 1 98 | 99 | /* Define to 1 if you have the header file. */ 100 | #define HAVE_UNISTD_H 1 101 | 102 | /* Define if -lz is available. */ 103 | #define HAVE_ZLIB 1 104 | 105 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 106 | */ 107 | #define LT_OBJDIR ".libs/" 108 | 109 | /* Define to the address where bug reports for this package should be sent. */ 110 | #define PACKAGE_BUGREPORT "" 111 | 112 | /* Define to the full name of this package. */ 113 | #define PACKAGE_NAME "package-unused" 114 | 115 | /* Define to the full name and version of this package. */ 116 | #define PACKAGE_STRING "package-unused version-unused" 117 | 118 | /* Define to the one symbol short name of this package. */ 119 | #define PACKAGE_TARNAME "libbacktrace" 120 | 121 | /* Define to the home page for this package. */ 122 | #define PACKAGE_URL "" 123 | 124 | /* Define to the version of this package. */ 125 | #define PACKAGE_VERSION "version-unused" 126 | 127 | /* Define to 1 if you have the ANSI C header files. */ 128 | #define STDC_HEADERS 1 129 | 130 | /* Enable extensions on AIX 3, Interix. */ 131 | #ifndef _ALL_SOURCE 132 | # define _ALL_SOURCE 1 133 | #endif 134 | /* Enable GNU extensions on systems that have them. */ 135 | #ifndef _GNU_SOURCE 136 | # define _GNU_SOURCE 1 137 | #endif 138 | /* Enable threading extensions on Solaris. */ 139 | #ifndef _POSIX_PTHREAD_SEMANTICS 140 | # define _POSIX_PTHREAD_SEMANTICS 1 141 | #endif 142 | /* Enable extensions on HP NonStop. */ 143 | #ifndef _TANDEM_SOURCE 144 | # define _TANDEM_SOURCE 1 145 | #endif 146 | /* Enable general extensions on Solaris. */ 147 | #ifndef __EXTENSIONS__ 148 | # define __EXTENSIONS__ 1 149 | #endif 150 | 151 | 152 | /* Enable large inode numbers on Mac OS X 10.5. */ 153 | #ifndef _DARWIN_USE_64_BIT_INODE 154 | # define _DARWIN_USE_64_BIT_INODE 1 155 | #endif 156 | 157 | /* Number of bits in a file offset, on hosts where this is settable. */ 158 | /* #undef _FILE_OFFSET_BITS */ 159 | 160 | /* Define for large files, on AIX-style hosts. */ 161 | /* #undef _LARGE_FILES */ 162 | 163 | /* Define to 1 if on MINIX. */ 164 | /* #undef _MINIX */ 165 | 166 | /* Define to 2 if the system does not provide POSIX.1 features except with 167 | this defined. */ 168 | /* #undef _POSIX_1_SOURCE */ 169 | 170 | /* Define to 1 if you need to in order for `stat' and other things to work. */ 171 | /* #undef _POSIX_SOURCE */ 172 | #endif 173 | -------------------------------------------------------------------------------- /Sources/CBacktrace/fileline.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* fileline.c -- Get file and line number information in a backtrace. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC) 44 | #include 45 | #endif 46 | 47 | #ifdef HAVE_MACH_O_DYLD_H 48 | #include 49 | #endif 50 | 51 | #include "include/backtrace.h" 52 | #include "internal.h" 53 | 54 | #ifndef HAVE_GETEXECNAME 55 | #define getexecname() NULL 56 | #endif 57 | 58 | #if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC) 59 | 60 | #define sysctl_exec_name1(state, error_callback, data) NULL 61 | #define sysctl_exec_name2(state, error_callback, data) NULL 62 | 63 | #else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */ 64 | 65 | static char * 66 | sysctl_exec_name (struct backtrace_state *state, 67 | int mib0, int mib1, int mib2, int mib3, 68 | backtrace_error_callback error_callback, void *data) 69 | { 70 | int mib[4]; 71 | size_t len; 72 | char *name; 73 | size_t rlen; 74 | 75 | mib[0] = mib0; 76 | mib[1] = mib1; 77 | mib[2] = mib2; 78 | mib[3] = mib3; 79 | 80 | if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0) 81 | return NULL; 82 | name = (char *) backtrace_alloc (state, len, error_callback, data); 83 | if (name == NULL) 84 | return NULL; 85 | rlen = len; 86 | if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0) 87 | { 88 | backtrace_free (state, name, len, error_callback, data); 89 | return NULL; 90 | } 91 | return name; 92 | } 93 | 94 | #ifdef HAVE_KERN_PROC_ARGS 95 | 96 | static char * 97 | sysctl_exec_name1 (struct backtrace_state *state, 98 | backtrace_error_callback error_callback, void *data) 99 | { 100 | /* This variant is used on NetBSD. */ 101 | return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1, 102 | KERN_PROC_PATHNAME, error_callback, data); 103 | } 104 | 105 | #else 106 | 107 | #define sysctl_exec_name1(state, error_callback, data) NULL 108 | 109 | #endif 110 | 111 | #ifdef HAVE_KERN_PROC 112 | 113 | static char * 114 | sysctl_exec_name2 (struct backtrace_state *state, 115 | backtrace_error_callback error_callback, void *data) 116 | { 117 | /* This variant is used on FreeBSD. */ 118 | return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1, 119 | error_callback, data); 120 | } 121 | 122 | #else 123 | 124 | #define sysctl_exec_name2(state, error_callback, data) NULL 125 | 126 | #endif 127 | 128 | #endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */ 129 | 130 | #ifdef HAVE_MACH_O_DYLD_H 131 | 132 | static char * 133 | macho_get_executable_path (struct backtrace_state *state, 134 | backtrace_error_callback error_callback, void *data) 135 | { 136 | uint32_t len; 137 | char *name; 138 | 139 | len = 0; 140 | if (_NSGetExecutablePath (NULL, &len) == 0) 141 | return NULL; 142 | name = (char *) backtrace_alloc (state, len, error_callback, data); 143 | if (name == NULL) 144 | return NULL; 145 | if (_NSGetExecutablePath (name, &len) != 0) 146 | { 147 | backtrace_free (state, name, len, error_callback, data); 148 | return NULL; 149 | } 150 | return name; 151 | } 152 | 153 | #else /* !defined (HAVE_MACH_O_DYLD_H) */ 154 | 155 | #define macho_get_executable_path(state, error_callback, data) NULL 156 | 157 | #endif /* !defined (HAVE_MACH_O_DYLD_H) */ 158 | 159 | /* Initialize the fileline information from the executable. Returns 1 160 | on success, 0 on failure. */ 161 | 162 | static int 163 | fileline_initialize (struct backtrace_state *state, 164 | backtrace_error_callback error_callback, void *data) 165 | { 166 | int failed; 167 | fileline fileline_fn; 168 | int pass; 169 | int called_error_callback; 170 | int descriptor; 171 | const char *filename; 172 | char buf[64]; 173 | 174 | if (!state->threaded) 175 | failed = state->fileline_initialization_failed; 176 | else 177 | failed = backtrace_atomic_load_int (&state->fileline_initialization_failed); 178 | 179 | if (failed) 180 | { 181 | error_callback (data, "failed to read executable information", -1); 182 | return 0; 183 | } 184 | 185 | if (!state->threaded) 186 | fileline_fn = state->fileline_fn; 187 | else 188 | fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); 189 | if (fileline_fn != NULL) 190 | return 1; 191 | 192 | /* We have not initialized the information. Do it now. */ 193 | 194 | descriptor = -1; 195 | called_error_callback = 0; 196 | for (pass = 0; pass < 8; ++pass) 197 | { 198 | int does_not_exist; 199 | 200 | switch (pass) 201 | { 202 | case 0: 203 | filename = state->filename; 204 | break; 205 | case 1: 206 | filename = getexecname (); 207 | break; 208 | case 2: 209 | filename = "/proc/self/exe"; 210 | break; 211 | case 3: 212 | filename = "/proc/curproc/file"; 213 | break; 214 | case 4: 215 | snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out", 216 | (long) getpid ()); 217 | filename = buf; 218 | break; 219 | case 5: 220 | filename = sysctl_exec_name1 (state, error_callback, data); 221 | break; 222 | case 6: 223 | filename = sysctl_exec_name2 (state, error_callback, data); 224 | break; 225 | case 7: 226 | filename = macho_get_executable_path (state, error_callback, data); 227 | break; 228 | default: 229 | abort (); 230 | } 231 | 232 | if (filename == NULL) 233 | continue; 234 | 235 | descriptor = backtrace_open (filename, error_callback, data, 236 | &does_not_exist); 237 | if (descriptor < 0 && !does_not_exist) 238 | { 239 | called_error_callback = 1; 240 | break; 241 | } 242 | if (descriptor >= 0) 243 | break; 244 | } 245 | 246 | if (descriptor < 0) 247 | { 248 | if (!called_error_callback) 249 | { 250 | if (state->filename != NULL) 251 | error_callback (data, state->filename, ENOENT); 252 | else 253 | error_callback (data, 254 | "libbacktrace could not find executable to open", 255 | 0); 256 | } 257 | failed = 1; 258 | } 259 | 260 | if (!failed) 261 | { 262 | if (!backtrace_initialize (state, filename, descriptor, error_callback, 263 | data, &fileline_fn)) 264 | failed = 1; 265 | } 266 | 267 | if (failed) 268 | { 269 | if (!state->threaded) 270 | state->fileline_initialization_failed = 1; 271 | else 272 | backtrace_atomic_store_int (&state->fileline_initialization_failed, 1); 273 | return 0; 274 | } 275 | 276 | if (!state->threaded) 277 | state->fileline_fn = fileline_fn; 278 | else 279 | { 280 | backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn); 281 | 282 | /* Note that if two threads initialize at once, one of the data 283 | sets may be leaked. */ 284 | } 285 | 286 | return 1; 287 | } 288 | 289 | /* Given a PC, find the file name, line number, and function name. */ 290 | 291 | int 292 | backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, 293 | backtrace_full_callback callback, 294 | backtrace_error_callback error_callback, void *data) 295 | { 296 | if (!fileline_initialize (state, error_callback, data)) 297 | return 0; 298 | 299 | if (state->fileline_initialization_failed) 300 | return 0; 301 | 302 | return state->fileline_fn (state, pc, callback, error_callback, data); 303 | } 304 | 305 | /* Given a PC, find the symbol for it, and its value. */ 306 | 307 | int 308 | backtrace_syminfo (struct backtrace_state *state, uintptr_t pc, 309 | backtrace_syminfo_callback callback, 310 | backtrace_error_callback error_callback, void *data) 311 | { 312 | if (!fileline_initialize (state, error_callback, data)) 313 | return 0; 314 | 315 | if (state->fileline_initialization_failed) 316 | return 0; 317 | 318 | state->syminfo_fn (state, pc, callback, error_callback, data); 319 | return 1; 320 | } 321 | 322 | /* A backtrace_syminfo_callback that can call into a 323 | backtrace_full_callback, used when we have a symbol table but no 324 | debug info. */ 325 | 326 | void 327 | backtrace_syminfo_to_full_callback (void *data, uintptr_t pc, 328 | const char *symname, 329 | uintptr_t symval ATTRIBUTE_UNUSED, 330 | uintptr_t symsize ATTRIBUTE_UNUSED) 331 | { 332 | struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; 333 | 334 | bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname); 335 | } 336 | 337 | /* An error callback that corresponds to 338 | backtrace_syminfo_to_full_callback. */ 339 | 340 | void 341 | backtrace_syminfo_to_full_error_callback (void *data, const char *msg, 342 | int errnum) 343 | { 344 | struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; 345 | 346 | bdata->full_error_callback (bdata->full_data, msg, errnum); 347 | } 348 | #endif 349 | -------------------------------------------------------------------------------- /Sources/CBacktrace/filenames.h: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* btest.c -- Filename header for libbacktrace library 3 | Copyright (C) 2012-2018 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #ifndef GCC_VERSION 35 | # define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) 36 | #endif 37 | 38 | #if (GCC_VERSION < 2007) 39 | # define __attribute__(x) 40 | #endif 41 | 42 | #ifndef ATTRIBUTE_UNUSED 43 | # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) 44 | #endif 45 | 46 | #if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) 47 | # define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\') 48 | # define HAS_DRIVE_SPEC(f) ((f)[0] != '\0' && (f)[1] == ':') 49 | # define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f)) 50 | #else 51 | # define IS_DIR_SEPARATOR(c) ((c) == '/') 52 | # define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0])) 53 | #endif 54 | #endif 55 | -------------------------------------------------------------------------------- /Sources/CBacktrace/include/backtrace.h: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* backtrace.h -- Public header file for stack backtrace library. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #ifndef BACKTRACE_H 35 | #define BACKTRACE_H 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* The backtrace state. This struct is intentionally not defined in 46 | the public interface. */ 47 | 48 | struct backtrace_state; 49 | 50 | /* The type of the error callback argument to backtrace functions. 51 | This function, if not NULL, will be called for certain error cases. 52 | The DATA argument is passed to the function that calls this one. 53 | The MSG argument is an error message. The ERRNUM argument, if 54 | greater than 0, holds an errno value. The MSG buffer may become 55 | invalid after this function returns. 56 | 57 | As a special case, the ERRNUM argument will be passed as -1 if no 58 | debug info can be found for the executable, or if the debug info 59 | exists but has an unsupported version, but the function requires 60 | debug info (e.g., backtrace_full, backtrace_pcinfo). The MSG in 61 | this case will be something along the lines of "no debug info". 62 | Similarly, ERRNUM will be passed as -1 if there is no symbol table, 63 | but the function requires a symbol table (e.g., backtrace_syminfo). 64 | This may be used as a signal that some other approach should be 65 | tried. */ 66 | 67 | typedef void (*backtrace_error_callback) (void *data, const char *msg, 68 | int errnum); 69 | 70 | /* Create state information for the backtrace routines. This must be 71 | called before any of the other routines, and its return value must 72 | be passed to all of the other routines. FILENAME is the path name 73 | of the executable file; if it is NULL the library will try 74 | system-specific path names. If not NULL, FILENAME must point to a 75 | permanent buffer. If THREADED is non-zero the state may be 76 | accessed by multiple threads simultaneously, and the library will 77 | use appropriate atomic operations. If THREADED is zero the state 78 | may only be accessed by one thread at a time. This returns a state 79 | pointer on success, NULL on error. If an error occurs, this will 80 | call the ERROR_CALLBACK routine. 81 | 82 | Calling this function allocates resources that cannot be freed. 83 | There is no backtrace_free_state function. The state is used to 84 | cache information that is expensive to recompute. Programs are 85 | expected to call this function at most once and to save the return 86 | value for all later calls to backtrace functions. */ 87 | 88 | extern struct backtrace_state *backtrace_create_state ( 89 | const char *filename, int threaded, 90 | backtrace_error_callback error_callback, void *data); 91 | 92 | /* The type of the callback argument to the backtrace_full function. 93 | DATA is the argument passed to backtrace_full. PC is the program 94 | counter. FILENAME is the name of the file containing PC, or NULL 95 | if not available. LINENO is the line number in FILENAME containing 96 | PC, or 0 if not available. FUNCTION is the name of the function 97 | containing PC, or NULL if not available. This should return 0 to 98 | continuing tracing. The FILENAME and FUNCTION buffers may become 99 | invalid after this function returns. */ 100 | 101 | typedef int (*backtrace_full_callback) (void *data, uintptr_t pc, 102 | const char *filename, int lineno, 103 | const char *function); 104 | 105 | /* Get a full stack backtrace. SKIP is the number of frames to skip; 106 | passing 0 will start the trace with the function calling 107 | backtrace_full. DATA is passed to the callback routine. If any 108 | call to CALLBACK returns a non-zero value, the stack backtrace 109 | stops, and backtrace returns that value; this may be used to limit 110 | the number of stack frames desired. If all calls to CALLBACK 111 | return 0, backtrace returns 0. The backtrace_full function will 112 | make at least one call to either CALLBACK or ERROR_CALLBACK. This 113 | function requires debug info for the executable. */ 114 | 115 | extern int backtrace_full (struct backtrace_state *state, int skip, 116 | backtrace_full_callback callback, 117 | backtrace_error_callback error_callback, 118 | void *data); 119 | 120 | /* The type of the callback argument to the backtrace_simple function. 121 | DATA is the argument passed to simple_backtrace. PC is the program 122 | counter. This should return 0 to continue tracing. */ 123 | 124 | typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc); 125 | 126 | /* Get a simple backtrace. SKIP is the number of frames to skip, as 127 | in backtrace. DATA is passed to the callback routine. If any call 128 | to CALLBACK returns a non-zero value, the stack backtrace stops, 129 | and backtrace_simple returns that value. Otherwise 130 | backtrace_simple returns 0. The backtrace_simple function will 131 | make at least one call to either CALLBACK or ERROR_CALLBACK. This 132 | function does not require any debug info for the executable. */ 133 | 134 | extern int backtrace_simple (struct backtrace_state *state, int skip, 135 | backtrace_simple_callback callback, 136 | backtrace_error_callback error_callback, 137 | void *data); 138 | 139 | /* Print the current backtrace in a user readable format to a FILE. 140 | SKIP is the number of frames to skip, as in backtrace_full. Any 141 | error messages are printed to stderr. This function requires debug 142 | info for the executable. */ 143 | 144 | extern void backtrace_print (struct backtrace_state *state, int skip, FILE *); 145 | 146 | /* Given PC, a program counter in the current program, call the 147 | callback function with filename, line number, and function name 148 | information. This will normally call the callback function exactly 149 | once. However, if the PC happens to describe an inlined call, and 150 | the debugging information contains the necessary information, then 151 | this may call the callback function multiple times. This will make 152 | at least one call to either CALLBACK or ERROR_CALLBACK. This 153 | returns the first non-zero value returned by CALLBACK, or 0. */ 154 | 155 | extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, 156 | backtrace_full_callback callback, 157 | backtrace_error_callback error_callback, 158 | void *data); 159 | 160 | /* The type of the callback argument to backtrace_syminfo. DATA and 161 | PC are the arguments passed to backtrace_syminfo. SYMNAME is the 162 | name of the symbol for the corresponding code. SYMVAL is the 163 | value and SYMSIZE is the size of the symbol. SYMNAME will be NULL 164 | if no error occurred but the symbol could not be found. */ 165 | 166 | typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc, 167 | const char *symname, 168 | uintptr_t symval, 169 | uintptr_t symsize); 170 | 171 | /* Given ADDR, an address or program counter in the current program, 172 | call the callback information with the symbol name and value 173 | describing the function or variable in which ADDR may be found. 174 | This will call either CALLBACK or ERROR_CALLBACK exactly once. 175 | This returns 1 on success, 0 on failure. This function requires 176 | the symbol table but does not require the debug info. Note that if 177 | the symbol table is present but ADDR could not be found in the 178 | table, CALLBACK will be called with a NULL SYMNAME argument. 179 | Returns 1 on success, 0 on error. */ 180 | 181 | extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr, 182 | backtrace_syminfo_callback callback, 183 | backtrace_error_callback error_callback, 184 | void *data); 185 | 186 | #ifdef __cplusplus 187 | } /* End extern "C". */ 188 | #endif 189 | 190 | #endif 191 | #endif 192 | -------------------------------------------------------------------------------- /Sources/CBacktrace/internal.h: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* internal.h -- Internal header file for stack backtrace library. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #ifndef BACKTRACE_INTERNAL_H 35 | #define BACKTRACE_INTERNAL_H 36 | 37 | /* We assume that and "include/backtrace.h" have already been 38 | included. */ 39 | 40 | #ifndef GCC_VERSION 41 | # define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) 42 | #endif 43 | 44 | #if (GCC_VERSION < 2007) 45 | # define __attribute__(x) 46 | #endif 47 | 48 | #ifndef ATTRIBUTE_UNUSED 49 | # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) 50 | #endif 51 | 52 | #ifndef ATTRIBUTE_MALLOC 53 | # if (GCC_VERSION >= 2096) 54 | # define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) 55 | # else 56 | # define ATTRIBUTE_MALLOC 57 | # endif 58 | #endif 59 | 60 | #ifndef ATTRIBUTE_FALLTHROUGH 61 | # if (GCC_VERSION >= 7000) 62 | # define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__)) 63 | # else 64 | # define ATTRIBUTE_FALLTHROUGH 65 | # endif 66 | #endif 67 | 68 | #ifndef HAVE_SYNC_FUNCTIONS 69 | 70 | /* Define out the sync functions. These should never be called if 71 | they are not available. */ 72 | 73 | #define __sync_bool_compare_and_swap(A, B, C) (abort(), 1) 74 | #define __sync_lock_test_and_set(A, B) (abort(), 0) 75 | #define __sync_lock_release(A) abort() 76 | 77 | #endif /* !defined (HAVE_SYNC_FUNCTIONS) */ 78 | 79 | #ifdef HAVE_ATOMIC_FUNCTIONS 80 | 81 | /* We have the atomic builtin functions. */ 82 | 83 | #define backtrace_atomic_load_pointer(p) \ 84 | __atomic_load_n ((p), __ATOMIC_ACQUIRE) 85 | #define backtrace_atomic_load_int(p) \ 86 | __atomic_load_n ((p), __ATOMIC_ACQUIRE) 87 | #define backtrace_atomic_store_pointer(p, v) \ 88 | __atomic_store_n ((p), (v), __ATOMIC_RELEASE) 89 | #define backtrace_atomic_store_size_t(p, v) \ 90 | __atomic_store_n ((p), (v), __ATOMIC_RELEASE) 91 | #define backtrace_atomic_store_int(p, v) \ 92 | __atomic_store_n ((p), (v), __ATOMIC_RELEASE) 93 | 94 | #else /* !defined (HAVE_ATOMIC_FUNCTIONS) */ 95 | #ifdef HAVE_SYNC_FUNCTIONS 96 | 97 | /* We have the sync functions but not the atomic functions. Define 98 | the atomic ones in terms of the sync ones. */ 99 | 100 | extern void *backtrace_atomic_load_pointer (void *); 101 | extern int backtrace_atomic_load_int (int *); 102 | extern void backtrace_atomic_store_pointer (void *, void *); 103 | extern void backtrace_atomic_store_size_t (size_t *, size_t); 104 | extern void backtrace_atomic_store_int (int *, int); 105 | 106 | #else /* !defined (HAVE_SYNC_FUNCTIONS) */ 107 | 108 | /* We have neither the sync nor the atomic functions. These will 109 | never be called. */ 110 | 111 | #define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL) 112 | #define backtrace_atomic_load_int(p) (abort(), 0) 113 | #define backtrace_atomic_store_pointer(p, v) abort() 114 | #define backtrace_atomic_store_size_t(p, v) abort() 115 | #define backtrace_atomic_store_int(p, v) abort() 116 | 117 | #endif /* !defined (HAVE_SYNC_FUNCTIONS) */ 118 | #endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */ 119 | 120 | /* The type of the function that collects file/line information. This 121 | is like backtrace_pcinfo. */ 122 | 123 | typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc, 124 | backtrace_full_callback callback, 125 | backtrace_error_callback error_callback, void *data); 126 | 127 | /* The type of the function that collects symbol information. This is 128 | like backtrace_syminfo. */ 129 | 130 | typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc, 131 | backtrace_syminfo_callback callback, 132 | backtrace_error_callback error_callback, void *data); 133 | 134 | /* What the backtrace state pointer points to. */ 135 | 136 | struct backtrace_state 137 | { 138 | /* The name of the executable. */ 139 | const char *filename; 140 | /* Non-zero if threaded. */ 141 | int threaded; 142 | /* The master lock for fileline_fn, fileline_data, syminfo_fn, 143 | syminfo_data, fileline_initialization_failed and everything the 144 | data pointers point to. */ 145 | void *lock; 146 | /* The function that returns file/line information. */ 147 | fileline fileline_fn; 148 | /* The data to pass to FILELINE_FN. */ 149 | void *fileline_data; 150 | /* The function that returns symbol information. */ 151 | syminfo syminfo_fn; 152 | /* The data to pass to SYMINFO_FN. */ 153 | void *syminfo_data; 154 | /* Whether initializing the file/line information failed. */ 155 | int fileline_initialization_failed; 156 | /* The lock for the freelist. */ 157 | int lock_alloc; 158 | /* The freelist when using mmap. */ 159 | struct backtrace_freelist_struct *freelist; 160 | }; 161 | 162 | /* Open a file for reading. Returns -1 on error. If DOES_NOT_EXIST 163 | is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1 164 | if the file does not exist. If the file does not exist and 165 | DOES_NOT_EXIST is not NULL, the function will return -1 and will 166 | not call ERROR_CALLBACK. On other errors, or if DOES_NOT_EXIST is 167 | NULL, the function will call ERROR_CALLBACK before returning. */ 168 | extern int backtrace_open (const char *filename, 169 | backtrace_error_callback error_callback, 170 | void *data, 171 | int *does_not_exist); 172 | 173 | /* A view of the contents of a file. This supports mmap when 174 | available. A view will remain in memory even after backtrace_close 175 | is called on the file descriptor from which the view was 176 | obtained. */ 177 | 178 | struct backtrace_view 179 | { 180 | /* The data that the caller requested. */ 181 | const void *data; 182 | /* The base of the view. */ 183 | void *base; 184 | /* The total length of the view. */ 185 | size_t len; 186 | }; 187 | 188 | /* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the 189 | result in *VIEW. Returns 1 on success, 0 on error. */ 190 | extern int backtrace_get_view (struct backtrace_state *state, int descriptor, 191 | off_t offset, uint64_t size, 192 | backtrace_error_callback error_callback, 193 | void *data, struct backtrace_view *view); 194 | 195 | /* Release a view created by backtrace_get_view. */ 196 | extern void backtrace_release_view (struct backtrace_state *state, 197 | struct backtrace_view *view, 198 | backtrace_error_callback error_callback, 199 | void *data); 200 | 201 | /* Close a file opened by backtrace_open. Returns 1 on success, 0 on 202 | error. */ 203 | 204 | extern int backtrace_close (int descriptor, 205 | backtrace_error_callback error_callback, 206 | void *data); 207 | 208 | /* Sort without using memory. */ 209 | 210 | extern void backtrace_qsort (void *base, size_t count, size_t size, 211 | int (*compar) (const void *, const void *)); 212 | 213 | /* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL, 214 | this does not report an error, it just returns NULL. */ 215 | 216 | extern void *backtrace_alloc (struct backtrace_state *state, size_t size, 217 | backtrace_error_callback error_callback, 218 | void *data) ATTRIBUTE_MALLOC; 219 | 220 | /* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is 221 | NULL, this does not report an error. */ 222 | 223 | extern void backtrace_free (struct backtrace_state *state, void *mem, 224 | size_t size, 225 | backtrace_error_callback error_callback, 226 | void *data); 227 | 228 | /* A growable vector of some struct. This is used for more efficient 229 | allocation when we don't know the final size of some group of data 230 | that we want to represent as an array. */ 231 | 232 | struct backtrace_vector 233 | { 234 | /* The base of the vector. */ 235 | void *base; 236 | /* The number of bytes in the vector. */ 237 | size_t size; 238 | /* The number of bytes available at the current allocation. */ 239 | size_t alc; 240 | }; 241 | 242 | /* Grow VEC by SIZE bytes. Return a pointer to the newly allocated 243 | bytes. Note that this may move the entire vector to a new memory 244 | location. Returns NULL on failure. */ 245 | 246 | extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size, 247 | backtrace_error_callback error_callback, 248 | void *data, 249 | struct backtrace_vector *vec); 250 | 251 | /* Finish the current allocation on VEC. Prepare to start a new 252 | allocation. The finished allocation will never be freed. Returns 253 | a pointer to the base of the finished entries, or NULL on 254 | failure. */ 255 | 256 | extern void* backtrace_vector_finish (struct backtrace_state *state, 257 | struct backtrace_vector *vec, 258 | backtrace_error_callback error_callback, 259 | void *data); 260 | 261 | /* Release any extra space allocated for VEC. This may change 262 | VEC->base. Returns 1 on success, 0 on failure. */ 263 | 264 | extern int backtrace_vector_release (struct backtrace_state *state, 265 | struct backtrace_vector *vec, 266 | backtrace_error_callback error_callback, 267 | void *data); 268 | 269 | /* Free the space managed by VEC. This will reset VEC. */ 270 | 271 | static inline void 272 | backtrace_vector_free (struct backtrace_state *state, 273 | struct backtrace_vector *vec, 274 | backtrace_error_callback error_callback, void *data) 275 | { 276 | vec->alc += vec->size; 277 | vec->size = 0; 278 | backtrace_vector_release (state, vec, error_callback, data); 279 | } 280 | 281 | /* Read initial debug data from a descriptor, and set the 282 | fileline_data, syminfo_fn, and syminfo_data fields of STATE. 283 | Return the fileln_fn field in *FILELN_FN--this is done this way so 284 | that the synchronization code is only implemented once. This is 285 | called after the descriptor has first been opened. It will close 286 | the descriptor if it is no longer needed. Returns 1 on success, 0 287 | on error. There will be multiple implementations of this function, 288 | for different file formats. Each system will compile the 289 | appropriate one. */ 290 | 291 | extern int backtrace_initialize (struct backtrace_state *state, 292 | const char *filename, 293 | int descriptor, 294 | backtrace_error_callback error_callback, 295 | void *data, 296 | fileline *fileline_fn); 297 | 298 | /* An enum for the DWARF sections we care about. */ 299 | 300 | enum dwarf_section 301 | { 302 | DEBUG_INFO, 303 | DEBUG_LINE, 304 | DEBUG_ABBREV, 305 | DEBUG_RANGES, 306 | DEBUG_STR, 307 | DEBUG_ADDR, 308 | DEBUG_STR_OFFSETS, 309 | DEBUG_LINE_STR, 310 | DEBUG_RNGLISTS, 311 | 312 | DEBUG_MAX 313 | }; 314 | 315 | /* Data for the DWARF sections we care about. */ 316 | 317 | struct dwarf_sections 318 | { 319 | const unsigned char *data[DEBUG_MAX]; 320 | size_t size[DEBUG_MAX]; 321 | }; 322 | 323 | /* DWARF data read from a file, used for .gnu_debugaltlink. */ 324 | 325 | struct dwarf_data; 326 | 327 | /* Add file/line information for a DWARF module. */ 328 | 329 | extern int backtrace_dwarf_add (struct backtrace_state *state, 330 | uintptr_t base_address, 331 | const struct dwarf_sections *dwarf_sections, 332 | int is_bigendian, 333 | struct dwarf_data *fileline_altlink, 334 | backtrace_error_callback error_callback, 335 | void *data, fileline *fileline_fn, 336 | struct dwarf_data **fileline_entry); 337 | 338 | /* A data structure to pass to backtrace_syminfo_to_full. */ 339 | 340 | struct backtrace_call_full 341 | { 342 | backtrace_full_callback full_callback; 343 | backtrace_error_callback full_error_callback; 344 | void *full_data; 345 | int ret; 346 | }; 347 | 348 | /* A backtrace_syminfo_callback that can call into a 349 | backtrace_full_callback, used when we have a symbol table but no 350 | debug info. */ 351 | 352 | extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc, 353 | const char *symname, 354 | uintptr_t symval, 355 | uintptr_t symsize); 356 | 357 | /* An error callback that corresponds to 358 | backtrace_syminfo_to_full_callback. */ 359 | 360 | extern void backtrace_syminfo_to_full_error_callback (void *, const char *, 361 | int); 362 | 363 | /* A test-only hook for elf_uncompress_zdebug. */ 364 | 365 | extern int backtrace_uncompress_zdebug (struct backtrace_state *, 366 | const unsigned char *compressed, 367 | size_t compressed_size, 368 | backtrace_error_callback, void *data, 369 | unsigned char **uncompressed, 370 | size_t *uncompressed_size); 371 | 372 | /* A test-only hook for elf_uncompress_lzma. */ 373 | 374 | extern int backtrace_uncompress_lzma (struct backtrace_state *, 375 | const unsigned char *compressed, 376 | size_t compressed_size, 377 | backtrace_error_callback, void *data, 378 | unsigned char **uncompressed, 379 | size_t *uncompressed_size); 380 | 381 | #endif 382 | #endif 383 | -------------------------------------------------------------------------------- /Sources/CBacktrace/mmap.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* mmap.c -- Memory allocation with mmap. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "include/backtrace.h" 44 | #include "internal.h" 45 | 46 | #ifndef HAVE_DECL_GETPAGESIZE 47 | extern int getpagesize (void); 48 | #endif 49 | 50 | /* Memory allocation on systems that provide anonymous mmap. This 51 | permits the backtrace functions to be invoked from a signal 52 | handler, assuming that mmap is async-signal safe. */ 53 | 54 | #ifndef MAP_ANONYMOUS 55 | #define MAP_ANONYMOUS MAP_ANON 56 | #endif 57 | 58 | #ifndef MAP_FAILED 59 | #define MAP_FAILED ((void *)-1) 60 | #endif 61 | 62 | /* A list of free memory blocks. */ 63 | 64 | struct backtrace_freelist_struct 65 | { 66 | /* Next on list. */ 67 | struct backtrace_freelist_struct *next; 68 | /* Size of this block, including this structure. */ 69 | size_t size; 70 | }; 71 | 72 | /* Free memory allocated by backtrace_alloc. */ 73 | 74 | static void 75 | backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size) 76 | { 77 | /* Just leak small blocks. We don't have to be perfect. Don't put 78 | more than 16 entries on the free list, to avoid wasting time 79 | searching when allocating a block. If we have more than 16 80 | entries, leak the smallest entry. */ 81 | 82 | if (size >= sizeof (struct backtrace_freelist_struct)) 83 | { 84 | size_t c; 85 | struct backtrace_freelist_struct **ppsmall; 86 | struct backtrace_freelist_struct **pp; 87 | struct backtrace_freelist_struct *p; 88 | 89 | c = 0; 90 | ppsmall = NULL; 91 | for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) 92 | { 93 | if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size) 94 | ppsmall = pp; 95 | ++c; 96 | } 97 | if (c >= 16) 98 | { 99 | if (size <= (*ppsmall)->size) 100 | return; 101 | *ppsmall = (*ppsmall)->next; 102 | } 103 | 104 | p = (struct backtrace_freelist_struct *) addr; 105 | p->next = state->freelist; 106 | p->size = size; 107 | state->freelist = p; 108 | } 109 | } 110 | 111 | /* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't 112 | report an error. */ 113 | 114 | void * 115 | backtrace_alloc (struct backtrace_state *state, 116 | size_t size, backtrace_error_callback error_callback, 117 | void *data) 118 | { 119 | void *ret; 120 | int locked; 121 | struct backtrace_freelist_struct **pp; 122 | size_t pagesize; 123 | size_t asksize; 124 | void *page; 125 | 126 | ret = NULL; 127 | 128 | /* If we can acquire the lock, then see if there is space on the 129 | free list. If we can't acquire the lock, drop straight into 130 | using mmap. __sync_lock_test_and_set returns the old state of 131 | the lock, so we have acquired it if it returns 0. */ 132 | 133 | if (!state->threaded) 134 | locked = 1; 135 | else 136 | locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0; 137 | 138 | if (locked) 139 | { 140 | for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) 141 | { 142 | if ((*pp)->size >= size) 143 | { 144 | struct backtrace_freelist_struct *p; 145 | 146 | p = *pp; 147 | *pp = p->next; 148 | 149 | /* Round for alignment; we assume that no type we care about 150 | is more than 8 bytes. */ 151 | size = (size + 7) & ~ (size_t) 7; 152 | if (size < p->size) 153 | backtrace_free_locked (state, (char *) p + size, 154 | p->size - size); 155 | 156 | ret = (void *) p; 157 | 158 | break; 159 | } 160 | } 161 | 162 | if (state->threaded) 163 | __sync_lock_release (&state->lock_alloc); 164 | } 165 | 166 | if (ret == NULL) 167 | { 168 | /* Allocate a new page. */ 169 | 170 | pagesize = getpagesize (); 171 | asksize = (size + pagesize - 1) & ~ (pagesize - 1); 172 | page = mmap (NULL, asksize, PROT_READ | PROT_WRITE, 173 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 174 | if (page == MAP_FAILED) 175 | { 176 | if (error_callback) 177 | error_callback (data, "mmap", errno); 178 | } 179 | else 180 | { 181 | size = (size + 7) & ~ (size_t) 7; 182 | if (size < asksize) 183 | backtrace_free (state, (char *) page + size, asksize - size, 184 | error_callback, data); 185 | 186 | ret = page; 187 | } 188 | } 189 | 190 | return ret; 191 | } 192 | 193 | /* Free memory allocated by backtrace_alloc. */ 194 | 195 | void 196 | backtrace_free (struct backtrace_state *state, void *addr, size_t size, 197 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 198 | void *data ATTRIBUTE_UNUSED) 199 | { 200 | int locked; 201 | 202 | /* If we are freeing a large aligned block, just release it back to 203 | the system. This case arises when growing a vector for a large 204 | binary with lots of debug info. Calling munmap here may cause us 205 | to call mmap again if there is also a large shared library; we 206 | just live with that. */ 207 | if (size >= 16 * 4096) 208 | { 209 | size_t pagesize; 210 | 211 | pagesize = getpagesize (); 212 | if (((uintptr_t) addr & (pagesize - 1)) == 0 213 | && (size & (pagesize - 1)) == 0) 214 | { 215 | /* If munmap fails for some reason, just add the block to 216 | the freelist. */ 217 | if (munmap (addr, size) == 0) 218 | return; 219 | } 220 | } 221 | 222 | /* If we can acquire the lock, add the new space to the free list. 223 | If we can't acquire the lock, just leak the memory. 224 | __sync_lock_test_and_set returns the old state of the lock, so we 225 | have acquired it if it returns 0. */ 226 | 227 | if (!state->threaded) 228 | locked = 1; 229 | else 230 | locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0; 231 | 232 | if (locked) 233 | { 234 | backtrace_free_locked (state, addr, size); 235 | 236 | if (state->threaded) 237 | __sync_lock_release (&state->lock_alloc); 238 | } 239 | } 240 | 241 | /* Grow VEC by SIZE bytes. */ 242 | 243 | void * 244 | backtrace_vector_grow (struct backtrace_state *state,size_t size, 245 | backtrace_error_callback error_callback, 246 | void *data, struct backtrace_vector *vec) 247 | { 248 | void *ret; 249 | 250 | if (size > vec->alc) 251 | { 252 | size_t pagesize; 253 | size_t alc; 254 | void *base; 255 | 256 | pagesize = getpagesize (); 257 | alc = vec->size + size; 258 | if (vec->size == 0) 259 | alc = 16 * size; 260 | else if (alc < pagesize) 261 | { 262 | alc *= 2; 263 | if (alc > pagesize) 264 | alc = pagesize; 265 | } 266 | else 267 | { 268 | alc *= 2; 269 | alc = (alc + pagesize - 1) & ~ (pagesize - 1); 270 | } 271 | base = backtrace_alloc (state, alc, error_callback, data); 272 | if (base == NULL) 273 | return NULL; 274 | if (vec->base != NULL) 275 | { 276 | memcpy (base, vec->base, vec->size); 277 | backtrace_free (state, vec->base, vec->size + vec->alc, 278 | error_callback, data); 279 | } 280 | vec->base = base; 281 | vec->alc = alc - vec->size; 282 | } 283 | 284 | ret = (char *) vec->base + vec->size; 285 | vec->size += size; 286 | vec->alc -= size; 287 | return ret; 288 | } 289 | 290 | /* Finish the current allocation on VEC. */ 291 | 292 | void * 293 | backtrace_vector_finish ( 294 | struct backtrace_state *state ATTRIBUTE_UNUSED, 295 | struct backtrace_vector *vec, 296 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 297 | void *data ATTRIBUTE_UNUSED) 298 | { 299 | void *ret; 300 | 301 | ret = vec->base; 302 | vec->base = (char *) vec->base + vec->size; 303 | vec->size = 0; 304 | return ret; 305 | } 306 | 307 | /* Release any extra space allocated for VEC. */ 308 | 309 | int 310 | backtrace_vector_release (struct backtrace_state *state, 311 | struct backtrace_vector *vec, 312 | backtrace_error_callback error_callback, 313 | void *data) 314 | { 315 | size_t size; 316 | size_t alc; 317 | size_t aligned; 318 | 319 | /* Make sure that the block that we free is aligned on an 8-byte 320 | boundary. */ 321 | size = vec->size; 322 | alc = vec->alc; 323 | aligned = (size + 7) & ~ (size_t) 7; 324 | alc -= aligned - size; 325 | 326 | backtrace_free (state, (char *) vec->base + aligned, alc, 327 | error_callback, data); 328 | vec->alc = 0; 329 | if (vec->size == 0) 330 | vec->base = NULL; 331 | return 1; 332 | } 333 | #endif 334 | -------------------------------------------------------------------------------- /Sources/CBacktrace/mmapio.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* mmapio.c -- File views using mmap. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "include/backtrace.h" 42 | #include "internal.h" 43 | 44 | #ifndef HAVE_DECL_GETPAGESIZE 45 | extern int getpagesize (void); 46 | #endif 47 | 48 | #ifndef MAP_FAILED 49 | #define MAP_FAILED ((void *)-1) 50 | #endif 51 | 52 | /* This file implements file views and memory allocation when mmap is 53 | available. */ 54 | 55 | /* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */ 56 | 57 | int 58 | backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED, 59 | int descriptor, off_t offset, uint64_t size, 60 | backtrace_error_callback error_callback, 61 | void *data, struct backtrace_view *view) 62 | { 63 | size_t pagesize; 64 | unsigned int inpage; 65 | off_t pageoff; 66 | void *map; 67 | 68 | if ((uint64_t) (size_t) size != size) 69 | { 70 | error_callback (data, "file size too large", 0); 71 | return 0; 72 | } 73 | 74 | pagesize = getpagesize (); 75 | inpage = offset % pagesize; 76 | pageoff = offset - inpage; 77 | 78 | size += inpage; 79 | size = (size + (pagesize - 1)) & ~ (pagesize - 1); 80 | 81 | map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff); 82 | if (map == MAP_FAILED) 83 | { 84 | error_callback (data, "mmap", errno); 85 | return 0; 86 | } 87 | 88 | view->data = (char *) map + inpage; 89 | view->base = map; 90 | view->len = size; 91 | 92 | return 1; 93 | } 94 | 95 | /* Release a view read by backtrace_get_view. */ 96 | 97 | void 98 | backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED, 99 | struct backtrace_view *view, 100 | backtrace_error_callback error_callback, 101 | void *data) 102 | { 103 | union { 104 | const void *cv; 105 | void *v; 106 | } const_cast; 107 | 108 | const_cast.cv = view->base; 109 | if (munmap (const_cast.v, view->len) < 0) 110 | error_callback (data, "munmap", errno); 111 | } 112 | #endif 113 | -------------------------------------------------------------------------------- /Sources/CBacktrace/posix.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* posix.c -- POSIX file I/O routines for the backtrace library. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "include/backtrace.h" 43 | #include "internal.h" 44 | 45 | #ifndef O_BINARY 46 | #define O_BINARY 0 47 | #endif 48 | 49 | #ifndef O_CLOEXEC 50 | #define O_CLOEXEC 0 51 | #endif 52 | 53 | #ifndef FD_CLOEXEC 54 | #define FD_CLOEXEC 1 55 | #endif 56 | 57 | /* Open a file for reading. */ 58 | 59 | int 60 | backtrace_open (const char *filename, backtrace_error_callback error_callback, 61 | void *data, int *does_not_exist) 62 | { 63 | int descriptor; 64 | 65 | if (does_not_exist != NULL) 66 | *does_not_exist = 0; 67 | 68 | descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC)); 69 | if (descriptor < 0) 70 | { 71 | /* If DOES_NOT_EXIST is not NULL, then don't call ERROR_CALLBACK 72 | if the file does not exist. We treat lacking permission to 73 | open the file as the file not existing; this case arises when 74 | running the libgo syscall package tests as root. */ 75 | if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES)) 76 | *does_not_exist = 1; 77 | else 78 | error_callback (data, filename, errno); 79 | return -1; 80 | } 81 | 82 | #ifdef HAVE_FCNTL 83 | /* Set FD_CLOEXEC just in case the kernel does not support 84 | O_CLOEXEC. It doesn't matter if this fails for some reason. 85 | FIXME: At some point it should be safe to only do this if 86 | O_CLOEXEC == 0. */ 87 | fcntl (descriptor, F_SETFD, FD_CLOEXEC); 88 | #endif 89 | 90 | return descriptor; 91 | } 92 | 93 | /* Close DESCRIPTOR. */ 94 | 95 | int 96 | backtrace_close (int descriptor, backtrace_error_callback error_callback, 97 | void *data) 98 | { 99 | if (close (descriptor) < 0) 100 | { 101 | error_callback (data, "close", errno); 102 | return 0; 103 | } 104 | return 1; 105 | } 106 | #endif 107 | -------------------------------------------------------------------------------- /Sources/CBacktrace/print.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* print.c -- Print the current backtrace. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #include "include/backtrace.h" 41 | #include "internal.h" 42 | 43 | /* Passed to callbacks. */ 44 | 45 | struct print_data 46 | { 47 | struct backtrace_state *state; 48 | FILE *f; 49 | }; 50 | 51 | /* Print one level of a backtrace. */ 52 | 53 | static int 54 | print_callback (void *data, uintptr_t pc, const char *filename, int lineno, 55 | const char *function) 56 | { 57 | struct print_data *pdata = (struct print_data *) data; 58 | 59 | fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n", 60 | (unsigned long) pc, 61 | function == NULL ? "???" : function, 62 | filename == NULL ? "???" : filename, 63 | lineno); 64 | return 0; 65 | } 66 | 67 | /* Print errors to stderr. */ 68 | 69 | static void 70 | error_callback (void *data, const char *msg, int errnum) 71 | { 72 | struct print_data *pdata = (struct print_data *) data; 73 | 74 | if (pdata->state->filename != NULL) 75 | fprintf (stderr, "%s: ", pdata->state->filename); 76 | fprintf (stderr, "libbacktrace: %s", msg); 77 | if (errnum > 0) 78 | fprintf (stderr, ": %s", strerror (errnum)); 79 | fputc ('\n', stderr); 80 | } 81 | 82 | /* Print a backtrace. */ 83 | 84 | void __attribute__((noinline)) 85 | backtrace_print (struct backtrace_state *state, int skip, FILE *f) 86 | { 87 | struct print_data data; 88 | 89 | data.state = state; 90 | data.f = f; 91 | backtrace_full (state, skip + 1, print_callback, error_callback, 92 | (void *) &data); 93 | } 94 | #endif 95 | -------------------------------------------------------------------------------- /Sources/CBacktrace/simple.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* simple.c -- The backtrace_simple function. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include "unwind.h" 37 | #include "include/backtrace.h" 38 | 39 | /* The simple_backtrace routine. */ 40 | 41 | /* Data passed through _Unwind_Backtrace. */ 42 | 43 | struct backtrace_simple_data 44 | { 45 | /* Number of frames to skip. */ 46 | int skip; 47 | /* Library state. */ 48 | struct backtrace_state *state; 49 | /* Callback routine. */ 50 | backtrace_simple_callback callback; 51 | /* Error callback routine. */ 52 | backtrace_error_callback error_callback; 53 | /* Data to pass to callback routine. */ 54 | void *data; 55 | /* Value to return from backtrace. */ 56 | int ret; 57 | }; 58 | 59 | /* Unwind library callback routine. This is passed to 60 | _Unwind_Backtrace. */ 61 | 62 | static _Unwind_Reason_Code 63 | simple_unwind (struct _Unwind_Context *context, void *vdata) 64 | { 65 | struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata; 66 | uintptr_t pc; 67 | int ip_before_insn = 0; 68 | 69 | #ifdef HAVE_GETIPINFO 70 | pc = _Unwind_GetIPInfo (context, &ip_before_insn); 71 | #else 72 | pc = _Unwind_GetIP (context); 73 | #endif 74 | 75 | if (bdata->skip > 0) 76 | { 77 | --bdata->skip; 78 | return _URC_NO_REASON; 79 | } 80 | 81 | if (!ip_before_insn) 82 | --pc; 83 | 84 | bdata->ret = bdata->callback (bdata->data, pc); 85 | 86 | if (bdata->ret != 0) 87 | return _URC_END_OF_STACK; 88 | 89 | return _URC_NO_REASON; 90 | } 91 | 92 | /* Get a simple stack backtrace. */ 93 | 94 | int __attribute__((noinline)) 95 | backtrace_simple (struct backtrace_state *state, int skip, 96 | backtrace_simple_callback callback, 97 | backtrace_error_callback error_callback, void *data) 98 | { 99 | struct backtrace_simple_data bdata; 100 | 101 | bdata.skip = skip + 1; 102 | bdata.state = state; 103 | bdata.callback = callback; 104 | bdata.error_callback = error_callback; 105 | bdata.data = data; 106 | bdata.ret = 0; 107 | _Unwind_Backtrace (simple_unwind, &bdata); 108 | return bdata.ret; 109 | } 110 | #endif 111 | -------------------------------------------------------------------------------- /Sources/CBacktrace/sort.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* sort.c -- Sort without allocating memory 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | 39 | #include "include/backtrace.h" 40 | #include "internal.h" 41 | 42 | /* The GNU glibc version of qsort allocates memory, which we must not 43 | do if we are invoked by a signal handler. So provide our own 44 | sort. */ 45 | 46 | static void 47 | swap (char *a, char *b, size_t size) 48 | { 49 | size_t i; 50 | 51 | for (i = 0; i < size; i++, a++, b++) 52 | { 53 | char t; 54 | 55 | t = *a; 56 | *a = *b; 57 | *b = t; 58 | } 59 | } 60 | 61 | void 62 | backtrace_qsort (void *basearg, size_t count, size_t size, 63 | int (*compar) (const void *, const void *)) 64 | { 65 | char *base = (char *) basearg; 66 | size_t i; 67 | size_t mid; 68 | 69 | tail_recurse: 70 | if (count < 2) 71 | return; 72 | 73 | /* The symbol table and DWARF tables, which is all we use this 74 | routine for, tend to be roughly sorted. Pick the middle element 75 | in the array as our pivot point, so that we are more likely to 76 | cut the array in half for each recursion step. */ 77 | swap (base, base + (count / 2) * size, size); 78 | 79 | mid = 0; 80 | for (i = 1; i < count; i++) 81 | { 82 | if ((*compar) (base, base + i * size) > 0) 83 | { 84 | ++mid; 85 | if (i != mid) 86 | swap (base + mid * size, base + i * size, size); 87 | } 88 | } 89 | 90 | if (mid > 0) 91 | swap (base, base + mid * size, size); 92 | 93 | /* Recurse with the smaller array, loop with the larger one. That 94 | ensures that our maximum stack depth is log count. */ 95 | if (2 * mid < count) 96 | { 97 | backtrace_qsort (base, mid, size, compar); 98 | base += (mid + 1) * size; 99 | count -= mid + 1; 100 | goto tail_recurse; 101 | } 102 | else 103 | { 104 | backtrace_qsort (base + (mid + 1) * size, count - (mid + 1), 105 | size, compar); 106 | count = mid; 107 | goto tail_recurse; 108 | } 109 | } 110 | #endif 111 | -------------------------------------------------------------------------------- /Sources/CBacktrace/state.c: -------------------------------------------------------------------------------- 1 | #ifdef __linux__ 2 | /* state.c -- Create the backtrace state. 3 | Copyright (C) 2012-2021 Free Software Foundation, Inc. 4 | Written by Ian Lance Taylor, Google. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | (1) Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | (3) The name of the author may not be used to 19 | endorse or promote products derived from this software without 20 | specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. */ 33 | 34 | #include "config.h" 35 | 36 | #include 37 | #include 38 | 39 | #include "include/backtrace.h" 40 | #include "backtrace-supported.h" 41 | #include "internal.h" 42 | 43 | /* Create the backtrace state. This will then be passed to all the 44 | other routines. */ 45 | 46 | struct backtrace_state * 47 | backtrace_create_state (const char *filename, int threaded, 48 | backtrace_error_callback error_callback, 49 | void *data) 50 | { 51 | struct backtrace_state init_state; 52 | struct backtrace_state *state; 53 | 54 | #ifndef HAVE_SYNC_FUNCTIONS 55 | if (threaded) 56 | { 57 | error_callback (data, "backtrace library does not support threads", 0); 58 | return NULL; 59 | } 60 | #endif 61 | 62 | memset (&init_state, 0, sizeof init_state); 63 | init_state.filename = filename; 64 | init_state.threaded = threaded; 65 | 66 | state = ((struct backtrace_state *) 67 | backtrace_alloc (&init_state, sizeof *state, error_callback, data)); 68 | if (state == NULL) 69 | return NULL; 70 | *state = init_state; 71 | 72 | return state; 73 | } 74 | #endif 75 | -------------------------------------------------------------------------------- /Sources/Sample/main.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the SwiftLinuxBacktrace open source project 4 | // 5 | // Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 6 | // Licensed under Apache License v2.0 7 | // 8 | // See LICENSE.txt for license information 9 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 10 | // 11 | // SPDX-License-Identifier: Apache-2.0 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | import Backtrace 16 | #if canImport(Darwin) 17 | import Darwin 18 | #elseif canImport(Glibc) 19 | import Glibc 20 | #elseif canImport(Musl) 21 | import Musl 22 | #endif 23 | 24 | #if swift(<5.9) || os(Windows) 25 | Backtrace.install() 26 | #endif 27 | 28 | func raiseSignal(_ signal: Int32) { 29 | raise(signal) 30 | } 31 | 32 | let reason = CommandLine.arguments.count == 2 ? CommandLine.arguments[1] : "unknown" 33 | switch reason.uppercased() { 34 | case "SIGILL": 35 | raiseSignal(SIGILL) 36 | case "SIGSEGV": 37 | raiseSignal(SIGSEGV) 38 | case "SIGBUS": 39 | raiseSignal(SIGBUS) 40 | case "SIGFPE": 41 | raiseSignal(SIGFPE) 42 | default: 43 | fatalError(reason) 44 | } 45 | -------------------------------------------------------------------------------- /Tests/BacktraceTests/BacktraceTests+XCTest.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the SwiftLinuxBacktrace open source project 4 | // 5 | // Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 6 | // Licensed under Apache License v2.0 7 | // 8 | // See LICENSE.txt for license information 9 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 10 | // 11 | // SPDX-License-Identifier: Apache-2.0 12 | // 13 | //===----------------------------------------------------------------------===// 14 | // 15 | // BacktraceTests+XCTest.swift 16 | // 17 | import XCTest 18 | 19 | /// 20 | /// NOTE: This file was generated by generate_linux_tests.rb 21 | /// 22 | /// Do NOT edit this file directly as it will be regenerated automatically when needed. 23 | /// 24 | 25 | extension BacktraceTests { 26 | public static var allTests: [(String, (BacktraceTests) -> () throws -> Void)] { 27 | return [ 28 | ("testFatalError", testFatalError), 29 | ("testSIGILL", testSIGILL), 30 | ("testSIGSEGV", testSIGSEGV), 31 | ("testSIGBUS", testSIGBUS), 32 | ("testSIGFPE", testSIGFPE), 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Tests/BacktraceTests/BacktraceTests.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the SwiftLinuxBacktrace open source project 4 | // 5 | // Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 6 | // Licensed under Apache License v2.0 7 | // 8 | // See LICENSE.txt for license information 9 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 10 | // 11 | // SPDX-License-Identifier: Apache-2.0 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | import XCTest 16 | 17 | public final class BacktraceTests: XCTestCase { 18 | func testFatalError() throws { 19 | #if !os(Linux) 20 | try XCTSkipIf(true, "test is only supported on Linux") 21 | #endif 22 | 23 | #if swift(>=5.9) 24 | try XCTSkipIf(true, "test is not supported on Swift 5.9") 25 | #endif 26 | 27 | let expectedError = UUID().uuidString 28 | let stderr = try runSample(reason: expectedError) 29 | print(stderr) 30 | 31 | XCTAssert(stderr.contains("Received signal 4. Backtrace:")) 32 | XCTAssert(stderr.contains("Current stack trace:"), "expected stanard error to include backtrace") 33 | XCTAssert(stderr.contains("Fatal error: \(expectedError)"), "expected stanard error to include error information") 34 | } 35 | 36 | func testSIGILL() throws { 37 | #if !os(Linux) 38 | try XCTSkipIf(true, "test is only supported on Linux") 39 | #endif 40 | 41 | #if swift(>=5.9) 42 | try XCTSkipIf(true, "test is not supported on Swift 5.9") 43 | #endif 44 | 45 | let stderr = try runSample(reason: "SIGILL") 46 | print(stderr) 47 | 48 | XCTAssert(stderr.contains("Received signal \(SIGILL). Backtrace:")) 49 | XCTAssert(stderr.contains("Sample.raiseSignal")) 50 | } 51 | 52 | func testSIGSEGV() throws { 53 | #if !os(Linux) 54 | try XCTSkipIf(true, "test is only supported on Linux") 55 | #endif 56 | 57 | #if swift(>=5.9) 58 | try XCTSkipIf(true, "test is not supported on Swift 5.9") 59 | #endif 60 | 61 | let stderr = try runSample(reason: "SIGSEGV") 62 | print(stderr) 63 | 64 | XCTAssert(stderr.contains("Received signal \(SIGSEGV). Backtrace:")) 65 | XCTAssert(stderr.contains("Sample.raiseSignal")) 66 | } 67 | 68 | func testSIGBUS() throws { 69 | #if !os(Linux) 70 | try XCTSkipIf(true, "test is only supported on Linux") 71 | #endif 72 | 73 | #if swift(>=5.9) 74 | try XCTSkipIf(true, "test is not supported on Swift 5.9") 75 | #endif 76 | 77 | let stderr = try runSample(reason: "SIGBUS") 78 | print(stderr) 79 | 80 | XCTAssert(stderr.contains("Received signal \(SIGBUS). Backtrace:")) 81 | XCTAssert(stderr.contains("Sample.raiseSignal")) 82 | } 83 | 84 | func testSIGFPE() throws { 85 | #if !os(Linux) 86 | try XCTSkipIf(true, "test is only supported on Linux") 87 | #endif 88 | 89 | #if swift(>=5.9) 90 | try XCTSkipIf(true, "test is not supported on Swift 5.9") 91 | #endif 92 | 93 | let stderr = try runSample(reason: "SIGFPE") 94 | print(stderr) 95 | 96 | XCTAssert(stderr.contains("Received signal \(SIGFPE). Backtrace:")) 97 | XCTAssert(stderr.contains("Sample.raiseSignal")) 98 | } 99 | 100 | func runSample(reason: String) throws -> String { 101 | let pipe = Pipe() 102 | let process = Process() 103 | process.executableURL = URL(fileURLWithPath: "/usr/bin/swift") 104 | process.arguments = ["run", "Sample", reason] 105 | process.standardError = pipe 106 | try process.run() 107 | process.waitUntilExit() 108 | return String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? "" 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the SwiftLinuxBacktrace open source project 4 | // 5 | // Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 6 | // Licensed under Apache License v2.0 7 | // 8 | // See LICENSE.txt for license information 9 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 10 | // 11 | // SPDX-License-Identifier: Apache-2.0 12 | // 13 | //===----------------------------------------------------------------------===// 14 | // 15 | // LinuxMain.swift 16 | // 17 | import XCTest 18 | 19 | /// 20 | /// NOTE: This file was generated by generate_linux_tests.rb 21 | /// 22 | /// Do NOT edit this file directly as it will be regenerated automatically when needed. 23 | /// 24 | 25 | #if os(Linux) || os(FreeBSD) 26 | import BacktraceTests 27 | 28 | XCTMain([ 29 | testCase(BacktraceTests.allTests), 30 | ]) 31 | #endif 32 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG swift_version=5.0 2 | ARG ubuntu_version=bionic 3 | ARG base_image=swift:$swift_version-$ubuntu_version 4 | FROM $base_image 5 | # needed to do again after FROM due to docker limitation 6 | ARG swift_version 7 | ARG ubuntu_version 8 | 9 | # set as UTF-8 10 | RUN apt-get update && apt-get install -y locales locales-all 11 | ENV LC_ALL en_US.UTF-8 12 | ENV LANG en_US.UTF-8 13 | ENV LANGUAGE en_US.UTF-8 14 | 15 | # dependencies 16 | RUN apt-get update && apt-get install -y wget 17 | RUN apt-get update && apt-get install -y lsof dnsutils netcat-openbsd net-tools curl jq # used by integration tests 18 | 19 | # ruby and jazzy for docs generation 20 | RUN apt-get update && apt-get install -y ruby ruby-dev libsqlite3-dev build-essential 21 | # jazzy no longer works on older version of ubuntu as ruby is too old. 22 | RUN if [ "${ubuntu_version}" = "jammy" ] ; then echo "gem: --no-document" > ~/.gemrc ; fi 23 | RUN if [ "${ubuntu_version}" = "jammy" ] ; then gem install jazzy ; fi 24 | 25 | # tools 26 | RUN mkdir -p $HOME/.tools 27 | RUN echo 'export PATH="$HOME/.tools:$PATH"' >> $HOME/.profile 28 | 29 | # swiftformat (until part of the toolchain) 30 | 31 | ARG swiftformat_version=0.44.6 32 | RUN git clone --branch $swiftformat_version --depth 1 https://github.com/nicklockwood/SwiftFormat $HOME/.tools/swift-format 33 | RUN cd $HOME/.tools/swift-format && swift build -c release 34 | RUN ln -s $HOME/.tools/swift-format/.build/release/swiftformat $HOME/.tools/swiftformat 35 | -------------------------------------------------------------------------------- /docker/docker-compose.1604.51.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:16.04-5.1 7 | build: 8 | args: 9 | ubuntu_version: "xenial" 10 | swift_version: "5.1" 11 | 12 | test: 13 | image: swift-linux-backtrace:16.04-5.1 14 | environment: 15 | - SANITIZER_ARG=--sanitize=thread 16 | 17 | shell: 18 | image: swift-linux-backtrace:16.04-5.1 19 | -------------------------------------------------------------------------------- /docker/docker-compose.1804.50.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:18.04-5.0 7 | build: 8 | args: 9 | ubuntu_version: "bionic" 10 | swift_version: "5.0" 11 | 12 | test: 13 | image: swift-linux-backtrace:18.04-5.0 14 | 15 | shell: 16 | image: swift-linux-backtrace:18.04-5.0 17 | -------------------------------------------------------------------------------- /docker/docker-compose.1804.52.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:18.04-5.2 7 | build: 8 | args: 9 | ubuntu_version: "bionic" 10 | swift_version: "5.2" 11 | 12 | test: 13 | image: swift-linux-backtrace:18.04-5.2 14 | 15 | shell: 16 | image: swift-linux-backtrace:18.04-5.2 17 | -------------------------------------------------------------------------------- /docker/docker-compose.1804.53.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:18.04-5.3 7 | build: 8 | args: 9 | ubuntu_version: "bionic" 10 | swift_version: "5.3" 11 | 12 | test: 13 | image: swift-linux-backtrace:18.04-5.3 14 | 15 | shell: 16 | image: swift-linux-backtrace:18.04-5.3 17 | -------------------------------------------------------------------------------- /docker/docker-compose.2004.54.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:20.04-5.4 7 | build: 8 | args: 9 | ubuntu_version: "focal" 10 | swift_version: "5.4" 11 | 12 | test: 13 | image: swift-linux-backtrace:20.04-5.4 14 | 15 | shell: 16 | image: swift-linux-backtrace:20.04-5.4 17 | -------------------------------------------------------------------------------- /docker/docker-compose.2004.55.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:20.04-5.5 7 | build: 8 | args: 9 | ubuntu_version: "focal" 10 | swift_version: "5.5" 11 | 12 | test: 13 | image: swift-linux-backtrace:20.04-5.5 14 | 15 | shell: 16 | image: swift-linux-backtrace:20.04-5.5 17 | -------------------------------------------------------------------------------- /docker/docker-compose.2004.56.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:20.04-5.6 7 | build: 8 | args: 9 | ubuntu_version: "focal" 10 | swift_version: "5.6" 11 | 12 | test: 13 | image: swift-linux-backtrace:20.04-5.6 14 | environment: 15 | - FORCE_TEST_DISCOVERY=--enable-test-discovery 16 | 17 | shell: 18 | image: swift-linux-backtrace:20.04-5.6 19 | -------------------------------------------------------------------------------- /docker/docker-compose.2004.57.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:20.04-5.7 7 | build: 8 | args: 9 | ubuntu_version: "focal" 10 | swift_version: "5.7" 11 | 12 | test: 13 | image: swift-linux-backtrace:20.04-5.7 14 | environment: 15 | - FORCE_TEST_DISCOVERY=--enable-test-discovery 16 | 17 | shell: 18 | image: swift-linux-backtrace:20.04-5.7 19 | -------------------------------------------------------------------------------- /docker/docker-compose.2204.510.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:22.04-5.10 7 | build: 8 | args: 9 | base_image: "swiftlang/swift:nightly-5.10-jammy" 10 | 11 | test: 12 | image: swift-linux-backtrace:22.04-5.10 13 | environment: 14 | - FORCE_TEST_DISCOVERY=--enable-test-discovery 15 | 16 | shell: 17 | image: swift-linux-backtrace:22.04-5.10 18 | -------------------------------------------------------------------------------- /docker/docker-compose.2204.58.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:22.04-5.8 7 | build: 8 | args: 9 | ubuntu_version: "jammy" 10 | swift_version: "5.8" 11 | 12 | test: 13 | image: swift-linux-backtrace:22.04-5.8 14 | environment: 15 | - FORCE_TEST_DISCOVERY=--enable-test-discovery 16 | 17 | shell: 18 | image: swift-linux-backtrace:22.04-5.8 19 | -------------------------------------------------------------------------------- /docker/docker-compose.2204.59.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:22.04-5.9 7 | build: 8 | args: 9 | ubuntu_version: "jammy" 10 | swift_version: "5.9" 11 | 12 | test: 13 | image: swift-linux-backtrace:22.04-5.9 14 | environment: 15 | - FORCE_TEST_DISCOVERY=--enable-test-discovery 16 | 17 | shell: 18 | image: swift-linux-backtrace:22.04-5.9 19 | -------------------------------------------------------------------------------- /docker/docker-compose.2204.main.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | runtime-setup: 6 | image: swift-linux-backtrace:22.04-main 7 | build: 8 | args: 9 | base_image: "swiftlang/swift:nightly-main-jammy" 10 | 11 | test: 12 | image: swift-linux-backtrace:22.04-main 13 | environment: 14 | - FORCE_TEST_DISCOVERY=--enable-test-discovery 15 | 16 | shell: 17 | image: swift-linux-backtrace:22.04-main 18 | -------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # this file is not designed to be run directly 2 | # instead, use the docker-compose.. files 3 | # eg docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.1804.50.yaml run test 4 | version: "3" 5 | 6 | services: 7 | 8 | runtime-setup: 9 | image: swift-linux-backtrace:default 10 | build: 11 | context: . 12 | dockerfile: Dockerfile 13 | 14 | common: &common 15 | image: swift-linux-backtrace:default 16 | depends_on: [runtime-setup] 17 | volumes: 18 | - ~/.ssh:/root/.ssh 19 | - ..:/code:z 20 | working_dir: /code 21 | cap_drop: 22 | - CAP_NET_RAW 23 | - CAP_NET_BIND_SERVICE 24 | 25 | soundness: 26 | <<: *common 27 | command: /bin/bash -cl "./scripts/soundness.sh" 28 | 29 | test: 30 | <<: *common 31 | command: /bin/bash -cl "swift test -c release -Xswiftc -g -Xswiftc -warnings-as-errors $${FORCE_TEST_DISCOVERY-} $${SANITIZER_ARG-}" 32 | 33 | # util 34 | 35 | shell: 36 | <<: *common 37 | entrypoint: /bin/bash -l 38 | -------------------------------------------------------------------------------- /scripts/generate_contributors_list.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##===----------------------------------------------------------------------===## 3 | ## 4 | ## This source file is part of the SwiftLinuxBacktrace open source project 5 | ## 6 | ## Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 7 | ## Licensed under Apache License v2.0 8 | ## 9 | ## See LICENSE.txt for license information 10 | ## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 11 | ## 12 | ## SPDX-License-Identifier: Apache-2.0 13 | ## 14 | ##===----------------------------------------------------------------------===## 15 | 16 | set -eu 17 | here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 18 | contributors=$( cd "$here"/.. && git shortlog -es | cut -f2 | sed 's/^/- /' ) 19 | 20 | cat > "$here/../CONTRIBUTORS.txt" <<- EOF 21 | For the purpose of tracking copyright, this is the list of individuals and 22 | organizations who have contributed source code to SwiftLinuxBacktrace. 23 | 24 | For employees of an organization/company where the copyright of work done 25 | by employees of that company is held by the company itself, only the company 26 | needs to be listed here. 27 | 28 | ## COPYRIGHT HOLDERS 29 | 30 | - Apple Inc. (all contributors with '@apple.com') 31 | 32 | ### Contributors 33 | 34 | $contributors 35 | 36 | **Updating this list** 37 | 38 | 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\` 39 | EOF 40 | -------------------------------------------------------------------------------- /scripts/generate_linux_tests.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # 4 | # process_test_files.rb 5 | # 6 | # Copyright 2016 Tony Stone 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | # Created by Tony Stone on 5/4/16. 21 | # 22 | require 'getoptlong' 23 | require 'fileutils' 24 | require 'pathname' 25 | 26 | include FileUtils 27 | 28 | # 29 | # This ruby script will auto generate LinuxMain.swift and the +XCTest.swift extension files for Swift Package Manager on Linux platforms. 30 | # 31 | # See https://github.com/apple/swift-corelibs-xctest/blob/master/Documentation/Linux.md 32 | # 33 | def header(fileName) 34 | string = <<-eos 35 | //===----------------------------------------------------------------------===// 36 | // 37 | // This source file is part of the SwiftLinuxBacktrace open source project 38 | // 39 | // Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 40 | // Licensed under Apache License v2.0 41 | // 42 | // See LICENSE.txt for license information 43 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 44 | // 45 | // SPDX-License-Identifier: Apache-2.0 46 | // 47 | //===----------------------------------------------------------------------===// 48 | // 49 | // 50 | // 51 | import XCTest 52 | 53 | /// 54 | /// NOTE: This file was generated by generate_linux_tests.rb 55 | /// 56 | /// Do NOT edit this file directly as it will be regenerated automatically when needed. 57 | /// 58 | eos 59 | 60 | string 61 | .sub('', File.basename(fileName)) 62 | .sub('', Time.now.to_s) 63 | end 64 | 65 | def createExtensionFile(fileName, classes) 66 | extensionFile = fileName.sub! '.swift', '+XCTest.swift' 67 | print 'Creating file: ' + extensionFile + "\n" 68 | 69 | File.open(extensionFile, 'w') do |file| 70 | file.write header(extensionFile) 71 | file.write "\n" 72 | 73 | for classArray in classes 74 | file.write 'extension ' + classArray[0] + " {\n" 75 | file.write ' public static var allTests: [(String, (' + classArray[0] + ") -> () throws -> Void)] {\n" 76 | file.write " return [\n" 77 | 78 | for funcName in classArray[1] 79 | file.write ' ("' + funcName + '", ' + funcName + "),\n" 80 | end 81 | 82 | file.write " ]\n" 83 | file.write " }\n" 84 | file.write "}\n" 85 | end 86 | end 87 | end 88 | 89 | def createLinuxMain(testsDirectory, allTestSubDirectories, files) 90 | fileName = testsDirectory + '/LinuxMain.swift' 91 | print 'Creating file: ' + fileName + "\n" 92 | 93 | File.open(fileName, 'w') do |file| 94 | file.write header(fileName) 95 | file.write "\n" 96 | 97 | file.write "#if os(Linux) || os(FreeBSD)\n" 98 | for testSubDirectory in allTestSubDirectories.sort { |x, y| x <=> y } 99 | file.write 'import ' + testSubDirectory + "\n" 100 | end 101 | file.write "\n" 102 | file.write "XCTMain([\n" 103 | 104 | testCases = [] 105 | for classes in files 106 | for classArray in classes 107 | testCases << classArray[0] 108 | end 109 | end 110 | 111 | for testCase in testCases.sort { |x, y| x <=> y } 112 | file.write ' testCase(' + testCase + ".allTests),\n" 113 | end 114 | file.write "])\n" 115 | file.write "#endif\n" 116 | end 117 | end 118 | 119 | def parseSourceFile(fileName) 120 | puts 'Parsing file: ' + fileName + "\n" 121 | 122 | classes = [] 123 | currentClass = nil 124 | inIfLinux = false 125 | inElse = false 126 | ignore = false 127 | 128 | # 129 | # Read the file line by line 130 | # and parse to find the class 131 | # names and func names 132 | # 133 | File.readlines(fileName).each do |line| 134 | if inIfLinux 135 | if /\#else/.match(line) 136 | inElse = true 137 | ignore = true 138 | else 139 | if /\#end/.match(line) 140 | inElse = false 141 | inIfLinux = false 142 | ignore = false 143 | end 144 | end 145 | else 146 | if /\#if[ \t]+os\(Linux\)/.match(line) 147 | inIfLinux = true 148 | ignore = false 149 | end 150 | end 151 | 152 | next if ignore 153 | # Match class or func 154 | match = line[/class[ \t]+[a-zA-Z0-9_]*(?=[ \t]*:[ \t]*XCTestCase)|func[ \t]+test[a-zA-Z0-9_]*(?=[ \t]*\(\))/, 0] 155 | if match 156 | 157 | if match[/class/, 0] == 'class' 158 | className = match.sub(/^class[ \t]+/, '') 159 | # 160 | # Create a new class / func structure 161 | # and add it to the classes array. 162 | # 163 | currentClass = [className, []] 164 | classes << currentClass 165 | else # Must be a func 166 | funcName = match.sub(/^func[ \t]+/, '') 167 | # 168 | # Add each func name the the class / func 169 | # structure created above. 170 | # 171 | currentClass[1] << funcName 172 | end 173 | end 174 | end 175 | classes 176 | end 177 | 178 | # 179 | # Main routine 180 | # 181 | # 182 | 183 | testsDirectory = 'Tests' 184 | 185 | options = GetoptLong.new(['--tests-dir', GetoptLong::OPTIONAL_ARGUMENT]) 186 | options.quiet = true 187 | 188 | begin 189 | options.each do |option, value| 190 | case option 191 | when '--tests-dir' 192 | testsDirectory = value 193 | end 194 | end 195 | rescue GetoptLong::InvalidOption 196 | end 197 | 198 | allTestSubDirectories = [] 199 | allFiles = [] 200 | 201 | Dir[testsDirectory + '/*'].each do |subDirectory| 202 | next unless File.directory?(subDirectory) 203 | directoryHasClasses = false 204 | Dir[subDirectory + '/*Test{s,}.swift'].each do |fileName| 205 | next unless File.file? fileName 206 | fileClasses = parseSourceFile(fileName) 207 | 208 | # 209 | # If there are classes in the 210 | # test source file, create an extension 211 | # file for it. 212 | # 213 | next unless fileClasses.count > 0 214 | createExtensionFile(fileName, fileClasses) 215 | directoryHasClasses = true 216 | allFiles << fileClasses 217 | end 218 | 219 | if directoryHasClasses 220 | allTestSubDirectories << Pathname.new(subDirectory).split.last.to_s 221 | end 222 | end 223 | 224 | # 225 | # Last step is the create a LinuxMain.swift file that 226 | # references all the classes and funcs in the source files. 227 | # 228 | if allFiles.count > 0 229 | createLinuxMain(testsDirectory, allTestSubDirectories, allFiles) 230 | end 231 | # eof 232 | -------------------------------------------------------------------------------- /scripts/preview_docc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##===----------------------------------------------------------------------===## 3 | ## 4 | ## This source file is part of the SwiftLinuxBacktrace open source project 5 | ## 6 | ## Copyright (c) 2022 Apple Inc. and the SwiftLinuxBacktrace project authors 7 | ## Licensed under Apache License v2.0 8 | ## 9 | ## See LICENSE.txt for license information 10 | ## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 11 | ## 12 | ## SPDX-License-Identifier: Apache-2.0 13 | ## 14 | ##===----------------------------------------------------------------------===## 15 | 16 | ##===----------------------------------------------------------------------===## 17 | ## 18 | ## This source file is part of the Swift Distributed Actors open source project 19 | ## 20 | ## Copyright (c) 2018-2019 Apple Inc. and the Swift Distributed Actors project authors 21 | ## Licensed under Apache License v2.0 22 | ## 23 | ## See LICENSE.txt for license information 24 | ## See CONTRIBUTORS.md for the list of Swift Distributed Actors project authors 25 | ## 26 | ## SPDX-License-Identifier: Apache-2.0 27 | ## 28 | ##===----------------------------------------------------------------------===## 29 | 30 | swift package --disable-sandbox preview-documentation --target $1 31 | -------------------------------------------------------------------------------- /scripts/soundness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##===----------------------------------------------------------------------===## 3 | ## 4 | ## This source file is part of the SwiftLinuxBacktrace open source project 5 | ## 6 | ## Copyright (c) 2017-2022 Apple Inc. and the SwiftLinuxBacktrace project authors 7 | ## Licensed under Apache License v2.0 8 | ## 9 | ## See LICENSE.txt for license information 10 | ## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 11 | ## 12 | ## SPDX-License-Identifier: Apache-2.0 13 | ## 14 | ##===----------------------------------------------------------------------===## 15 | 16 | set -eu 17 | 18 | here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 19 | 20 | function replace_acceptable_years() { 21 | # this needs to replace all acceptable forms with 'YEARS' 22 | sed -e 's/20[12][78901]-20[12][89012]/YEARS/' -e 's/2019/YEARS/' -e 's/202[012]/YEARS/' 23 | } 24 | 25 | printf "=> Checking linux tests... " 26 | FIRST_OUT="$(git status --porcelain)" 27 | ruby "$here/../scripts/generate_linux_tests.rb" > /dev/null 28 | SECOND_OUT="$(git status --porcelain)" 29 | if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then 30 | printf "\033[0;31mmissing changes!\033[0m\n" 31 | git --no-pager diff 32 | exit 1 33 | else 34 | printf "\033[0;32mokay.\033[0m\n" 35 | fi 36 | 37 | printf "=> Checking format... " 38 | FIRST_OUT="$(git status --porcelain)" 39 | swiftformat . > /dev/null 2>&1 40 | SECOND_OUT="$(git status --porcelain)" 41 | if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then 42 | printf "\033[0;31mformatting issues!\033[0m\n" 43 | git --no-pager diff 44 | exit 1 45 | else 46 | printf "\033[0;32mokay.\033[0m\n" 47 | fi 48 | 49 | printf "=> Checking license headers\n" 50 | tmp=$(mktemp /tmp/.swift-aws-lambda-sanity_XXXXXX) 51 | 52 | for language in swift-or-c bash dtrace; do 53 | printf " * $language... " 54 | declare -a matching_files 55 | declare -a exceptions 56 | expections=( ) 57 | matching_files=( -name '*' ) 58 | case "$language" in 59 | swift-or-c) 60 | exceptions=( -name Package.swift -o -name 'Package@*.swift' -o -path './Sources/CBacktrace/*' ) 61 | matching_files=( -name '*.swift' -o -name '*.c' -o -name '*.h' ) 62 | cat > "$tmp" <<"EOF" 63 | //===----------------------------------------------------------------------===// 64 | // 65 | // This source file is part of the SwiftLinuxBacktrace open source project 66 | // 67 | // Copyright (c) YEARS Apple Inc. and the SwiftLinuxBacktrace project authors 68 | // Licensed under Apache License v2.0 69 | // 70 | // See LICENSE.txt for license information 71 | // See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 72 | // 73 | // SPDX-License-Identifier: Apache-2.0 74 | // 75 | //===----------------------------------------------------------------------===// 76 | EOF 77 | ;; 78 | bash) 79 | matching_files=( -name '*.sh' ) 80 | cat > "$tmp" <<"EOF" 81 | #!/bin/bash 82 | ##===----------------------------------------------------------------------===## 83 | ## 84 | ## This source file is part of the SwiftLinuxBacktrace open source project 85 | ## 86 | ## Copyright (c) YEARS Apple Inc. and the SwiftLinuxBacktrace project authors 87 | ## Licensed under Apache License v2.0 88 | ## 89 | ## See LICENSE.txt for license information 90 | ## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 91 | ## 92 | ## SPDX-License-Identifier: Apache-2.0 93 | ## 94 | ##===----------------------------------------------------------------------===## 95 | EOF 96 | ;; 97 | dtrace) 98 | matching_files=( -name '*.d' ) 99 | cat > "$tmp" <<"EOF" 100 | #!/usr/sbin/dtrace -q -s 101 | /*===----------------------------------------------------------------------===* 102 | * 103 | * This source file is part of the SwiftLinuxBacktrace open source project 104 | * 105 | * Copyright (c) YEARS Apple Inc. and the SwiftLinuxBacktrace project authors 106 | * Licensed under Apache License v2.0 107 | * 108 | * See LICENSE.txt for license information 109 | * See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 110 | * 111 | * SPDX-License-Identifier: Apache-2.0 112 | * 113 | *===----------------------------------------------------------------------===*/ 114 | EOF 115 | ;; 116 | *) 117 | echo >&2 "ERROR: unknown language '$language'" 118 | ;; 119 | esac 120 | 121 | expected_lines=$(cat "$tmp" | wc -l) 122 | expected_sha=$(cat "$tmp" | shasum) 123 | 124 | ( 125 | cd "$here/.." 126 | find . \ 127 | \( \! -path './.build/*' -a \ 128 | \( "${matching_files[@]}" \) -a \ 129 | \( \! \( "${exceptions[@]}" \) \) \) | while read line; do 130 | if [[ "$(cat "$line" | replace_acceptable_years | head -n $expected_lines | shasum)" != "$expected_sha" ]]; then 131 | printf "\033[0;31mmissing headers in file '$line'!\033[0m\n" 132 | diff -u <(cat "$line" | replace_acceptable_years | head -n $expected_lines) "$tmp" 133 | exit 1 134 | fi 135 | done 136 | printf "\033[0;32mokay.\033[0m\n" 137 | ) 138 | done 139 | 140 | rm "$tmp" 141 | -------------------------------------------------------------------------------- /scripts/vendor-libbacktrace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##===----------------------------------------------------------------------===## 3 | ## 4 | ## This source file is part of the SwiftLinuxBacktrace open source project 5 | ## 6 | ## Copyright (c) 2019-2020 Apple Inc. and the SwiftLinuxBacktrace project authors 7 | ## Licensed under Apache License v2.0 8 | ## 9 | ## See LICENSE.txt for license information 10 | ## See CONTRIBUTORS.txt for the list of SwiftLinuxBacktrace project authors 11 | ## 12 | ## SPDX-License-Identifier: Apache-2.0 13 | ## 14 | ##===----------------------------------------------------------------------===## 15 | 16 | #!/bin/bash 17 | 18 | # This script creates a vendored copy of libbacktrace that is 19 | # suitable for building with the Swift Package Manager. 20 | # 21 | # Usage: 22 | # 1. Run this script in the package root. It will place 23 | # a local copy of the libbacktrace sources in Sources/CBacktrace. 24 | # Any prior contents of Sources/CBacktrace will be deleted. 25 | 26 | set -eou pipefail 27 | 28 | if [ "$(uname -s)" != "Linux" ] 29 | then 30 | echo "This script may only be run on Linux" 31 | exit 1 32 | fi 33 | 34 | HERE=$(pwd) 35 | DSTROOT=Sources/CBacktrace 36 | TMPDIR=$(mktemp -d /tmp/.workingXXXXXX) 37 | SRCROOT="${TMPDIR}/src/libbacktrace" 38 | 39 | echo "REMOVING any previously-vendored libbacktrace code" 40 | rm -rf "${DSTROOT:?}/"* 41 | 42 | echo "CLONING libbacktrace" 43 | mkdir -p "$SRCROOT" 44 | git clone https://github.com/ianlancetaylor/libbacktrace.git "$SRCROOT" 45 | echo "CLONED libbacktrace" 46 | 47 | echo "CONFIGURING libbacktrace" 48 | cd "$SRCROOT" 49 | ./configure > configure_log.txt 2>&1 50 | cd "$HERE" 51 | 52 | PATTERNS=( 53 | '*.c' 54 | '*.h' 55 | 'LICENSE' 56 | ) 57 | 58 | for pattern in "${PATTERNS[@]}" 59 | do 60 | echo "COPYING $pattern" 61 | cp "$SRCROOT"/$pattern "$DSTROOT" 62 | done 63 | 64 | EXCLUDES=( 65 | '*test*' 66 | 'nounwind.c' 67 | 'pecoff.c' 68 | 'read.c' 69 | 'unknown.c' 70 | 'xcoff.c' 71 | 'macho.c' 72 | 'alloc.c' 73 | 'allocfail.c' 74 | 'instrumented_alloc.c' 75 | ) 76 | 77 | for exclude in "${EXCLUDES[@]}" 78 | do 79 | echo "EXCLUDING $exclude" 80 | find $DSTROOT -name "$exclude" -exec rm -rf {} \; 81 | done 82 | 83 | echo "MOVING backtrace.h" 84 | mkdir -p "$DSTROOT/include" 85 | mv "$DSTROOT/backtrace.h" "$DSTROOT/include" 86 | 87 | echo "REPLACING references to \"backtrace.h\" with \"include/backtrace.h\"" 88 | find $DSTROOT -name "*.[ch]" -print0 | xargs -0 sed -i -e 's#"backtrace.h"#"include/backtrace.h"#g' 89 | 90 | echo "ADDING preprocessor conditionals" 91 | find $DSTROOT -name "*.[ch]" -print0 | xargs -0 sed -i -e '1i#ifdef __linux__' -e '$a#endif' 92 | 93 | echo "DONE" 94 | --------------------------------------------------------------------------------