Skip to content

Commit 5626571

Browse files
committed
apply code review feedback
1 parent 9db938e commit 5626571

File tree

6 files changed

+65
-51
lines changed

6 files changed

+65
-51
lines changed

include/swift/Runtime/Runtime.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ namespace runtime {
3737
namespace mangling {
3838
#endif
3939

40-
SWIFT_RUNTIME_STDLIB_SPI
41-
char * _swift_runtime_demangle(
42-
const char *mangledName,
43-
size_t mangledNameLength,
44-
char *outputBuffer,
45-
size_t *outputBufferSize,
46-
uint32_t flags
47-
);
40+
SWIFT_RUNTIME_STDLIB_SPI
41+
char * _swift_runtime_demangle(
42+
const char *mangledName,
43+
size_t mangledNameLength,
44+
char *outputBuffer,
45+
size_t *outputBufferSize,
46+
uint32_t flags
47+
);
4848

4949
#ifdef __cplusplus
5050
} // namespace mangling

stdlib/public/RuntimeModule/Mangling.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal import BacktracingImpl.Runtime
2929

3030
// - MARK: Demangling
3131

32-
/// Given a mangled Swift symbol, demangle it into a human readable format.
32+
/// Given a mangled Swift, or C++, symbol, demangle it into a human readable format.
3333
///
3434
/// If the provided bytes are not a valid mangled swift name, the output span will be initialized with zero elements.
3535
/// If mangling succeeds the output span will contain the resulting demangled string.
@@ -52,6 +52,8 @@ internal import BacktracingImpl.Runtime
5252
/// ├─────────────────────╫────────┤
5353
/// │ Swift 5+ ║ $s │
5454
/// └─────────────────────╨────────┘
55+
///
56+
/// This function also attempts to demangle C++ symbols starting with `_Z`.
5557
///
5658
/// - Parameters:
5759
/// - mangledName: A mangled Swift symbol.
@@ -62,7 +64,7 @@ internal import BacktracingImpl.Runtime
6264
public func demangle(_ mangledName: String) -> String? {
6365
var length: size_t = 0
6466

65-
let demangled: UnsafeMutablePointer<Int8>? = _swift_runtime_demangle(
67+
let demangled: UnsafeMutablePointer<CChar>? = _swift_runtime_demangle(
6668
mangledName, mangledName.utf8.count,
6769
nil, &length,
6870
/*flags=*/0

stdlib/public/RuntimeModule/SymbolicatedBacktrace.swift

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -202,28 +202,23 @@ public struct SymbolicatedBacktrace: CustomStringConvertible {
202202

203203
/// Demangle the raw name, if possible.
204204
private func demangleRawName() -> String {
205-
if #available(SwiftStdlib 6.3, *) {
206-
// Reuse the public API demangle() when available
207-
return demangle(rawName) ?? rawName
208-
} else {
209-
// Fallback to backtrace entrypoint to the demangler.
210-
var length: size_t = 0
211-
if let demangled = _swift_backtrace_demangle(rawName, rawName.utf8.count, nil, &length) {
212-
defer { free(demangled) }
213-
214-
// length is the size of the buffer that was allocated, *not* the
215-
// length of the string.
216-
let stringLen = strlen(demangled)
217-
if stringLen > 0 {
218-
return demangled.withMemoryRebound(to: UInt8.self, capacity: stringLen) {
219-
let demangledBytes = UnsafeBufferPointer<UInt8>(start: $0,
220-
count: stringLen)
221-
return String(decoding: demangledBytes, as: UTF8.self)
222-
}
205+
// Fallback to backtrace entrypoint to the demangler.
206+
var length: size_t = 0
207+
if let demangled = _swift_backtrace_demangle(rawName, rawName.utf8.count, nil, &length) {
208+
defer { free(demangled) }
209+
210+
// length is the size of the buffer that was allocated, *not* the
211+
// length of the string.
212+
let stringLen = strlen(demangled)
213+
if stringLen > 0 {
214+
return demangled.withMemoryRebound(to: UInt8.self, capacity: stringLen) {
215+
let demangledBytes = UnsafeBufferPointer<UInt8>(start: $0,
216+
count: stringLen)
217+
return String(decoding: demangledBytes, as: UTF8.self)
223218
}
224219
}
225-
return rawName
226220
}
221+
return rawName
227222
}
228223

229224
/// A textual description of this symbol.

stdlib/public/RuntimeModule/modules/Runtime/Runtime.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ void swift_reportWarning(uint32_t flags, const char *message);
3333
bool _swift_backtrace_isThunkFunction(const char *rawName);
3434

3535
// Demangle the given raw name (supports Swift and C++)
36-
//
37-
// The demangled string IS a null-terminated c-string.
3836
char *_swift_backtrace_demangle(const char *rawName,
3937
size_t rawNameLength,
4038
char *outputBuffer,
@@ -46,9 +44,14 @@ char *_swift_backtrace_demangle(const char *rawName,
4644
// If null is passed as the 'outputBuffer' the runtime function will allocate a buffer and return it.
4745
// If an 'outputBuffer' is passed, the output will be written into it, and the same buffer will be returned from this
4846
//
49-
// The demangled result String is NOT null-terminated.
47+
// The demangled result string is NOT null-terminated.
5048
// The demangled string length is indicated through the outputBufferSize parameter.
5149
//
50+
// Currently supported flags:
51+
// - 0: 'default'
52+
// - 1: '_swift_backtrace_demangle compatible mode', uses SimplifiedUIDemangleOptions for formatting
53+
// - *: unsupported values, result in immediate demangling failure.
54+
5255
// Introduced in Swift 6.3.
5356
char *_swift_runtime_demangle(const char *rawName,
5457
size_t rawNameLength,

stdlib/public/runtime/Demangle.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,12 +1050,14 @@ namespace swift {
10501050
size_t *outputBufferSize,
10511051
uint32_t flags) {
10521052
if (flags > 1) {
1053-
swift::fatalError(0, "Only 'flags' value of '0' and '1' is currently supported.");
1054-
}
1055-
if (outputBuffer != nullptr && outputBufferSize == nullptr) {
1056-
swift::fatalError(0, "'outputBuffer' is passed but the size is 'nullptr'.");
1053+
// ignore not supported flags
1054+
return nullptr;
10571055
}
10581056

1057+
// Very simple flags parsing, move to something more proper once we support more flags
1058+
bool shouldNullTerminateString = flags & 1;
1059+
bool shouldUseSimplifiedUIDemangleOptions = flags & 1;
1060+
10591061
llvm::StringRef name = llvm::StringRef(mangledName, mangledNameLength);
10601062

10611063
// You must provide buffer size if you're providing your own output buffer
@@ -1066,7 +1068,7 @@ namespace swift {
10661068
if (Demangle::isSwiftSymbol(name)) {
10671069
// Determine demangling/formatting options:
10681070
auto options = DemangleOptions();
1069-
if (flags == 1) {
1071+
if (shouldUseSimplifiedUIDemangleOptions) {
10701072
// simplified display options, for backtraces
10711073
options = DemangleOptions::SimplifiedUIDemangleOptions();
10721074
}
@@ -1080,12 +1082,19 @@ namespace swift {
10801082
}
10811083

10821084
if (outputBuffer == nullptr) {
1083-
outputBuffer = (char *)::malloc(result.length());
1085+
auto totalLength = shouldNullTerminateString ? (result.length() + 1) : result.length();
1086+
outputBuffer = (char *)::malloc(totalLength);
10841087
bufferSize = result.length();
10851088
}
10861089

1087-
size_t toCopy = std::min(bufferSize, result.length());
1090+
size_t toCopy = std::min(
1091+
shouldNullTerminateString ? (bufferSize - 1) : bufferSize,
1092+
shouldNullTerminateString ? (result.length() - 1) : result.length()
1093+
);
10881094
::memcpy(outputBuffer, result.data(), toCopy);
1095+
if (shouldNullTerminateString) {
1096+
outputBuffer[toCopy] = '\0';
1097+
}
10891098

10901099
return outputBuffer;
10911100
#ifndef _WIN32
@@ -1110,8 +1119,14 @@ namespace swift {
11101119
return result;
11111120
}
11121121

1113-
size_t toCopy = std::min(bufferSize, resultLen);
1122+
size_t toCopy = std::min(
1123+
shouldNullTerminateString ? (bufferSize - 1) : bufferSize,
1124+
shouldNullTerminateString ? (resultLen - 1) : resultLen
1125+
);
11141126
::memcpy(outputBuffer, result, toCopy);
1127+
if (shouldNullTerminateString) {
1128+
outputBuffer[toCopy] = '\0';
1129+
}
11151130

11161131
free(result);
11171132

@@ -1123,7 +1138,9 @@ namespace swift {
11231138
#endif
11241139
}
11251140

1126-
*outputBufferSize = 0; // indicate we did not write to buffer
1141+
if (outputBufferSize) {
1142+
*outputBufferSize = 0; // indicate we did not write to buffer
1143+
}
11271144
return nullptr;
11281145
}
11291146
}

test/Concurrency/Runtime/RuntimeDemangle.swift

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ var DemangleTests = TestSuite("Demangle")
1616

1717
if #available(SwiftStdlib 6.3, *) {
1818
DemangleTests.test("basic string return API") {
19-
// First, test that we get back the mangled name with invalid input.
19+
// First, test that we get back 'nil' with invalid input.
2020
expectEqual(demangle("abc123"), nil)
2121
expectEqual(demangle("Si"), nil)
2222
expectEqual(demangle("Swift is super cool!"), nil)
@@ -117,26 +117,23 @@ if #available(SwiftStdlib 6.3, *) {
117117
// Test the return of demangle into with a smaller buffer.
118118
// Swift.Int requires 9 bytes, give this 8
119119
let smolBuffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 8)
120-
var outputSpan = OutputSpan<UTF8.CodeUnit>(buffer: smolBuffer, initializedCount: 0)
120+
var smolOutputSpan = OutputSpan<UTF8.CodeUnit>(buffer: smolBuffer, initializedCount: 0)
121121
defer { smolBuffer.deallocate() }
122122

123-
let smolPtr = smolBuffer.baseAddress!
124-
125-
let fail = demangle("$sSi".utf8Span, into: &outputSpan)
123+
let fail = demangle("$sSi".utf8Span, into: &smolOutputSpan)
126124
expectEqual(fail, .truncated(9))
127-
expectEqual(String(cString: smolPtr), "Swift.In")
125+
expectEqual(String(copying: try! UTF8Span(validating: smolOutputSpan.span)), "Swift.In")
128126
}
129127

130128
DemangleTests.test("Span API - small buffer, success") {
131129
let smolBuffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 9)
132-
var outputSpan = OutputSpan<UTF8.CodeUnit>(buffer: smolBuffer, initializedCount: 0)
130+
var smolOutputSpan = OutputSpan<UTF8.CodeUnit>(buffer: smolBuffer, initializedCount: 0)
133131
defer { smolBuffer.deallocate() }
134132

135-
let smolPtr = smolBuffer.baseAddress!
136133
// Test nil return on successful demangle.
137-
let success = demangle("$s4Smol3IntV".utf8Span, into: &outputSpan)
134+
let success = demangle("$s4Smol3IntV".utf8Span, into: &smolOutputSpan)
138135
expectEqual(success, .success)
139-
expectEqual(String(cString: smolPtr), "Smol.Int")
136+
expectEqual(String(copying: try! UTF8Span(validating: smolOutputSpan.span)), "Smol.Int")
140137
}
141138

142139
}

0 commit comments

Comments
 (0)