Skip to content

Commit 2b594b2

Browse files
authored
Merge pull request #69488 from w6sec/mangled
[swift-inspect] Add an option to print mangled names while dumping generic metadata.
2 parents 4ec627e + b6f77a4 commit 2b594b2

File tree

7 files changed

+89
-20
lines changed

7 files changed

+89
-20
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3122,7 +3122,8 @@ class MetadataReader {
31223122
break;
31233123

31243124
case GenericParamKind::TypePack:
3125-
assert(false && "Packs not supported here yet");
3125+
// assert(false && "Packs not supported here yet");
3126+
return {};
31263127

31273128
default:
31283129
// We don't know about this kind of parameter.

include/swift/RemoteInspection/ReflectionContext.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -853,24 +853,25 @@ class ReflectionContext
853853

854854
/// Returns true if the address is known to the reflection context.
855855
/// Currently, that means that either the address falls within the text or
856-
/// data segments of a registered image, or the address points to a Metadata
857-
/// whose type context descriptor is within the text segment of a registered
858-
/// image.
859-
bool ownsAddress(RemoteAddress Address) {
856+
/// data segments of a registered image, or optionally, the address points
857+
/// to a Metadata whose type context descriptor is within the text segment
858+
/// of a registered image.
859+
bool ownsAddress(RemoteAddress Address, bool checkMetadataDescriptor = true) {
860860
if (ownsAddress(Address, textRanges))
861861
return true;
862862
if (ownsAddress(Address, dataRanges))
863863
return true;
864864

865-
// This is usually called on a Metadata address which might have been
866-
// on the heap. Try reading it and looking up its type context descriptor
867-
// instead.
868-
if (auto Metadata = readMetadata(Address.getAddressData()))
869-
if (auto DescriptorAddress =
870-
super::readAddressOfNominalTypeDescriptor(Metadata, true))
871-
if (ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
872-
return true;
873-
865+
if (checkMetadataDescriptor) {
866+
// This is usually called on a Metadata address which might have been
867+
// on the heap. Try reading it and looking up its type context descriptor
868+
// instead.
869+
if (auto Metadata = readMetadata(Address.getAddressData()))
870+
if (auto DescriptorAddress =
871+
super::readAddressOfNominalTypeDescriptor(Metadata, true))
872+
if (ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
873+
return true;
874+
}
874875
return false;
875876
}
876877

include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ SWIFT_REMOTE_MIRROR_LINKAGE
138138
int
139139
swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Address);
140140

141+
/// Returns whether the given address is strictly in the DATA, AUTH or TEXT
142+
/// segments of the image added to this library. Images must be added using
143+
/// swift_reflection_addImage, not swift_reflection_addReflectionInfo, for this
144+
/// function to work properly. If addReflectionInfo is used, the return value
145+
/// will always be false.
146+
SWIFT_REMOTE_MIRROR_LINKAGE
147+
int
148+
swift_reflection_ownsAddressStrict(SwiftReflectionContextRef ContextRef, uintptr_t Address);
149+
141150
/// Returns the metadata pointer for a given object.
142151
SWIFT_REMOTE_MIRROR_LINKAGE
143152
uintptr_t
@@ -179,6 +188,7 @@ swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
179188
///
180189
/// The returned string is heap allocated and the caller must free() it when
181190
/// done.
191+
[[deprecated("Please use swift_reflection_copyNameForTypeRef()")]]
182192
SWIFT_REMOTE_MIRROR_LINKAGE
183193
char *
184194
swift_reflection_copyDemangledNameForTypeRef(
@@ -189,6 +199,18 @@ char *
189199
swift_reflection_copyDemangledNameForProtocolDescriptor(
190200
SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto);
191201

202+
/// Returns the mangled or demangled name for a typeref, or NULL if the name
203+
/// couldn't be created.
204+
///
205+
/// The returned string is heap allocated and the caller must free() it when
206+
/// done.
207+
208+
SWIFT_REMOTE_MIRROR_LINKAGE
209+
char*
210+
swift_reflection_copyNameForTypeRef(SwiftReflectionContextRef ContextRef,
211+
swift_typeref_t OpaqueTypeRef,
212+
bool mangled);
213+
192214
/// Returns a structure describing the layout of a value of a typeref.
193215
/// For classes, this returns the reference value itself.
194216
SWIFT_REMOTE_MIRROR_LINKAGE

stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,12 @@ swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Add
314314
return Context->ownsAddress(RemoteAddress(Address));
315315
}
316316

317+
int
318+
swift_reflection_ownsAddressStrict(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
319+
auto Context = ContextRef->nativeContext;
320+
return Context->ownsAddress(RemoteAddress(Address), false);
321+
}
322+
317323
uintptr_t
318324
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
319325
uintptr_t Object) {
@@ -367,6 +373,26 @@ swift_reflection_copyDemangledNameForTypeRef(
367373
return strdup(Name.c_str());
368374
}
369375

376+
char *
377+
swift_reflection_copyNameForTypeRef(SwiftReflectionContextRef ContextRef,
378+
swift_typeref_t OpaqueTypeRef,
379+
bool mangled) {
380+
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
381+
382+
Demangle::Demangler Dem;
383+
if (mangled) {
384+
auto Mangling = mangleNode(TR->getDemangling(Dem));
385+
if (Mangling.isSuccess()) {
386+
return strdup(Mangling.result().c_str());
387+
}
388+
}
389+
else {
390+
auto Name = nodeToString(TR->getDemangling(Dem));
391+
return strdup(Name.c_str());
392+
}
393+
return nullptr;
394+
}
395+
370396
SWIFT_REMOTE_MIRROR_LINKAGE
371397
char *
372398
swift_reflection_copyDemangledNameForProtocolDescriptor(
@@ -697,7 +723,7 @@ void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
697723
}
698724

699725
char *DemangledName =
700-
swift_reflection_copyDemangledNameForTypeRef(ContextRef, OpaqueTypeRef);
726+
swift_reflection_copyNameForTypeRef(ContextRef, OpaqueTypeRef, false);
701727
std::cout << "Demangled name: " << DemangledName << "\n";
702728
free(DemangledName);
703729
}

tools/swift-inspect/Sources/swift-inspect/Operations/DumpGenericMetadata.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ internal struct DumpGenericMetadata: ParsableCommand {
3333
@OptionGroup()
3434
var backtraceOptions: BacktraceOptions
3535

36+
@OptionGroup()
37+
var genericMetadataOptions: GenericMetadataOptions
38+
3639
func run() throws {
3740
try inspect(options: options) { process in
3841
let allocations: [swift_metadata_allocation_t] =
@@ -43,9 +46,8 @@ internal struct DumpGenericMetadata: ParsableCommand {
4346
if pointer == 0 { return nil }
4447

4548
return Metadata(ptr: pointer,
46-
allocation: allocations.last(where: { pointer >= $0.ptr }),
47-
name: process.context.name(type: pointer) ??
48-
"<unknown>",
49+
allocation: allocations.last(where: { pointer >= $0.ptr && pointer < $0.ptr + UInt64($0.size) }),
50+
name: (process.context.name(type: pointer, mangled: genericMetadataOptions.mangled) ?? "<unknown>"),
4951
isArrayOfClass: process.context.isArrayOfClass(pointer))
5052
}
5153

@@ -54,12 +56,17 @@ internal struct DumpGenericMetadata: ParsableCommand {
5456
? nil
5557
: try process.context.allocationStacks
5658

59+
var errorneousMetadata: [(ptr: swift_reflection_ptr_t, name: String)] = []
60+
5761
print("Address", "Allocation", "Size", "Offset", "isArrayOfClass", "Name", separator: "\t")
5862
generics.forEach {
5963
print("\(hex: $0.ptr)", terminator: "\t")
6064
if let allocation = $0.allocation, let offset = $0.offset {
6165
print("\(hex: allocation.ptr)\t\(allocation.size)\t\(offset)", terminator: "\t")
6266
} else {
67+
if (swift_reflection_ownsAddressStrict(process.context, UInt($0.ptr))) == 0 {
68+
errorneousMetadata.append((ptr: $0.ptr, name: $0.name))
69+
}
6370
print("???\t??\t???", terminator: "\t")
6471
}
6572
print($0.isArrayOfClass, terminator: "\t")
@@ -72,6 +79,14 @@ internal struct DumpGenericMetadata: ParsableCommand {
7279
}
7380
}
7481
}
82+
83+
if errorneousMetadata.count > 0 {
84+
print("Error: The following metadata was not found in any DATA or AUTH segments, may be garbage.")
85+
errorneousMetadata.forEach {
86+
print("\(hex: $0.ptr)\t\($0.name)")
87+
}
88+
}
89+
7590
}
7691
}
7792
}

tools/swift-inspect/Sources/swift-inspect/RemoteMirror+Extensions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ extension SwiftReflectionContextRef {
6464
}
6565
}
6666

67-
internal func name(type: swift_reflection_ptr_t) -> String? {
67+
internal func name(type: swift_reflection_ptr_t, mangled: Bool = false) -> String? {
6868
let typeref = swift_reflection_typeRefForMetadata(self, UInt(type))
6969
if typeref == 0 { return nil }
7070

71-
guard let name = swift_reflection_copyDemangledNameForTypeRef(self, typeref) else {
71+
guard let name = swift_reflection_copyNameForTypeRef(self, typeref, mangled) else {
7272
return nil
7373
}
7474
defer { free(name) }

tools/swift-inspect/Sources/swift-inspect/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ internal struct BacktraceOptions: ParsableArguments {
4242
}
4343
}
4444

45+
internal struct GenericMetadataOptions: ParsableArguments {
46+
@Flag(help: "Show allocations in mangled form")
47+
var mangled: Bool = false
48+
}
4549

4650
internal func inspect(options: UniversalOptions,
4751
_ body: (any RemoteProcess) throws -> Void) throws {

0 commit comments

Comments
 (0)