| 1462 | } |
| 1463 | |
| 1464 | void testPointerToPointerChain() { |
| 1465 | // StructB* → StructB { StructC* } → StructC { field } |
| 1466 | NodeTree tree; |
| 1467 | tree.baseAddress = 0; |
| 1468 | |
| 1469 | Node root; |
| 1470 | root.kind = NodeKind::Struct; |
| 1471 | root.name = "Root"; |
| 1472 | root.parentId = 0; |
| 1473 | int ri = tree.addNode(root); |
| 1474 | uint64_t rootId = tree.nodes[ri].id; |
| 1475 | |
| 1476 | // StructC (innermost target) |
| 1477 | Node structC; |
| 1478 | structC.kind = NodeKind::Struct; |
| 1479 | structC.name = "InnerData"; |
| 1480 | structC.structTypeName = "InnerData"; |
| 1481 | structC.parentId = 0; |
| 1482 | structC.offset = 300; |
| 1483 | int ci = tree.addNode(structC); |
| 1484 | uint64_t structCId = tree.nodes[ci].id; |
| 1485 | |
| 1486 | Node cf; |
| 1487 | cf.kind = NodeKind::UInt64; |
| 1488 | cf.name = "payload"; |
| 1489 | cf.parentId = structCId; |
| 1490 | cf.offset = 0; |
| 1491 | tree.addNode(cf); |
| 1492 | |
| 1493 | // StructB (middle target, contains ptr to C) |
| 1494 | Node structB; |
| 1495 | structB.kind = NodeKind::Struct; |
| 1496 | structB.name = "Wrapper"; |
| 1497 | structB.structTypeName = "Wrapper"; |
| 1498 | structB.parentId = 0; |
| 1499 | structB.offset = 200; |
| 1500 | int bi = tree.addNode(structB); |
| 1501 | uint64_t structBId = tree.nodes[bi].id; |
| 1502 | |
| 1503 | Node bf; |
| 1504 | bf.kind = NodeKind::UInt32; |
| 1505 | bf.name = "flags"; |
| 1506 | bf.parentId = structBId; |
| 1507 | bf.offset = 0; |
| 1508 | tree.addNode(bf); |
| 1509 | |
| 1510 | Node bptr; |
| 1511 | bptr.kind = NodeKind::Pointer64; |
| 1512 | bptr.name = "inner"; |
| 1513 | bptr.parentId = structBId; |
| 1514 | bptr.offset = 4; |
| 1515 | bptr.refId = structCId; // points to InnerData |
| 1516 | tree.addNode(bptr); |
| 1517 | |
| 1518 | // Root's pointer to StructB |
| 1519 | Node rptr; |
| 1520 | rptr.kind = NodeKind::Pointer64; |
| 1521 | rptr.name = "wrapper_ptr"; |