Skip to content

Commit ff68796

Browse files
committed
[Metadata reader] Handle symbolic references in mangled names.
When reading a mangled name, make sure to cope with embedded null bytes that show up in symbolic references. When demangling such a name, handle symbolic references.
1 parent 850a2a7 commit ff68796

File tree

2 files changed

+139
-16
lines changed

2 files changed

+139
-16
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 132 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,131 @@ class MetadataReader {
14411441
return name;
14421442
}
14431443

1444+
/// The kind of mangled name to read.
1445+
enum class MangledNameKind {
1446+
Type,
1447+
Symbol,
1448+
};
1449+
1450+
/// Clone the given demangle node into the demangler \c dem.
1451+
static Demangle::NodePointer cloneDemangleNode(Demangle::NodePointer node,
1452+
Demangler &dem) {
1453+
if (!node)
1454+
return nullptr;
1455+
1456+
Demangle::NodePointer newNode;
1457+
if (node->hasText())
1458+
newNode = dem.createNode(node->getKind(), node->getText());
1459+
else if (node->hasIndex())
1460+
newNode = dem.createNode(node->getKind(), node->getIndex());
1461+
else
1462+
newNode = dem.createNode(node->getKind());
1463+
1464+
for (auto child : *node) {
1465+
newNode->addChild(cloneDemangleNode(child, dem), dem);
1466+
}
1467+
return newNode;
1468+
}
1469+
1470+
/// Read a mangled name at the given remote address and return the
1471+
/// demangle tree.
1472+
Demangle::NodePointer readMangledName(RemoteAddress address,
1473+
MangledNameKind kind,
1474+
Demangler &dem) {
1475+
// Read chunks of the mangled name, for which the string can be
1476+
// prematurely terminated by a symbolic reference.
1477+
std::string mangledName;
1478+
RemoteAddress currentAddress = address;
1479+
unsigned index = 0;
1480+
while (true) {
1481+
// Read the next chunk.
1482+
std::string chunk;
1483+
if (!Reader->readString(currentAddress, chunk))
1484+
return nullptr;
1485+
1486+
// Move the address forward and add the next chunk.
1487+
currentAddress =
1488+
RemoteAddress(currentAddress.getAddressData() + chunk.size() + 1);
1489+
mangledName += std::move(chunk);
1490+
1491+
// Scan through the mangled name to skip over symbolic references.
1492+
unsigned end = mangledName.size();
1493+
while (index < end) {
1494+
char c = mangledName[index];
1495+
1496+
// Figure out how far to step in the string.
1497+
unsigned step = 1;
1498+
if (c >= '\x01' && c <= '\x17') {
1499+
step += sizeof(uint32_t);
1500+
}
1501+
else if (c >= '\x18' && c <= '\x1F') {
1502+
step += sizeof(typename Runtime::StoredPointer);
1503+
}
1504+
1505+
// If we would be stepping past the end, break out.
1506+
if (index + step > end)
1507+
break;
1508+
1509+
index += step;
1510+
}
1511+
1512+
// If we didn't make it to the end, the '\0' is significant. Add it to the
1513+
// mangled name and
1514+
if (index < end) {
1515+
mangledName.push_back('\0');
1516+
continue;
1517+
}
1518+
1519+
// We're done.
1520+
break;
1521+
}
1522+
1523+
// Install our own symbolic reference resolver
1524+
dem.setSymbolicReferenceResolver([&](SymbolicReferenceKind kind,
1525+
Directness directness,
1526+
int32_t offset,
1527+
const void *base) -> NodePointer {
1528+
// Resolve the reference to a remote address.
1529+
auto offsetInMangledName = (const char *)base - mangledName.data();
1530+
auto remoteAddress =
1531+
address.getAddressData() + offsetInMangledName + offset;
1532+
1533+
if (directness == Directness::Indirect) {
1534+
if (auto indirectAddress = readPointerValue(remoteAddress)) {
1535+
remoteAddress = *indirectAddress;
1536+
} else {
1537+
return nullptr;
1538+
}
1539+
}
1540+
1541+
switch (kind) {
1542+
case Demangle::SymbolicReferenceKind::Context: {
1543+
Demangler innerDemangler;
1544+
auto result = readDemanglingForContextDescriptor(
1545+
remoteAddress, innerDemangler);
1546+
1547+
return cloneDemangleNode(result, dem);
1548+
}
1549+
}
1550+
1551+
return nullptr;
1552+
});
1553+
1554+
NodePointer result;
1555+
switch (kind) {
1556+
case MangledNameKind::Type:
1557+
result = dem.demangleType(mangledName);
1558+
break;
1559+
1560+
case MangledNameKind::Symbol:
1561+
result = dem.demangleSymbol(mangledName);
1562+
break;
1563+
}
1564+
1565+
dem.setSymbolicReferenceResolver(nullptr);
1566+
return result;
1567+
}
1568+
14441569
/// Read and demangle the name of an anonymous context.
14451570
Demangle::NodePointer demangleAnonymousContextName(
14461571
ContextDescriptorRef contextRef,
@@ -1455,13 +1580,9 @@ class MetadataReader {
14551580
auto mangledContextName = anonymousBuffer->getMangledContextName();
14561581
auto mangledNameAddress = resolveRelativeField(contextRef,
14571582
mangledContextName->name);
1458-
1459-
// FIXME: Symbolic references can break this
1460-
std::string mangledName;
1461-
if (!Reader->readString(RemoteAddress(mangledNameAddress), mangledName))
1462-
return nullptr;
1463-
1464-
return dem.demangleSymbol(mangledName);
1583+
return readMangledName(RemoteAddress(mangledNameAddress),
1584+
MangledNameKind::Symbol,
1585+
dem);
14651586
}
14661587

14671588
/// If we have a context whose parent context is an anonymous context
@@ -1622,15 +1743,10 @@ class MetadataReader {
16221743
auto extendedContextAddress =
16231744
resolveRelativeField(descriptor, extensionBuffer->ExtendedContext);
16241745

1625-
// FIXME: Symbolic references can break this
1626-
std::string mangledExtendedContext;
1627-
if (!Reader->readString(RemoteAddress(extendedContextAddress),
1628-
mangledExtendedContext))
1629-
return nullptr;
1630-
1631-
auto demangledExtendedContext = dem.demangleType(mangledExtendedContext);
1632-
if (!demangledExtendedContext)
1633-
return nullptr;
1746+
auto demangledExtendedContext =
1747+
readMangledName(RemoteAddress(extendedContextAddress),
1748+
MangledNameKind::Type,
1749+
dem);
16341750

16351751
// FIXME: If there are generic requirements, turn them into a demangle
16361752
// tree.

test/RemoteAST/extensions.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,10 @@ extension Int {
1111

1212
// CHECK: Int.Inner
1313
printType(Int.Inner.self)
14+
15+
extension Int.Inner {
16+
struct MoreInner { }
17+
}
18+
19+
// CHECK: Int.Inner.MoreInner
20+
printType(Int.Inner.MoreInner.self)

0 commit comments

Comments
 (0)