Skip to content

Commit 9ef116a

Browse files
committed
Implement SymbolInfo::getFilename() on Win32
1 parent 39aef7d commit 9ef116a

File tree

12 files changed

+270
-97
lines changed

12 files changed

+270
-97
lines changed

include/swift/Runtime/Win32Strings.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===--- Win32Strings.h ---------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Includes conversion functions for use with Windows API that produces or
14+
// consumes wide strings (wchar_t) which, on Windows, are UTF-16.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_RUNTIME_WIN32STRINGS_H
19+
#define SWIFT_RUNTIME_WIN32STRINGS_H
20+
21+
#if defined(_WIN32)
22+
namespace swift {
23+
/// Convert an argument, represented by a wide string, to UTF-8.
24+
///
25+
/// @param str The string to convert.
26+
///
27+
/// @returns The string, converted to UTF-8. The caller is responsible for
28+
/// freeing this string with @c free() when done with it.
29+
///
30+
/// If @a str cannot be converted to UTF-8, @c nullptr is returned.
31+
SWIFT_RUNTIME_STDLIB_INTERNAL
32+
char *swift_win32_copyUTF8FromWide(const wchar_t *str);
33+
}
34+
#endif
35+
#endif

stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,15 @@ internal func _getMetadataSection(_ index: UInt) -> UnsafeRawPointer?
138138
@_silgen_name("swift_getMetadataSectionCount")
139139
internal func _getMetadataSectionCount() -> UInt
140140

141-
@_silgen_name("swift_getMetadataSectionName")
142-
internal func _getMetadataSectionName(
141+
@_silgen_name("swift_copyMetadataSectionName")
142+
internal func _copyMetadataSectionName(
143143
_ metadata_section: UnsafeRawPointer
144-
) -> UnsafePointer<CChar>
144+
) -> UnsafeMutablePointer<CChar>?
145+
146+
@_silgen_name("swift_freeMetadataSectionName")
147+
internal func _freeMetadataSectionName(
148+
_ name: UnsafeMutablePointer<CChar>
149+
) -> Void
145150
#endif
146151

147152
extension Section {
@@ -154,9 +159,13 @@ extension Section {
154159
internal func getReflectionInfoForImage(atIndex i: UInt32) -> ReflectionInfo? {
155160
#if INTERNAL_CHECKS_ENABLED
156161
return _getMetadataSection(UInt(i)).map { rawPointer in
157-
let name = _getMetadataSectionName(rawPointer)
162+
let cName = _copyMetadataSectionName(rawPointer)
163+
defer {
164+
_freeMetadataSectionName(cName)
165+
}
166+
let name = cName.flatMap { String(validatingUTF8: $0) } ?? "<unavailable>"
158167
let metadataSection = rawPointer.bindMemory(to: MetadataSections.self, capacity: 1).pointee
159-
return ReflectionInfo(imageName: String(validatingUTF8: name)!,
168+
return ReflectionInfo(imageName: name,
160169
fieldmd: Section(range: metadataSection.swift5_fieldmd),
161170
assocty: Section(range: metadataSection.swift5_assocty),
162171
builtin: Section(range: metadataSection.swift5_builtin),

stdlib/public/CommandLineSupport/CommandLine.cpp

Lines changed: 8 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <string>
2626

2727
#include "swift/Runtime/Debug.h"
28+
#include "swift/Runtime/Win32Strings.h"
2829

2930
#include "swift/shims/GlobalObjects.h"
3031
#include "swift/shims/RuntimeStubs.h"
@@ -193,48 +194,6 @@ static void swift::enumerateUnsafeArgv(const F& body) {
193194
#elif defined(_WIN32)
194195
#include <stdlib.h>
195196

196-
namespace swift {
197-
/// Convert an argument, represented by a wide string, to UTF-8.
198-
///
199-
/// @param str The string to convert.
200-
///
201-
/// @returns The string, converted to UTF-8. The caller is responsible for
202-
/// freeing this string when done with it.
203-
///
204-
/// If @a str cannot be converted to UTF-8, a fatal error occurs.
205-
static char *copyUTF8FromWide(wchar_t *str) {
206-
char *result = nullptr;
207-
208-
int resultLength = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str,
209-
-1, nullptr, 0, nullptr, nullptr);
210-
if (resultLength <= 0) {
211-
swift::fatalError(0,
212-
"Fatal error: Could not get length of commandline "
213-
"argument '%ls': %lu\n",
214-
str, GetLastError());
215-
}
216-
217-
result = reinterpret_cast<char *>(malloc(resultLength));
218-
if (!result) {
219-
swift::fatalError(0,
220-
"Fatal error: Could not allocate space for commandline "
221-
"argument '%ls': %d\n",
222-
str, errno);
223-
}
224-
225-
resultLength = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, -1,
226-
result, resultLength, nullptr, nullptr);
227-
if (resultLength <= 0) {
228-
swift::fatalError(0,
229-
"Fatal error: Conversion to UTF-8 failed for "
230-
"commandline argument '%ls': %lu\n",
231-
str, GetLastError());
232-
}
233-
234-
return result;
235-
}
236-
}
237-
238197
static char **swift::getUnsafeArgvArgc(int *outArgLen) {
239198
return nullptr;
240199
}
@@ -244,7 +203,13 @@ static void swift::enumerateUnsafeArgv(const F& body) {
244203
int argc = 0;
245204
if (LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &argc)) {
246205
std::for_each(wargv, wargv + argc, [=] (wchar_t *warg) {
247-
auto arg = copyUTF8FromWide(warg);
206+
auto arg = swift_win32_copyUTF8FromWide(warg);
207+
if (!arg) {
208+
swift::fatalError(0,
209+
"Fatal error: Could not convert commandline argument "
210+
"'%ls' to UTF-8: Windows error %lu, C error %d.\n",
211+
warg, GetLastError(), errno);
212+
}
248213
body(argc, arg);
249214
free(arg);
250215
});

stdlib/public/runtime/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ set(swift_runtime_sources
6969
SwiftDtoa.cpp
7070
SwiftTLSContext.cpp
7171
ThreadingError.cpp
72-
AccessibleFunction.cpp)
72+
AccessibleFunction.cpp
73+
Win32Strings.cpp)
7374

7475
# Acknowledge that the following sources are known.
7576
set(LLVM_OPTIONAL_SOURCES

stdlib/public/runtime/Errors.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ enum: uint32_t {
7878
using namespace swift;
7979

8080
#if SWIFT_STDLIB_SUPPORTS_BACKTRACE_REPORTING && SWIFT_STDLIB_HAS_DLADDR
81-
static bool getSymbolNameAddr(llvm::StringRef libraryName,
82-
const SymbolInfo &syminfo,
81+
static bool getSymbolNameAddr(const SymbolInfo &syminfo,
8382
std::string &symbolName, uintptr_t &addrOut) {
8483
// If we failed to find a symbol and thus dlinfo->dli_sname is nullptr, we
8584
// need to use the hex address.
@@ -149,12 +148,14 @@ void swift::dumpStackTraceEntry(unsigned index, void *framePC,
149148
return;
150149
}
151150

152-
// If SymbolInfo:lookup succeeded then fileName is non-null. Thus, we find the
151+
// If SymbolInfo:lookup succeeded and fileName is non-null, we can find the
153152
// library name here. Avoid using StringRef::rsplit because its definition
154153
// is not provided in the header so that it requires linking with
155154
// libSupport.a.
156-
llvm::StringRef libraryName{syminfo->getFilename()};
157-
libraryName = libraryName.substr(libraryName.rfind('/')).substr(1);
155+
const char *libraryName = syminfo->getImageFilename();
156+
if (!libraryName) {
157+
libraryName = "<unavailable>";
158+
}
158159

159160
// Next we get the symbol name that we are going to use in our backtrace.
160161
std::string symbolName;
@@ -163,12 +164,12 @@ void swift::dumpStackTraceEntry(unsigned index, void *framePC,
163164
// we just get HexAddr + 0.
164165
uintptr_t symbolAddr = uintptr_t(framePC);
165166
bool foundSymbol =
166-
getSymbolNameAddr(libraryName, syminfo.value(), symbolName, symbolAddr);
167+
getSymbolNameAddr(syminfo.value(), symbolName, symbolAddr);
167168
ptrdiff_t offset = 0;
168169
if (foundSymbol) {
169170
offset = ptrdiff_t(uintptr_t(framePC) - symbolAddr);
170171
} else {
171-
auto baseAddress = syminfo->getBaseAddress();
172+
const void *baseAddress = syminfo->getImageBaseAddress();
172173
offset = ptrdiff_t(uintptr_t(framePC) - uintptr_t(baseAddress));
173174
symbolAddr = uintptr_t(framePC);
174175
symbolName = "<unavailable>";
@@ -182,12 +183,11 @@ void swift::dumpStackTraceEntry(unsigned index, void *framePC,
182183
// This gives enough info to reconstruct identical debugging target after
183184
// this process terminates.
184185
if (shortOutput) {
185-
fprintf(stderr, "%s`%s + %td", libraryName.data(), symbolName.c_str(),
186-
offset);
186+
fprintf(stderr, "%s`%s + %td", libraryName, symbolName.c_str(), offset);
187187
} else {
188188
constexpr const char *format = "%-4u %-34s 0x%0.16" PRIxPTR " %s + %td\n";
189-
fprintf(stderr, format, index, libraryName.data(), symbolAddr,
190-
symbolName.c_str(), offset);
189+
fprintf(stderr, format, index, libraryName, symbolAddr, symbolName.c_str(),
190+
offset);
191191
}
192192
#else
193193
if (shortOutput) {

stdlib/public/runtime/ImageInspectionCommon.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ static void fixupMetadataSectionBaseAddress(swift::MetadataSections *sections) {
6464
if (fixupNeeded) {
6565
// We need to fix up the base address. We'll need a known-good address in
6666
// the same image: `sections` itself will work nicely.
67-
auto symbolInfo = SymbolInfo::lookup(sections);
68-
if (symbolInfo.has_value() && symbolInfo->getBaseAddress()) {
69-
sections->baseAddress.store(symbolInfo->getBaseAddress(),
70-
std::memory_order_relaxed);
67+
if (auto symbolInfo = SymbolInfo::lookup(sections)) {
68+
if (const void *baseAddress = symbolInfo->getImageBaseAddress()) {
69+
sections->baseAddress.store(baseAddress, std::memory_order_relaxed);
70+
}
7171
}
7272
}
7373
}
@@ -188,22 +188,26 @@ const swift::MetadataSections *swift_getMetadataSection(size_t index) {
188188
}
189189

190190
SWIFT_RUNTIME_EXPORT
191-
const char *
192-
swift_getMetadataSectionName(const swift::MetadataSections *section) {
191+
char *swift_copyMetadataSectionName(const swift::MetadataSections *section) {
193192
if (auto info = SymbolInfo::lookup(section)) {
194-
if (info->getFilename()) {
195-
return info->getFilename();
193+
if (const char *imagePath = info->getImagePath()) {
194+
return strdup(imagePath);
196195
}
197196
}
198197
return "";
199198
}
200199

200+
SWIFT_RUNTIME_EXPORT
201+
void swift_freeMetadataSectionName(char *name) {
202+
free(name);
203+
}
204+
201205
SWIFT_RUNTIME_EXPORT
202206
void swift_getMetadataSectionBaseAddress(const swift::MetadataSections *section,
203207
void const **out_actual,
204208
void const **out_expected) {
205209
if (auto info = SymbolInfo::lookup(section)) {
206-
*out_actual = info->getBaseAddress();
210+
*out_actual = info->getImageBaseAddress();
207211
} else {
208212
*out_actual = nullptr;
209213
}

stdlib/public/runtime/ImageInspectionCommon.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,11 @@ void swift_enumerateAllMetadataSections(
8686
#ifndef NDEBUG
8787

8888
SWIFT_RUNTIME_EXPORT
89-
const char *
90-
swift_getMetadataSectionName(const struct swift::MetadataSections *section);
89+
char *
90+
swift_copyMetadataSectionName(const struct swift::MetadataSections *section);
91+
92+
SWIFT_RUNTIME_EXPORT
93+
void swift_freeMetadataSectionName(char *name);
9194

9295
SWIFT_RUNTIME_EXPORT
9396
void swift_getMetadataSectionBaseAddress(

stdlib/public/runtime/ReflectionMirror.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,8 +1117,8 @@ id swift_reflectionMirror_quickLookObject(OpaqueValue *value, const Metadata *T)
11171117
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
11181118
const char *swift_keyPath_copySymbolName(void *address) {
11191119
if (auto info = SymbolInfo::lookup(address)) {
1120-
if (info->getSymbolName()) {
1121-
return strdup(info->getSymbolName());
1120+
if (const char *symbolName = info->getSymbolName()) {
1121+
return strdup(symbolName);
11221122
}
11231123
}
11241124
return nullptr;

0 commit comments

Comments
 (0)