Skip to content

[swift-inspect] Add an option to print mangled names while dumping generic metadata. #69488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -3116,7 +3116,8 @@ class MetadataReader {
break;

case GenericParamKind::TypePack:
assert(false && "Packs not supported here yet");
// assert(false && "Packs not supported here yet");
return {};

default:
// We don't know about this kind of parameter.
Expand Down
27 changes: 14 additions & 13 deletions include/swift/RemoteInspection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -853,24 +853,25 @@ class ReflectionContext

/// Returns true if the address is known to the reflection context.
/// Currently, that means that either the address falls within the text or
/// data segments of a registered image, or the address points to a Metadata
/// whose type context descriptor is within the text segment of a registered
/// image.
bool ownsAddress(RemoteAddress Address) {
/// data segments of a registered image, or optionally, the address points
/// to a Metadata whose type context descriptor is within the text segment
/// of a registered image.
bool ownsAddress(RemoteAddress Address, bool checkMetadataDescriptor = true) {
if (ownsAddress(Address, textRanges))
return true;
if (ownsAddress(Address, dataRanges))
return true;

// This is usually called on a Metadata address which might have been
// on the heap. Try reading it and looking up its type context descriptor
// instead.
if (auto Metadata = readMetadata(Address.getAddressData()))
if (auto DescriptorAddress =
super::readAddressOfNominalTypeDescriptor(Metadata, true))
if (ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
return true;

if (checkMetadataDescriptor) {
// This is usually called on a Metadata address which might have been
// on the heap. Try reading it and looking up its type context descriptor
// instead.
if (auto Metadata = readMetadata(Address.getAddressData()))
if (auto DescriptorAddress =
super::readAddressOfNominalTypeDescriptor(Metadata, true))
if (ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
return true;
}
return false;
}

Expand Down
22 changes: 22 additions & 0 deletions include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ SWIFT_REMOTE_MIRROR_LINKAGE
int
swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Address);

/// Returns whether the given address is strictly in the DATA, AUTH or TEXT
/// segments of the image added to this library. Images must be added using
/// swift_reflection_addImage, not swift_reflection_addReflectionInfo, for this
/// function to work properly. If addReflectionInfo is used, the return value
/// will always be false.
SWIFT_REMOTE_MIRROR_LINKAGE
int
swift_reflection_ownsAddressStrict(SwiftReflectionContextRef ContextRef, uintptr_t Address);

/// Returns the metadata pointer for a given object.
SWIFT_REMOTE_MIRROR_LINKAGE
uintptr_t
Expand Down Expand Up @@ -179,6 +188,7 @@ swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
///
/// The returned string is heap allocated and the caller must free() it when
/// done.
[[deprecated("Please use swift_reflection_copyNameForTypeRef()")]]
SWIFT_REMOTE_MIRROR_LINKAGE
char *
swift_reflection_copyDemangledNameForTypeRef(
Expand All @@ -189,6 +199,18 @@ char *
swift_reflection_copyDemangledNameForProtocolDescriptor(
SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto);

/// Returns the mangled or demangled name for a typeref, or NULL if the name
/// couldn't be created.
///
/// The returned string is heap allocated and the caller must free() it when
/// done.

SWIFT_REMOTE_MIRROR_LINKAGE
char*
swift_reflection_copyNameForTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef,
bool mangled);

/// Returns a structure describing the layout of a value of a typeref.
/// For classes, this returns the reference value itself.
SWIFT_REMOTE_MIRROR_LINKAGE
Expand Down
28 changes: 27 additions & 1 deletion stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Add
return Context->ownsAddress(RemoteAddress(Address));
}

int
swift_reflection_ownsAddressStrict(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
auto Context = ContextRef->nativeContext;
return Context->ownsAddress(RemoteAddress(Address), false);
}

uintptr_t
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
uintptr_t Object) {
Expand Down Expand Up @@ -367,6 +373,26 @@ swift_reflection_copyDemangledNameForTypeRef(
return strdup(Name.c_str());
}

char *
swift_reflection_copyNameForTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef,
bool mangled) {
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);

Demangle::Demangler Dem;
if (mangled) {
auto Mangling = mangleNode(TR->getDemangling(Dem));
if (Mangling.isSuccess()) {
return strdup(Mangling.result().c_str());
}
}
else {
auto Name = nodeToString(TR->getDemangling(Dem));
return strdup(Name.c_str());
}
return nullptr;
}

SWIFT_REMOTE_MIRROR_LINKAGE
char *
swift_reflection_copyDemangledNameForProtocolDescriptor(
Expand Down Expand Up @@ -697,7 +723,7 @@ void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
}

char *DemangledName =
swift_reflection_copyDemangledNameForTypeRef(ContextRef, OpaqueTypeRef);
swift_reflection_copyNameForTypeRef(ContextRef, OpaqueTypeRef, false);
std::cout << "Demangled name: " << DemangledName << "\n";
free(DemangledName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ internal struct DumpGenericMetadata: ParsableCommand {
@OptionGroup()
var backtraceOptions: BacktraceOptions

@OptionGroup()
var genericMetadataOptions: GenericMetadataOptions

func run() throws {
try inspect(options: options) { process in
let allocations: [swift_metadata_allocation_t] =
Expand All @@ -43,9 +46,8 @@ internal struct DumpGenericMetadata: ParsableCommand {
if pointer == 0 { return nil }

return Metadata(ptr: pointer,
allocation: allocations.last(where: { pointer >= $0.ptr }),
name: process.context.name(type: pointer) ??
"<unknown>",
allocation: allocations.last(where: { pointer >= $0.ptr && pointer < $0.ptr + UInt64($0.size) }),
name: (process.context.name(type: pointer, mangled: genericMetadataOptions.mangled) ?? "<unknown>"),
isArrayOfClass: process.context.isArrayOfClass(pointer))
}

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

var errorneousMetadata: [(ptr: swift_reflection_ptr_t, name: String)] = []

print("Address", "Allocation", "Size", "Offset", "isArrayOfClass", "Name", separator: "\t")
generics.forEach {
print("\(hex: $0.ptr)", terminator: "\t")
if let allocation = $0.allocation, let offset = $0.offset {
print("\(hex: allocation.ptr)\t\(allocation.size)\t\(offset)", terminator: "\t")
} else {
if (swift_reflection_ownsAddressStrict(process.context, UInt($0.ptr))) == 0 {
errorneousMetadata.append((ptr: $0.ptr, name: $0.name))
}
print("???\t??\t???", terminator: "\t")
}
print($0.isArrayOfClass, terminator: "\t")
Expand All @@ -72,6 +79,14 @@ internal struct DumpGenericMetadata: ParsableCommand {
}
}
}

if errorneousMetadata.count > 0 {
print("Error: The following metadata was not found in any DATA or AUTH segments, may be garbage.")
errorneousMetadata.forEach {
print("\(hex: $0.ptr)\t\($0.name)")
}
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ extension SwiftReflectionContextRef {
}
}

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

guard let name = swift_reflection_copyDemangledNameForTypeRef(self, typeref) else {
guard let name = swift_reflection_copyNameForTypeRef(self, typeref, mangled) else {
return nil
}
defer { free(name) }
Expand Down
4 changes: 4 additions & 0 deletions tools/swift-inspect/Sources/swift-inspect/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ internal struct BacktraceOptions: ParsableArguments {
}
}

internal struct GenericMetadataOptions: ParsableArguments {
@Flag(help: "Show allocations in mangled form")
var mangled: Bool = false
}

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