Skip to content

Commit df5580b

Browse files
mikeashairspeedswift
authored andcommitted
[Tools] Move metadata dumping into swiftdt, have Remote Mirror just iterate and inspect.
rdar://problem/55481578
1 parent 48e5473 commit df5580b

File tree

7 files changed

+230
-90
lines changed

7 files changed

+230
-90
lines changed

include/swift/Reflection/ReflectionContext.h

Lines changed: 49 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -802,42 +802,29 @@ class ReflectionContext
802802
}
803803
}
804804

805-
void dumpConformanceNode(const struct ConformanceNode *Node) {
806-
Demangle::Demangler Dem;
807-
808-
std::string TypeName = "<unknown>";
809-
if (auto TR = readTypeFromMetadata(Node->Type)) {
810-
auto Demangling = TR->getDemangling(Dem);
811-
TypeName = nodeToString(Demangling);
812-
}
813-
814-
auto ProtocolDemangled = readDemanglingForContextDescriptor(Node->Proto, Dem);
815-
auto ProtocolName = nodeToString(ProtocolDemangled);
816-
817-
printf("Conformance: %s: %s\n", TypeName.c_str(), ProtocolName.c_str());
818-
}
819-
820-
void dumpConformanceTree(StoredPointer NodePtr) {
805+
void iterateConformanceTree(StoredPointer NodePtr,
806+
std::function<void(StoredPointer Type, StoredPointer Proto)> Call) {
821807
if (!NodePtr)
822808
return;
823809
auto NodeBytes = getReader().readBytes(RemoteAddress(NodePtr), sizeof(Node));
824810
auto NodeData = reinterpret_cast<const ConformanceNode *>(NodeBytes.get());
825811
if (!NodeData)
826812
return;
827-
dumpConformanceNode(NodeData);
828-
dumpConformanceTree(NodeData->Left);
829-
dumpConformanceTree(NodeData->Right);
813+
Call(NodeData->Type, NodeData->Proto);
814+
iterateConformanceTree(NodeData->Left, Call);
815+
iterateConformanceTree(NodeData->Right, Call);
830816
}
831817

832-
void dumpConformances() {
818+
bool iterateConformances(
819+
std::function<void(StoredPointer Type, StoredPointer Proto)> Call) {
833820
std::string ConformancesName = "__ZL12Conformances";
834821
auto ConformancesAddr = getReader().getSymbolAddress(ConformancesName);
835-
printf("%#llx\n", ConformancesAddr.getAddressData());
836822
if (!ConformancesAddr)
837-
return;
823+
return false;
838824

839825
auto Root = getReader().readPointer(ConformancesAddr, sizeof(StoredPointer));
840-
dumpConformanceTree(Root->getResolvedAddress().getAddressData());
826+
iterateConformanceTree(Root->getResolvedAddress().getAddressData(), Call);
827+
return true;
841828
}
842829

843830
void iterateModules(Demangle::NodePointer Ptr, std::function<void(llvm::StringRef)> Call) {
@@ -847,53 +834,41 @@ class ReflectionContext
847834
iterateModules(Child, Call);
848835
}
849836

850-
void dumpGenericMetadataCacheEntry(const char *Ptr) {
851-
struct GenericMetadataCacheEntry {
852-
StoredPointer Left, Right;
853-
StoredPointer LockedStorage;
854-
uint8_t LockedStorageKind;
855-
uint8_t TrackingInfo;
856-
uint16_t NumKeyParameters;
857-
uint16_t NumWitnessTables;
858-
uint32_t Hash;
859-
StoredPointer Value;
860-
};
861-
862-
auto EntryPtr = (const GenericMetadataCacheEntry *)Ptr;
863-
printf(" Left: %#llx\n", EntryPtr->Left);
864-
printf(" Right: %#llx\n", EntryPtr->Right);
865-
printf(" LockedStorage: %#llx\n", EntryPtr->LockedStorage);
866-
printf(" LockedStorageKind: %u\n", EntryPtr->LockedStorageKind);
867-
printf(" TrackingInfo: %u\n", EntryPtr->TrackingInfo);
868-
printf(" NumKeyParameters: %u\n", EntryPtr->NumKeyParameters);
869-
printf(" NumWitnessTables: %u\n", EntryPtr->NumWitnessTables);
870-
printf(" Hash: %#x\n", EntryPtr->Hash);
871-
printf(" Value: %#llx\n", EntryPtr->Value);
872-
873-
if (EntryPtr->Value) {
874-
if (auto Metadata = readMetadata(EntryPtr->Value)) {
875-
if (auto TR = readTypeFromMetadata(Metadata.getAddressData())) {
876-
Demangle::Demangler Dem;
877-
auto Demangling = TR->getDemangling(Dem);
878-
auto Name = nodeToString(Demangling);
879-
printf(" Name: %s\n", Name.c_str());
880-
881-
printf(" Modules:");
882-
iterateModules(Demangling, [](llvm::StringRef Str){
883-
printf(" %s", Str.str().c_str());
884-
});
885-
printf("\n");
886-
}
887-
}
837+
struct MetadataAllocation {
838+
uint16_t Tag;
839+
StoredPointer Ptr;
840+
unsigned Size;
841+
};
842+
843+
StoredPointer allocationMetadataPointer(MetadataAllocation Allocation) {
844+
if (Allocation.Tag == GenericMetadataCacheTag) {
845+
struct GenericMetadataCacheEntry {
846+
StoredPointer Left, Right;
847+
StoredPointer LockedStorage;
848+
uint8_t LockedStorageKind;
849+
uint8_t TrackingInfo;
850+
uint16_t NumKeyParameters;
851+
uint16_t NumWitnessTables;
852+
uint32_t Hash;
853+
StoredPointer Value;
854+
};
855+
auto AllocationBytes =
856+
getReader().readBytes(RemoteAddress(Allocation.Ptr),
857+
Allocation.Size);
858+
auto Entry = reinterpret_cast<const GenericMetadataCacheEntry *>(
859+
AllocationBytes.get());
860+
if (!Entry)
861+
return 0;
862+
return Entry->Value;
888863
}
864+
return 0;
889865
}
890866

891-
void dumpMetadataAllocations() {
867+
bool iterateMetadataAllocations(std::function<void (MetadataAllocation)> Call) {
892868
std::string AllocationPoolName = "__ZL14AllocationPool";
893869
auto AllocationPoolAddr = getReader().getSymbolAddress(AllocationPoolName);
894-
printf("%#llx\n", AllocationPoolAddr.getAddressData());
895-
896-
printf("Initial pool: %#llx\n", getReader().getSymbolAddress("__ZL21InitialAllocationPool").getAddressData());
870+
if (!AllocationPoolAddr)
871+
return false;
897872

898873
struct PoolRange {
899874
StoredPointer Begin;
@@ -912,8 +887,8 @@ class ReflectionContext
912887
.readBytes(RemoteAddress(AllocationPoolAddr), sizeof(PoolRange));
913888
auto Pool = reinterpret_cast<const PoolRange *>(PoolBytes.get());
914889
if (!Pool)
915-
return;
916-
890+
return false;
891+
917892
auto TrailerPtr = Pool->Begin + Pool->Remaining;
918893
while (TrailerPtr) {
919894
auto TrailerBytes = getReader()
@@ -922,38 +897,31 @@ class ReflectionContext
922897
if (!Trailer)
923898
break;
924899
auto PoolStart = TrailerPtr - Trailer->PoolSize;
925-
printf("Found pool at %#llx, allocation size is %llu\n",
926-
PoolStart, Trailer->PoolSize + sizeof(PoolTrailer));
927-
928900
auto PoolBytes = getReader()
929901
.readBytes(RemoteAddress(PoolStart), Trailer->PoolSize);
930902
auto PoolPtr = (const char *)PoolBytes.get();
931903
if (!PoolPtr)
932904
break;
905+
933906
uintptr_t Offset = 0;
934907
while (Offset < Trailer->PoolSize) {
935908
auto AllocationPtr = PoolPtr + Offset;
936909
auto Header = (const AllocationHeader *)AllocationPtr;
937910
if (Header->Size == 0)
938911
break;
939-
auto Allocation = AllocationPtr + sizeof(AllocationHeader);
940912
auto RemoteAddr = PoolStart + Offset + sizeof(AllocationHeader);
941-
printf("Allocation tag %u size %u offset %#lx, remote address %#llx\n", Header->Tag, Header->Size, Offset, RemoteAddr);
942-
943-
switch (Header->Tag) {
944-
case GenericMetadataCacheTag: {
945-
dumpGenericMetadataCacheEntry(Allocation);
946-
break;
947-
}
948-
default:
949-
break;
950-
}
913+
MetadataAllocation Allocation;
914+
Allocation.Tag = Header->Tag;
915+
Allocation.Ptr = RemoteAddr;
916+
Allocation.Size = Header->Size;
917+
Call(Allocation);
951918

952919
Offset += sizeof(AllocationHeader) + Header->Size;
953920
}
954921

955922
TrailerPtr = Trailer->PrevTrailer;
956923
}
924+
return true;
957925
}
958926

959927
private:

include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ char *
159159
swift_reflection_copyDemangledNameForTypeRef(
160160
SwiftReflectionContextRef ContextRef, swift_typeref_t OpaqueTypeRef);
161161

162+
SWIFT_REMOTE_MIRROR_LINKAGE
163+
char *
164+
swift_reflection_copyDemangledNameForProtocolDescriptor(
165+
SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto);
166+
162167
/// Returns a structure describing the layout of a value of a typeref.
163168
/// For classes, this returns the reference value itself.
164169
SWIFT_REMOTE_MIRROR_LINKAGE
@@ -284,10 +289,24 @@ size_t swift_reflection_demangle(const char *MangledName, size_t Length,
284289
char *OutDemangledName, size_t MaxLength);
285290

286291
SWIFT_REMOTE_MIRROR_LINKAGE
287-
void swift_reflection_dumpConformanceCache(SwiftReflectionContextRef ContextRef);
292+
int swift_reflection_iterateConformanceCache(
293+
SwiftReflectionContextRef ContextRef,
294+
void (*Call)(swift_reflection_ptr_t Type,
295+
swift_reflection_ptr_t Proto,
296+
void *ContextPtr),
297+
void *ContextPtr);
298+
299+
SWIFT_REMOTE_MIRROR_LINKAGE
300+
int swift_reflection_iterateMetadataAllocations(
301+
SwiftReflectionContextRef ContextRef,
302+
void (*Call)(swift_metadata_allocation_t Allocation,
303+
void *ContextPtr),
304+
void *ContextPtr);
288305

289306
SWIFT_REMOTE_MIRROR_LINKAGE
290-
void swift_reflection_dumpMetadataAllocations(SwiftReflectionContextRef ContextRef);
307+
swift_reflection_ptr_t swift_reflection_allocationMetadataPointer(
308+
SwiftReflectionContextRef ContextRef,
309+
swift_metadata_allocation_t Allocation);
291310

292311
#ifdef __cplusplus
293312
} // extern "C"

include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ typedef struct swift_childinfo {
141141
swift_typeref_t TR;
142142
} swift_childinfo_t;
143143

144+
enum swift_metadata_allocation_tag {
145+
SWIFT_GENERIC_METADATA_CACHE_ALLOCATION = 14,
146+
};
147+
148+
// Tags other than those defined in swift_metadata_allocation_tag will be used
149+
// and must be treated as unknown.
150+
typedef int swift_metadata_allocation_tag_t;
151+
152+
typedef struct swift_metadata_allocation {
153+
swift_metadata_allocation_tag_t Tag;
154+
swift_reflection_ptr_t Ptr;
155+
unsigned Size;
156+
} swift_metadata_allocation_t;
157+
144158
/// An opaque pointer to a context which maintains state and
145159
/// caching of reflection structure for heap instances.
146160
typedef struct SwiftReflectionContext *SwiftReflectionContextRef;

stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,18 @@ swift_reflection_copyDemangledNameForTypeRef(
280280
return strdup(Name.c_str());
281281
}
282282

283+
SWIFT_REMOTE_MIRROR_LINKAGE
284+
char *
285+
swift_reflection_copyDemangledNameForProtocolDescriptor(
286+
SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto) {
287+
auto Context = ContextRef->nativeContext;
288+
289+
Demangle::Demangler Dem;
290+
auto Demangling = Context->readDemanglingForContextDescriptor(Proto, Dem);
291+
auto Name = nodeToString(Demangling);
292+
return strdup(Name.c_str());
293+
}
294+
283295
swift_typeref_t
284296
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
285297
unsigned Index) {
@@ -573,12 +585,41 @@ size_t swift_reflection_demangle(const char *MangledName, size_t Length,
573585
return Demangled.size();
574586
}
575587

576-
void swift_reflection_dumpConformanceCache(SwiftReflectionContextRef ContextRef) {
588+
int swift_reflection_iterateConformanceCache(
589+
SwiftReflectionContextRef ContextRef,
590+
void (*Call)(swift_reflection_ptr_t Type,
591+
swift_reflection_ptr_t Proto,
592+
void *ContextPtr),
593+
void *ContextPtr) {
594+
auto Context = ContextRef->nativeContext;
595+
return Context->iterateConformances([&](auto Type, auto Proto) {
596+
Call(Type, Proto, ContextPtr);
597+
});
598+
}
599+
600+
int swift_reflection_iterateMetadataAllocations(
601+
SwiftReflectionContextRef ContextRef,
602+
void (*Call)(swift_metadata_allocation_t Allocation,
603+
void *ContextPtr),
604+
void *ContextPtr) {
577605
auto Context = ContextRef->nativeContext;
578-
Context->dumpConformances();
606+
return Context->iterateMetadataAllocations([&](auto Allocation) {
607+
swift_metadata_allocation CAllocation;
608+
CAllocation.Tag = Allocation.Tag;
609+
CAllocation.Ptr = Allocation.Ptr;
610+
CAllocation.Size = Allocation.Size;
611+
Call(CAllocation, ContextPtr);
612+
});
579613
}
580614

581-
void swift_reflection_dumpMetadataAllocations(SwiftReflectionContextRef ContextRef) {
615+
SWIFT_REMOTE_MIRROR_LINKAGE
616+
swift_reflection_ptr_t swift_reflection_allocationMetadataPointer(
617+
SwiftReflectionContextRef ContextRef,
618+
swift_metadata_allocation_t Allocation) {
582619
auto Context = ContextRef->nativeContext;
583-
Context->dumpMetadataAllocations();
620+
NativeReflectionContext::MetadataAllocation NativeAllocation;
621+
NativeAllocation.Tag = Allocation.Tag;
622+
NativeAllocation.Ptr = Allocation.Ptr;
623+
NativeAllocation.Size = Allocation.Size;
624+
return Context->allocationMetadataPointer(NativeAllocation);
584625
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import SwiftRemoteMirror
2+
3+
extension DefaultStringInterpolation {
4+
mutating func appendInterpolation(hex: swift_reflection_ptr_t) {
5+
appendInterpolation("0x")
6+
appendInterpolation(String(hex, radix: 16))
7+
}
8+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import SwiftRemoteMirror
2+
3+
extension SwiftReflectionContextRef {
4+
func name(metadata: swift_reflection_ptr_t) -> String? {
5+
let tr = swift_reflection_typeRefForMetadata(self, UInt(metadata));
6+
guard tr != 0 else { return nil }
7+
8+
guard let cstr = swift_reflection_copyDemangledNameForTypeRef(self, tr)
9+
else { return nil }
10+
defer { free(cstr) }
11+
return String(cString: cstr)
12+
}
13+
14+
func name(proto: swift_reflection_ptr_t) -> String? {
15+
guard let cstr = swift_reflection_copyDemangledNameForProtocolDescriptor(
16+
self, proto) else { return nil }
17+
defer { free(cstr) }
18+
return String(cString: cstr)
19+
}
20+
21+
func iterateConformanceCache(
22+
call: (swift_reflection_ptr_t, swift_reflection_ptr_t) -> Void) -> Bool {
23+
var call = call
24+
let success = swift_reflection_iterateConformanceCache(self, {
25+
let callPtr = $2!.bindMemory(to: ((swift_reflection_ptr_t, swift_reflection_ptr_t) -> Void).self, capacity: 1)
26+
callPtr.pointee($0, $1)
27+
}, &call)
28+
return success != 0
29+
}
30+
31+
func iterateMetadataAllocations(call: (swift_metadata_allocation_t) -> Void)
32+
-> Bool {
33+
var call = call
34+
let success = swift_reflection_iterateMetadataAllocations(self, {
35+
let callPtr = $1!.bindMemory(to:
36+
((swift_metadata_allocation_t) -> Void).self, capacity: 1)
37+
callPtr.pointee($0)
38+
}, &call)
39+
return success != 0
40+
}
41+
42+
func metadataPointer(allocation: swift_metadata_allocation_t)
43+
-> swift_reflection_ptr_t {
44+
return swift_reflection_allocationMetadataPointer(self, allocation)
45+
}
46+
}

0 commit comments

Comments
 (0)