Skip to content

Demangler: Make symbolic reference resolver part of demangle(Symbol|Type) calls. #27181

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
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
28 changes: 13 additions & 15 deletions include/swift/Demangling/Demangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,11 @@ class Demangler : public NodeFactory {
int NumWords;
StringRef Text;
size_t Pos;
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver;

public:
DemangleInitRAII(Demangler &Dem, StringRef MangledName);
DemangleInitRAII(Demangler &Dem, StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver);
~DemangleInitRAII();
};
friend DemangleInitRAII;
Expand Down Expand Up @@ -587,39 +589,35 @@ class Demangler : public NodeFactory {

void clear() override;

/// Install a resolver for symbolic references in a mangled string.
void setSymbolicReferenceResolver(
std::function<SymbolicReferenceResolver_t> resolver) {
SymbolicReferenceResolver = resolver;
}

/// Take the symbolic reference resolver.
std::function<SymbolicReferenceResolver_t> &&
takeSymbolicReferenceResolver() {
return std::move(SymbolicReferenceResolver);
}

/// Demangle the given symbol and return the parse tree.
///
/// \param MangledName The mangled symbol string, which start with the
/// mangling prefix $S.
/// \param SymbolicReferenceResolver A function invoked to resolve symbolic references in
/// the string. If null, then symbolic references will cause the demangle to fail.
///
/// \returns A parse tree for the demangled string - or a null pointer
/// on failure.
/// The lifetime of the returned node tree ends with the lifetime of the
/// Demangler or with a call of clear().
NodePointer demangleSymbol(StringRef MangledName);
NodePointer demangleSymbol(StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver
= nullptr);

/// Demangle the given type and return the parse tree.
///
/// \param MangledName The mangled type string, which does _not_ start with
/// the mangling prefix $S.
/// \param SymbolicReferenceResolver A function invoked to resolve symbolic references in
/// the string. If null, then symbolic references will cause the demangle to fail.
///
/// \returns A parse tree for the demangled string - or a null pointer
/// on failure.
/// The lifetime of the returned node tree ends with the lifetime of the
/// Demangler or with a call of clear().
NodePointer demangleType(StringRef MangledName);
NodePointer demangleType(StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver
= nullptr);
};

/// A demangler which uses stack space for its initial memory.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Reflection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class ReflectionContext

explicit ReflectionContext(std::shared_ptr<MemoryReader> reader)
: super(std::move(reader)) {
getBuilder().setSymbolicReferenceResolverReader(*this);
getBuilder().setMetadataReader(*this);
}

ReflectionContext(const ReflectionContext &other) = delete;
Expand Down
19 changes: 16 additions & 3 deletions include/swift/Reflection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,14 +483,27 @@ class TypeRefBuilder {

uint64_t getRemoteAddrOfTypeRefPointer(const void *pointer);

std::function<auto (SymbolicReferenceKind kind,
Directness directness,
int32_t offset, const void *base) -> Demangle::Node *>
SymbolicReferenceResolver;

std::string normalizeReflectionName(StringRef name);
bool reflectionNameMatches(StringRef reflectionName,
StringRef searchName);

Demangle::Node *demangleTypeRef(StringRef mangledName) {
return Dem.demangleType(mangledName, SymbolicReferenceResolver);
}

public:
template<typename Runtime>
void setSymbolicReferenceResolverReader(
void setMetadataReader(
remote::MetadataReader<Runtime, TypeRefBuilder> &reader) {
// Have the TypeRefBuilder demangle symbolic references by reading their
// demangling out of the referenced context descriptors in the target
// process.
Dem.setSymbolicReferenceResolver(
SymbolicReferenceResolver =
[this, &reader](SymbolicReferenceKind kind,
Directness directness,
int32_t offset, const void *base) -> Demangle::Node * {
Expand Down Expand Up @@ -531,7 +544,7 @@ class TypeRefBuilder {
}

return nullptr;
});
};

OpaqueUnderlyingTypeReader =
[&reader](const void *descriptor, unsigned ordinal) -> const TypeRef* {
Expand Down
12 changes: 5 additions & 7 deletions include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -1690,9 +1690,8 @@ class MetadataReader {
break;
}

// Install our own symbolic reference resolver
auto oldSymbolicReferenceResolver = dem.takeSymbolicReferenceResolver();
dem.setSymbolicReferenceResolver([&](SymbolicReferenceKind kind,
// Symbolic reference resolver for the demangle operation below.
auto symbolicReferenceResolver = [&](SymbolicReferenceKind kind,
Directness directness,
int32_t offset,
const void *base) ->
Expand Down Expand Up @@ -1726,20 +1725,19 @@ class MetadataReader {
}

return nullptr;
});
};

swift::Demangle::NodePointer result;
switch (kind) {
case MangledNameKind::Type:
result = dem.demangleType(mangledName);
result = dem.demangleType(mangledName, symbolicReferenceResolver);
break;

case MangledNameKind::Symbol:
result = dem.demangleSymbol(mangledName);
result = dem.demangleSymbol(mangledName, symbolicReferenceResolver);
break;
}

dem.setSymbolicReferenceResolver(std::move(oldSymbolicReferenceResolver));
return result;
}

Expand Down
21 changes: 15 additions & 6 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,18 +493,21 @@ void Demangler::clear() {
}

Demangler::DemangleInitRAII::DemangleInitRAII(Demangler &Dem,
StringRef MangledName)
StringRef MangledName,
std::function<SymbolicReferenceResolver_t> TheSymbolicReferenceResolver)
// Save the current demangler state so we can restore it.
: Dem(Dem),
NodeStack(Dem.NodeStack), Substitutions(Dem.Substitutions),
NumWords(Dem.NumWords), Text(Dem.Text), Pos(Dem.Pos)
NumWords(Dem.NumWords), Text(Dem.Text), Pos(Dem.Pos),
SymbolicReferenceResolver(std::move(Dem.SymbolicReferenceResolver))
{
// Reset the demangler state for a nested job.
Dem.NodeStack.init(Dem, 16);
Dem.Substitutions.init(Dem, 16);
Dem.NumWords = 0;
Dem.Text = MangledName;
Dem.Pos = 0;
Dem.SymbolicReferenceResolver = std::move(TheSymbolicReferenceResolver);
}

Demangler::DemangleInitRAII::~DemangleInitRAII() {
Expand All @@ -514,10 +517,13 @@ Demangler::DemangleInitRAII::~DemangleInitRAII() {
Dem.NumWords = NumWords;
Dem.Text = Text;
Dem.Pos = Pos;
Dem.SymbolicReferenceResolver = std::move(SymbolicReferenceResolver);
}

NodePointer Demangler::demangleSymbol(StringRef MangledName) {
DemangleInitRAII state(*this, MangledName);
NodePointer Demangler::demangleSymbol(StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver) {
DemangleInitRAII state(*this, MangledName,
std::move(SymbolicReferenceResolver));

// Demangle old-style class and protocol names, which are still used in the
// ObjC metadata.
Expand Down Expand Up @@ -561,8 +567,10 @@ NodePointer Demangler::demangleSymbol(StringRef MangledName) {
return topLevel;
}

NodePointer Demangler::demangleType(StringRef MangledName) {
DemangleInitRAII state(*this, MangledName);
NodePointer Demangler::demangleType(StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver) {
DemangleInitRAII state(*this, MangledName,
std::move(SymbolicReferenceResolver));

parseAndPushNodes();

Expand Down Expand Up @@ -701,6 +709,7 @@ NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind,
NodePointer resolved = nullptr;
if (SymbolicReferenceResolver)
resolved = SymbolicReferenceResolver(kind, direct, value, at);

// With no resolver, or a resolver that failed, refuse to demangle further.
if (!resolved)
return nullptr;
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Utils/SpecializationMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AttributeDemangler : public Demangle::Demangler {
public:
void demangleAndAddAsChildren(StringRef MangledSpecialization,
NodePointer Parent) {
DemangleInitRAII state(*this, MangledSpecialization);
DemangleInitRAII state(*this, MangledSpecialization, nullptr);
if (!parseAndPushNodes()) {
llvm::errs() << "Can't demangle: " << MangledSpecialization << '\n';
abort();
Expand Down
45 changes: 23 additions & 22 deletions stdlib/public/Reflection/TypeRefBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ TypeRefBuilder::getRemoteAddrOfTypeRefPointer(const void *pointer) {
TypeRefBuilder::TypeRefBuilder() : TC(*this) {}

/// Normalize a mangled name so it can be matched with string equality.
static std::string normalizeReflectionName(Demangler &dem, StringRef reflectionName) {
std::string
TypeRefBuilder::normalizeReflectionName(StringRef reflectionName) {
reflectionName = dropSwiftManglingPrefix(reflectionName);

// Remangle the reflection name to resolve symbolic references.
if (auto node = dem.demangleType(reflectionName)) {
if (auto node = demangleTypeRef(reflectionName)) {
return mangleNode(node);
}

Expand All @@ -64,10 +65,10 @@ static std::string normalizeReflectionName(Demangler &dem, StringRef reflectionN
}

/// Determine whether the given reflection protocol name matches.
static bool reflectionNameMatches(Demangler &dem,
StringRef reflectionName,
StringRef searchName) {
auto normalized = normalizeReflectionName(dem, reflectionName);
bool
TypeRefBuilder::reflectionNameMatches(StringRef reflectionName,
StringRef searchName) {
auto normalized = normalizeReflectionName(reflectionName);
return searchName.equals(normalized);
}

Expand All @@ -91,12 +92,12 @@ lookupTypeWitness(const std::string &MangledTypeName,
uint64_t NameOffset = Info.AssociatedType.SectionOffset
- Info.ReflectionString.SectionOffset;
for (const auto &AssocTyDescriptor : Info.AssociatedType.Metadata) {
if (!reflectionNameMatches(Dem,
if (!reflectionNameMatches(
AssocTyDescriptor.getMangledConformingTypeName(TypeRefOffset),
MangledTypeName))
continue;

if (!reflectionNameMatches(Dem,
if (!reflectionNameMatches(
AssocTyDescriptor.getMangledProtocolTypeName(TypeRefOffset),
Protocol))
continue;
Expand All @@ -107,7 +108,7 @@ lookupTypeWitness(const std::string &MangledTypeName,

auto SubstitutedTypeName =
AssocTy.getMangledSubstitutedTypeName(TypeRefOffset);
auto Demangled = Dem.demangleType(SubstitutedTypeName);
auto Demangled = demangleTypeRef(SubstitutedTypeName);
auto *TypeWitness = swift::Demangle::decodeMangledType(*this, Demangled);

AssociatedTypeCache.insert(std::make_pair(key, TypeWitness));
Expand All @@ -129,7 +130,7 @@ lookupSuperclass(const TypeRef *TR) {

auto TypeRefOffset = FD.second->Field.SectionOffset
- FD.second->TypeReference.SectionOffset;
auto Demangled = Dem.demangleType(FD.first->getSuperclass(TypeRefOffset));
auto Demangled = demangleTypeRef(FD.first->getSuperclass(TypeRefOffset));
auto Unsubstituted = swift::Demangle::decodeMangledType(*this, Demangled);
if (!Unsubstituted)
return nullptr;
Expand Down Expand Up @@ -164,7 +165,7 @@ TypeRefBuilder::getFieldTypeInfo(const TypeRef *TR) {
if (!FD.hasMangledTypeName())
continue;
auto CandidateMangledName = FD.getMangledTypeName(TypeRefOffset);
auto NormalizedName = normalizeReflectionName(Dem, CandidateMangledName);
auto NormalizedName = normalizeReflectionName(CandidateMangledName);
FieldTypeInfoCache[NormalizedName] = {&FD, &Info};
Dem.clear();
}
Expand Down Expand Up @@ -204,7 +205,7 @@ bool TypeRefBuilder::getFieldTypeRefs(
continue;
}

auto Demangled = Dem.demangleType(Field.getMangledTypeName(TypeRefOffset));
auto Demangled = demangleTypeRef(Field.getMangledTypeName(TypeRefOffset));
auto Unsubstituted = swift::Demangle::decodeMangledType(*this, Demangled);
if (!Unsubstituted)
return false;
Expand Down Expand Up @@ -244,7 +245,7 @@ TypeRefBuilder::getBuiltinTypeInfo(const TypeRef *TR) {
continue;
auto CandidateMangledName =
BuiltinTypeDescriptor.getMangledTypeName(TypeRefOffset);
if (!reflectionNameMatches(Dem, CandidateMangledName, MangledName))
if (!reflectionNameMatches(CandidateMangledName, MangledName))
continue;
return &BuiltinTypeDescriptor;
}
Expand Down Expand Up @@ -277,7 +278,7 @@ TypeRefBuilder::getClosureContextInfo(const CaptureDescriptor &CD,
const TypeRef *TR = nullptr;
if (i->hasMangledTypeName()) {
auto MangledName = i->getMangledTypeName(TypeRefOffset);
auto DemangleTree = Dem.demangleType(MangledName);
auto DemangleTree = demangleTypeRef(MangledName);
TR = swift::Demangle::decodeMangledType(*this, DemangleTree);
}
Info.CaptureTypes.push_back(TR);
Expand All @@ -287,7 +288,7 @@ TypeRefBuilder::getClosureContextInfo(const CaptureDescriptor &CD,
const TypeRef *TR = nullptr;
if (i->hasMangledTypeName()) {
auto MangledName = i->getMangledTypeName(TypeRefOffset);
auto DemangleTree = Dem.demangleType(MangledName);
auto DemangleTree = demangleTypeRef(MangledName);
TR = swift::Demangle::decodeMangledType(*this, DemangleTree);
}

Expand All @@ -312,7 +313,7 @@ TypeRefBuilder::getClosureContextInfo(const CaptureDescriptor &CD,
void
TypeRefBuilder::dumpTypeRef(StringRef MangledName,
std::ostream &OS, bool printTypeName) {
auto DemangleTree = Dem.demangleType(MangledName);
auto DemangleTree = demangleTypeRef(MangledName);
auto TypeName = nodeToString(DemangleTree);
OS << TypeName << '\n';
auto TR = swift::Demangle::decodeMangledType(*this, DemangleTree);
Expand All @@ -333,7 +334,7 @@ void TypeRefBuilder::dumpFieldSection(std::ostream &OS) {
uint64_t NameOffset = sections.Field.SectionOffset
- sections.ReflectionString.SectionOffset;
for (const auto &descriptor : sections.Field.Metadata) {
auto TypeDemangling = Dem.demangleType(
auto TypeDemangling = demangleTypeRef(
dropSwiftManglingPrefix(descriptor.getMangledTypeName(TypeRefOffset)));
auto TypeName = nodeToString(TypeDemangling);
OS << TypeName << '\n';
Expand Down Expand Up @@ -363,10 +364,10 @@ void TypeRefBuilder::dumpAssociatedTypeSection(std::ostream &OS) {
uint64_t NameOffset = sections.AssociatedType.SectionOffset
- sections.ReflectionString.SectionOffset;
for (const auto &descriptor : sections.AssociatedType.Metadata) {
auto conformingTypeNode = Dem.demangleType(
auto conformingTypeNode = demangleTypeRef(
descriptor.getMangledConformingTypeName(TypeRefOffset));
auto conformingTypeName = nodeToString(conformingTypeNode);
auto protocolNode = Dem.demangleType(dropSwiftManglingPrefix(
auto protocolNode = demangleTypeRef(dropSwiftManglingPrefix(
descriptor.getMangledProtocolTypeName(TypeRefOffset)));
auto protocolName = nodeToString(protocolNode);

Expand All @@ -388,10 +389,10 @@ void TypeRefBuilder::dumpBuiltinTypeSection(std::ostream &OS) {
uint64_t TypeRefOffset = sections.Builtin.SectionOffset
- sections.TypeReference.SectionOffset;
for (const auto &descriptor : sections.Builtin.Metadata) {
auto typeName =
Demangle::demangleTypeAsString(
auto typeNode = demangleTypeRef(
descriptor.getMangledTypeName(TypeRefOffset));

auto typeName = nodeToString(typeNode);

OS << "\n- " << typeName << ":\n";
OS << "Size: " << descriptor.Size << "\n";
OS << "Alignment: " << descriptor.getAlignment() << "\n";
Expand Down
4 changes: 0 additions & 4 deletions stdlib/public/runtime/Casting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ static void _buildNameForMetadata(const Metadata *type,
// Use the remangler to generate a mangled name from the type metadata.

Demangle::Demangler Dem;
// We want to resolve symbolic references to a user-comprehensible
// representation of the referenced context.
Dem.setSymbolicReferenceResolver(ResolveToDemanglingForContext(Dem));

auto demangling = _swift_buildDemanglingForMetadata(type, Dem);
if (demangling == nullptr) {
result = "<<< invalid type >>>";
Expand Down
3 changes: 2 additions & 1 deletion stdlib/public/runtime/Demangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
case ContextDescriptorKind::Extension: {
auto extension = llvm::cast<ExtensionContextDescriptor>(component);
// Demangle the extension self type.
auto selfType = Dem.demangleType(extension->getMangledExtendedContext());
auto selfType = Dem.demangleType(extension->getMangledExtendedContext(),
ResolveToDemanglingForContext(Dem));
if (selfType->getKind() == Node::Kind::Type)
selfType = selfType->getChild(0);

Expand Down
Loading