Skip to content

Commit 633471c

Browse files
committed
Reflection: Share demangler with MetadataReader.
TypeRefBuilder and MetadataReader had nearly identical symbolic reference resolvers, but diverged because TypeRefBuilder had its own local/remote address management mechanism, and because TypeRefBuilder tries to resolve opaque types to their underlying types, whereas other MetadataReader clients want to preserve them as written in source. The first problem has been addressed by making TypeRefBuilder use `RemoteRef` everywhere, and the second can be handled with a flag (and might be able to be handled more elegantly with some more refactoring of general opaque type handling in MetadataReader).
1 parent 8c4df3b commit 633471c

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)