@@ -1441,6 +1441,131 @@ class MetadataReader {
1441
1441
return name;
1442
1442
}
1443
1443
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
+
1444
1569
// / Read and demangle the name of an anonymous context.
1445
1570
Demangle::NodePointer demangleAnonymousContextName (
1446
1571
ContextDescriptorRef contextRef,
@@ -1455,13 +1580,9 @@ class MetadataReader {
1455
1580
auto mangledContextName = anonymousBuffer->getMangledContextName ();
1456
1581
auto mangledNameAddress = resolveRelativeField (contextRef,
1457
1582
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);
1465
1586
}
1466
1587
1467
1588
// / If we have a context whose parent context is an anonymous context
@@ -1622,15 +1743,10 @@ class MetadataReader {
1622
1743
auto extendedContextAddress =
1623
1744
resolveRelativeField (descriptor, extensionBuffer->ExtendedContext );
1624
1745
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);
1634
1750
1635
1751
// FIXME: If there are generic requirements, turn them into a demangle
1636
1752
// tree.
0 commit comments