[Backtracing] Updates following review.

Added some explanatory text to the Compact Backtrace Format
documentation, and also to the `CMakeLists.txt` for the runtime.

Tweaked the conversions for `Backtrace.Address` to truncate, which
should result in reasonable behaviour for negative fixed-width
integers.

Use a constant for the ASCII values for `/` and `\` in the Compact
Image Format encoder/decoder.

Make the TSD key for `ElfImageCache` non-optional, and call
`fatalError()` if we don't get one.

rdar://124913332
This commit is contained in:
Alastair Houghton
2025-01-27 17:22:39 +00:00
parent c9c5dc0de1
commit 26d0e49764
5 changed files with 28 additions and 17 deletions

View File

@@ -57,6 +57,10 @@ The following instructions are currently defined
| `1000xxxx` | `rep` | Repeat the previous frame |
| `1xxxxxxx` | reserved | Reserved for future expansion |
If the bit labelled `a` is set, it means that the address computation
is absolute rather than being relative to the previously computed
address.
### `end`/`trunc`
#### Encoding

View File

@@ -148,13 +148,13 @@ extension Backtrace.Address {
return T(0)
case let .sixteenBit(addr):
guard T.bitWidth >= 16 else { return nil }
return T(addr)
return T(truncatingIfNeeded: addr)
case let .thirtyTwoBit(addr):
guard T.bitWidth >= 32 else { return nil }
return T(addr)
return T(truncatingIfNeeded: addr)
case let .sixtyFourBit(addr):
guard T.bitWidth >= 64 else { return nil }
return T(addr)
return T(truncatingIfNeeded: addr)
}
}
}
@@ -204,11 +204,11 @@ extension Backtrace.Address {
public init?<T: FixedWidthInteger>(_ value: T) {
switch T.bitWidth {
case 16:
self.init(UInt16(value))
self.init(UInt16(truncatingIfNeeded: value))
case 32:
self.init(UInt32(value))
self.init(UInt32(truncatingIfNeeded: value))
case 64:
self.init(UInt64(value))
self.init(UInt64(truncatingIfNeeded: value))
default:
return nil
}

View File

@@ -16,6 +16,9 @@
import Swift
private let slash = UInt8(ascii: "/")
private let backslash = UInt8(ascii: "\\")
@_spi(Internal)
public enum CompactImageMapFormat {
@@ -58,7 +61,7 @@ public enum CompactImageMapFormat {
while pos < end {
let ch = str[pos]
if pos > base && (ch == 0x2f || ch == 0x5c) {
if pos > base && (ch == slash || ch == backslash) {
let range = base..<pos
let prefix = String(str[range])!
body(prefix)
@@ -179,7 +182,8 @@ public enum CompactImageMapFormat {
guard let char = iterator.next() else {
return nil
}
if base + n > stringBase! && (char == 0x2f || char == 0x5c) {
if base + n > stringBase! && (char == slash
|| char == backslash) {
let prefix = String(decoding: resultBytes[stringBase!..<base+n],
as: UTF8.self)
#if DEBUG_COMPACT_IMAGE_MAP
@@ -226,11 +230,11 @@ public enum CompactImageMapFormat {
print("framewk version='\(versionChar)' name='\(name)'")
#endif
resultBytes.append(0x2f) // '/'
resultBytes.append(slash)
resultBytes.append(contentsOf: nameBytes)
resultBytes.append(contentsOf: ".framework/Versions/".utf8)
resultBytes.append(version)
resultBytes.append(0x2f)
resultBytes.append(slash)
resultBytes.append(contentsOf: nameBytes)
return String(decoding: resultBytes, as: UTF8.self)
@@ -383,7 +387,7 @@ public enum CompactImageMapFormat {
// Extract the name from the path
if let path = path {
if let lastSlashNdx = path.utf8.lastIndex(
where: { $0 == 0x2f || $0 == 0x5c }
where: { $0 == slash || $0 == backslash }
) {
let nameNdx = path.index(after: lastSlashNdx)
@@ -726,7 +730,7 @@ public enum CompactImageMapFormat {
version = remainingPath[verNdx]
let slashNdx = remainingPath.index(after: verNdx)
if remainingPath[slashNdx] == 0x2f {
if remainingPath[slashNdx] == slash {
let nameNdx = remainingPath.index(after: slashNdx)
if remainingPath[nameNdx...].elementsEqual(name.utf8) {
self.remainingPath = remainingPath[nameNdx...]

View File

@@ -66,7 +66,7 @@ final class ElfImageCache {
return nil
}
private static var key: pthread_key_t? = {
private static var key: pthread_key_t = {
var theKey = pthread_key_t()
let err = pthread_key_create(
&theKey,
@@ -78,15 +78,15 @@ final class ElfImageCache {
}
)
if err != 0 {
return nil
fatalError("Unable to create TSD key for ElfImageCache")
}
return theKey
}()
static var threadLocal: ElfImageCache {
guard let rawPtr = pthread_getspecific(key!) else {
guard let rawPtr = pthread_getspecific(key) else {
let cache = Unmanaged<ElfImageCache>.passRetained(ElfImageCache())
pthread_setspecific(key!, cache.toOpaque())
pthread_setspecific(key, cache.toOpaque())
return cache.takeUnretainedValue()
}
let cache = Unmanaged<ElfImageCache>.fromOpaque(rawPtr)

View File

@@ -144,6 +144,10 @@ foreach(sdk ${SWIFT_SDKS})
endif()
endforeach()
# In modern CMake, we would be able to use the previous name `swiftRuntime`
# without clashing with the `Runtime` module, but the current build system
# is architected in such a way that we had to rename this to `swiftRuntimeCore`
# in order to avoid a clash with the new Swift module.
add_swift_target_library(swiftRuntimeCore OBJECT_LIBRARY
${swift_runtime_sources}
${swift_runtime_objc_sources}
@@ -323,4 +327,3 @@ if(static_binary_lnk_file_list)
add_dependencies(stdlib ${static_binary_lnk_file_list})
add_custom_target(static_binary_magic ALL DEPENDS ${static_binary_lnk_file_list})
endif()