Skip to content

Commit e5b31c4

Browse files
authored
Merge pull request swiftlang#27383 from jckarter/type-ref-builder-remote-metadata-reader
Reflection: Share demangler with MetadataReader.
2 parents 1653af4 + 633471c commit e5b31c4

File tree

7 files changed

+208
-185
lines changed

7 files changed

+208
-185
lines changed

include/swift/Reflection/ReflectionContext.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,8 @@ class ReflectionContext
107107
using typename super::StoredPointer;
108108

109109
explicit ReflectionContext(std::shared_ptr<MemoryReader> reader)
110-
: super(std::move(reader)) {
111-
getBuilder().setMetadataReader(*this);
112-
}
110+
: super(std::move(reader), *this)
111+
{}
113112

114113
ReflectionContext(const ReflectionContext &other) = delete;
115114
ReflectionContext &operator=(const ReflectionContext &other) = delete;

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 56 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ class ReflectionSection {
6565
size_t size() const {
6666
return Size;
6767
}
68+
69+
bool containsRemoteAddress(uint64_t remoteAddr,
70+
uint64_t size) const {
71+
return Start.getAddressData() <= remoteAddr
72+
&& remoteAddr + size <= Start.getAddressData() + Size;
73+
}
74+
75+
template<typename U>
76+
RemoteRef<U> getRemoteRef(uint64_t remoteAddr) const {
77+
assert(containsRemoteAddress(remoteAddr, sizeof(U)));
78+
auto localAddr = (uint64_t)(uintptr_t)Start.getLocalBuffer()
79+
+ (remoteAddr - Start.getAddressData());
80+
81+
return RemoteRef<U>(remoteAddr, (const U*)localAddr);
82+
}
6883
};
6984

7085
template<typename Self, typename Descriptor>
@@ -239,17 +254,12 @@ class TypeRefBuilder {
239254
using BuiltTypeDecl = Optional<std::string>;
240255
using BuiltProtocolDecl = Optional<std::pair<std::string, bool /*isObjC*/>>;
241256

242-
TypeRefBuilder();
243-
244257
TypeRefBuilder(const TypeRefBuilder &other) = delete;
245258
TypeRefBuilder &operator=(const TypeRefBuilder &other) = delete;
246259

247260
private:
248261
Demangle::Demangler Dem;
249262

250-
std::function<const TypeRef* (const void*, unsigned)>
251-
OpaqueUnderlyingTypeReader;
252-
253263
/// Makes sure dynamically allocated TypeRefs stick around for the life of
254264
/// this TypeRefBuilder and are automatically released.
255265
std::vector<std::unique_ptr<const TypeRef>> TypeRefPool;
@@ -555,106 +565,66 @@ class TypeRefBuilder {
555565
return ReflectionInfos;
556566
}
557567

568+
public:
569+
enum ForTesting_t { ForTesting };
570+
571+
// Only for testing. A TypeRefBuilder built this way will not be able to
572+
// decode records in remote memory.
573+
explicit TypeRefBuilder(ForTesting_t) : TC(*this) {}
574+
558575
private:
559576
std::vector<ReflectionInfo> ReflectionInfos;
560-
561-
uint64_t getRemoteAddrOfTypeRefPointer(const void *pointer);
562-
563-
std::function<auto (SymbolicReferenceKind kind,
564-
Directness directness,
565-
int32_t offset, const void *base) -> Demangle::Node *>
566-
SymbolicReferenceResolver;
567-
577+
568578
std::string normalizeReflectionName(RemoteRef<char> name);
569579
bool reflectionNameMatches(RemoteRef<char> reflectionName,
570580
StringRef searchName);
571581

572582
public:
583+
RemoteRef<char> readTypeRef(uint64_t remoteAddr);
584+
573585
template<typename Record, typename Field>
574586
RemoteRef<char> readTypeRef(RemoteRef<Record> record,
575587
const Field &field) {
576588
uint64_t remoteAddr = record.resolveRelativeFieldData(field);
577-
// TODO: This assumes the remote and local buffer addresses are contiguous,
578-
// which should not be a guarantee that MemoryReaders need to maintain.
579-
// Ultimately this should use the MemoryReader to read the string.
580-
auto localAddr = (uint64_t)(uintptr_t)record.getLocalBuffer()
581-
+ (int64_t)(remoteAddr - record.getAddressData());
582-
583-
// Skip the mangling prefix, if any.
584-
auto localPtr = (const char *)localAddr;
585-
if (localPtr[0] == '$' && localPtr[1] == 's') {
586-
remoteAddr += 2;
587-
localPtr += 2;
588-
}
589589

590-
return RemoteRef<char>(remoteAddr, localPtr);
590+
return readTypeRef(remoteAddr);
591591
}
592-
592+
593593
StringRef getTypeRefString(RemoteRef<char> record) {
594594
return Demangle::makeSymbolicMangledNameStringRef(record.getLocalBuffer());
595595
}
596596

597-
Demangle::Node *demangleTypeRef(RemoteRef<char> string) {
598-
// TODO: Use the remote addr in the RemoteRef to resolve and read from
599-
// remote addresses in the resolver function.
600-
return Dem.demangleType(getTypeRefString(string),
601-
SymbolicReferenceResolver);
602-
}
597+
private:
598+
// These fields are captured from the MetadataReader template passed into the
599+
// TypeRefBuilder struct, to isolate its template-ness from the rest of
600+
// TypeRefBuilder.
601+
unsigned PointerSize;
602+
std::function<Demangle::Node * (RemoteRef<char>)>
603+
TypeRefDemangler;
604+
std::function<const TypeRef* (const void*, unsigned)>
605+
OpaqueUnderlyingTypeReader;
603606

607+
public:
604608
template<typename Runtime>
605-
void setMetadataReader(
606-
remote::MetadataReader<Runtime, TypeRefBuilder> &reader) {
607-
// Have the TypeRefBuilder demangle symbolic references by reading their
608-
// demangling out of the referenced context descriptors in the target
609-
// process.
610-
SymbolicReferenceResolver =
611-
[this, &reader](SymbolicReferenceKind kind,
612-
Directness directness,
613-
int32_t offset, const void *base) -> Demangle::Node * {
614-
// Resolve the reference to a remote address.
615-
auto remoteAddress = getRemoteAddrOfTypeRefPointer(base);
616-
if (remoteAddress == 0)
617-
return nullptr;
618-
619-
auto address = remoteAddress + offset;
620-
if (directness == Directness::Indirect) {
621-
if (auto indirectAddress = reader.readPointerValue(address)) {
622-
address = *indirectAddress;
623-
} else {
624-
return nullptr;
625-
}
626-
}
627-
628-
switch (kind) {
629-
case Demangle::SymbolicReferenceKind::Context: {
630-
auto context = reader.readContextDescriptor(address);
631-
if (!context)
632-
return nullptr;
633-
// Try to preserve a reference to an OpaqueTypeDescriptor symbolically,
634-
// since we'd like to read out and resolve the type ref to the
635-
// underlying type if available.
636-
if (context->getKind() == ContextDescriptorKind::OpaqueType) {
637-
return Dem.createNode(
638-
Node::Kind::OpaqueTypeDescriptorSymbolicReference,
639-
context.getAddressData());
640-
}
641-
642-
return reader.buildContextMangling(context, Dem);
643-
}
644-
case Demangle::SymbolicReferenceKind::AccessorFunctionReference:
645-
// The symbolic reference points at a resolver function, but we can't
646-
// execute code in the target process to resolve it from here.
647-
return nullptr;
648-
}
649-
650-
return nullptr;
651-
};
652-
653-
OpaqueUnderlyingTypeReader =
654-
[&reader](const void *descriptor, unsigned ordinal) -> const TypeRef* {
655-
auto context = (typename Runtime::StoredPointer)descriptor;
656-
return reader.readUnderlyingTypeForOpaqueTypeDescriptor(context, ordinal);
657-
};
609+
TypeRefBuilder(remote::MetadataReader<Runtime, TypeRefBuilder> &reader)
610+
: TC(*this),
611+
PointerSize(sizeof(typename Runtime::StoredPointer)),
612+
TypeRefDemangler(
613+
[this, &reader](RemoteRef<char> string) -> Demangle::Node * {
614+
return reader.demangle(string,
615+
remote::MangledNameKind::Type,
616+
Dem, /*useOpaqueTypeSymbolicReferences*/ true);
617+
}),
618+
OpaqueUnderlyingTypeReader(
619+
[&reader](const void *descriptor, unsigned ordinal) -> const TypeRef* {
620+
auto context = (typename Runtime::StoredPointer)descriptor;
621+
return reader.readUnderlyingTypeForOpaqueTypeDescriptor(context,
622+
ordinal);
623+
})
624+
{}
625+
626+
Demangle::Node *demangleTypeRef(RemoteRef<char> string) {
627+
return TypeRefDemangler(string);
658628
}
659629

660630
TypeConverter &getTypeConverter() { return TC; }

include/swift/Remote/MetadataReader.h

Lines changed: 79 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ using FunctionParam = swift::Demangle::FunctionParam<BuiltType>;
4141
template <typename BuilderType>
4242
using TypeDecoder = swift::Demangle::TypeDecoder<BuilderType>;
4343

44+
/// The kind of mangled name to read.
45+
enum class MangledNameKind {
46+
Type,
47+
Symbol,
48+
};
49+
4450
/// A pointer to the local buffer of an object that also remembers the
4551
/// address at which it was stored remotely.
4652
template <typename T>
@@ -287,6 +293,75 @@ class MetadataReader {
287293
ContextDescriptorCache.clear();
288294
}
289295

296+
/// Demangle a mangled name that was read from the given remote address.
297+
Demangle::NodePointer demangle(RemoteRef<char> mangledName,
298+
MangledNameKind kind,
299+
Demangler &dem,
300+
bool useOpaqueTypeSymbolicReferences = false) {
301+
// Symbolic reference resolver for the demangle operation below.
302+
auto symbolicReferenceResolver = [&](SymbolicReferenceKind kind,
303+
Directness directness,
304+
int32_t offset,
305+
const void *base) ->
306+
swift::Demangle::NodePointer {
307+
// Resolve the reference to a remote address.
308+
auto offsetInMangledName =
309+
(const char *)base - mangledName.getLocalBuffer();
310+
auto remoteAddress =
311+
mangledName.getAddressData() + offsetInMangledName + offset;
312+
313+
if (directness == Directness::Indirect) {
314+
if (auto indirectAddress = readPointerValue(remoteAddress)) {
315+
remoteAddress = *indirectAddress;
316+
} else {
317+
return nullptr;
318+
}
319+
}
320+
321+
switch (kind) {
322+
case Demangle::SymbolicReferenceKind::Context: {
323+
auto context = readContextDescriptor(remoteAddress);
324+
if (!context)
325+
return nullptr;
326+
// Try to preserve a reference to an OpaqueTypeDescriptor
327+
// symbolically, since we'd like to read out and resolve the type ref
328+
// to the underlying type if available.
329+
if (useOpaqueTypeSymbolicReferences
330+
&& context->getKind() == ContextDescriptorKind::OpaqueType) {
331+
return dem.createNode(
332+
Node::Kind::OpaqueTypeDescriptorSymbolicReference,
333+
context.getAddressData());
334+
}
335+
336+
return buildContextMangling(context, dem);
337+
}
338+
case Demangle::SymbolicReferenceKind::AccessorFunctionReference: {
339+
// The symbolic reference points at a resolver function, but we can't
340+
// execute code in the target process to resolve it from here.
341+
return nullptr;
342+
}
343+
}
344+
345+
return nullptr;
346+
};
347+
348+
auto mangledNameStr =
349+
Demangle::makeSymbolicMangledNameStringRef(mangledName.getLocalBuffer());
350+
351+
swift::Demangle::NodePointer result;
352+
switch (kind) {
353+
case MangledNameKind::Type:
354+
result = dem.demangleType(mangledNameStr, symbolicReferenceResolver);
355+
break;
356+
357+
case MangledNameKind::Symbol:
358+
result = dem.demangleSymbol(mangledNameStr, symbolicReferenceResolver);
359+
break;
360+
}
361+
362+
return result;
363+
}
364+
290365
/// Given a demangle tree, attempt to turn it into a type.
291366
BuiltType decodeMangledType(NodePointer Node) {
292367
return swift::Demangle::decodeMangledType(Builder, Node);
@@ -1630,12 +1705,6 @@ class MetadataReader {
16301705
return name;
16311706
}
16321707

1633-
/// The kind of mangled name to read.
1634-
enum class MangledNameKind {
1635-
Type,
1636-
Symbol,
1637-
};
1638-
16391708
/// Clone the given demangle node into the demangler \c dem.
16401709
static Demangle::NodePointer cloneDemangleNode(Demangle::NodePointer node,
16411710
Demangler &dem) {
@@ -1655,7 +1724,7 @@ class MetadataReader {
16551724
}
16561725
return newNode;
16571726
}
1658-
1727+
16591728
/// Read a mangled name at the given remote address and return the
16601729
/// demangle tree.
16611730
Demangle::NodePointer readMangledName(RemoteAddress address,
@@ -1709,55 +1778,9 @@ class MetadataReader {
17091778
break;
17101779
}
17111780

1712-
// Symbolic reference resolver for the demangle operation below.
1713-
auto symbolicReferenceResolver = [&](SymbolicReferenceKind kind,
1714-
Directness directness,
1715-
int32_t offset,
1716-
const void *base) ->
1717-
swift::Demangle::NodePointer {
1718-
// Resolve the reference to a remote address.
1719-
auto offsetInMangledName = (const char *)base - mangledName.data();
1720-
auto remoteAddress =
1721-
address.getAddressData() + offsetInMangledName + offset;
1722-
1723-
if (directness == Directness::Indirect) {
1724-
if (auto indirectAddress = readPointerValue(remoteAddress)) {
1725-
remoteAddress = *indirectAddress;
1726-
} else {
1727-
return nullptr;
1728-
}
1729-
}
1730-
1731-
switch (kind) {
1732-
case Demangle::SymbolicReferenceKind::Context: {
1733-
Demangler innerDemangler;
1734-
auto result = readDemanglingForContextDescriptor(
1735-
remoteAddress, innerDemangler);
1736-
1737-
return cloneDemangleNode(result, dem);
1738-
}
1739-
case Demangle::SymbolicReferenceKind::AccessorFunctionReference: {
1740-
// The symbolic reference points at a resolver function, but we can't
1741-
// execute code in the target process to resolve it from here.
1742-
return nullptr;
1743-
}
1744-
}
1745-
1746-
return nullptr;
1747-
};
1748-
1749-
swift::Demangle::NodePointer result;
1750-
switch (kind) {
1751-
case MangledNameKind::Type:
1752-
result = dem.demangleType(mangledName, symbolicReferenceResolver);
1753-
break;
1754-
1755-
case MangledNameKind::Symbol:
1756-
result = dem.demangleSymbol(mangledName, symbolicReferenceResolver);
1757-
break;
1758-
}
1759-
1760-
return result;
1781+
return demangle(RemoteRef<char>(address.getAddressData(),
1782+
mangledName.data()),
1783+
kind, dem);
17611784
}
17621785

17631786
/// Read and demangle the name of an anonymous context.

include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,20 @@ SWIFT_REMOTE_MIRROR_LINKAGE
7272
void
7373
swift_reflection_destroyReflectionContext(SwiftReflectionContextRef Context);
7474

75-
/// Add reflection sections for a loaded Swift image.
75+
/// DEPRECATED. Add reflection sections for a loaded Swift image.
76+
///
77+
/// You probably want to use \c swift_reflection_addImage instead.
7678
SWIFT_REMOTE_MIRROR_LINKAGE
7779
void
7880
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
7981
swift_reflection_info_t Info);
8082

81-
#if defined(__APPLE__) && defined(__MACH__)
8283
/// Add reflection information from a loaded Swift image.
8384
/// Returns true on success, false if the image's memory couldn't be read.
8485
SWIFT_REMOTE_MIRROR_LINKAGE
8586
int
8687
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
8788
swift_addr_t imageStart);
88-
#endif
8989

9090
/// Returns a boolean indicating if the isa mask was successfully
9191
/// read, in which case it is stored in the isaMask out parameter.

0 commit comments

Comments
 (0)