Skip to content

Commit 90c7731

Browse files
committed
Merge remote-tracking branch 'origin/GP-5588_ghizard_PDB_fix_aligned_base_placement_and_create_another_vxtable_location_workaround'
2 parents 13834fa + 63facf9 commit 90c7731

File tree

4 files changed

+433
-274
lines changed

4 files changed

+433
-274
lines changed

Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/classtype/MsftVxtManager.java

Lines changed: 162 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@
5252
* {@link #createVirtualTable(CategoryPath, String, Address, TaskMonitor)} methods demangle
5353
* the strings and created tables within a owner/parentage tree based on the demangled information.
5454
* <p><p>
55-
* The {@link #findVbt(ClassID, List)} and {@link #findVft(ClassID, List)} methods attempt
56-
* to find the VF/VB tables by finding the appropriate node in the tree based upon owner and
57-
* at-times-mismatched parentage information from the user. This mismatch is not necessarily
55+
* The {@link #findVbt(ClassID, List, Integer)} and {@link #findVft(ClassID, List, Integer)} methods
56+
* attempt to find the VF/VB tables by finding the appropriate node in the tree based upon owner
57+
* and at-times-mismatched parentage information from the user. This mismatch is not necessarily
5858
* the fault of the user, but more due to what parentage is incorporated into the mangled name.
5959
* <p><p>
6060
* <B> DESIGN of find mechanism</B>
@@ -127,6 +127,12 @@ public class MsftVxtManager extends VxtManager {
127127
private Map<ClassID, List<VirtualBaseTable>> vbtsByOwner;
128128
private Map<ClassID, List<VirtualFunctionTable>> vftsByOwner;
129129

130+
// A new interim solution using the address order per owner.
131+
private Map<ClassID, Map<Address, VirtualBaseTable>> vbtByAddressByOwner;
132+
private Map<ClassID, Map<Address, VirtualFunctionTable>> vftByAddressByOwner;
133+
private Map<ClassID, Map<Integer, VirtualBaseTable>> vbtByPtrOrdinalByOwner;
134+
private Map<ClassID, Map<Integer, VirtualFunctionTable>> vftByPtrOrdinalByOwner;
135+
130136
// Used for locating vft and vbt
131137
// These are explicitly used for storing/retrieving the "program" versions which result from
132138
// locating and parsing the mangled strings for these tables. It is possible that these
@@ -149,6 +155,10 @@ public MsftVxtManager(ClassTypeManager ctm, Program program) {
149155
parentageNodeByMangled = new HashMap<>();
150156
vbtsByOwner = new HashMap<>();
151157
vftsByOwner = new HashMap<>();
158+
vbtByAddressByOwner = new HashMap<>();
159+
vftByAddressByOwner = new HashMap<>();
160+
vbtByPtrOrdinalByOwner = new HashMap<>();
161+
vftByPtrOrdinalByOwner = new HashMap<>();
152162
vbtRoot = new ParentageNode(null);
153163
vftRoot = new ParentageNode(null);
154164
vbtsByOwnerParentage = new HashMap<>();
@@ -295,23 +305,63 @@ public VirtualFunctionTable[] getVfts(ClassID owner) {
295305
* @param parentage the parentage for the desired table. The parentage must start with the
296306
* parent that contains the pointer to the table and should include the ordered lineage from
297307
* that class through all of its decendents to the owner, excluding the owner
308+
* @param ordinal ordinal of table for owner as sorted by address
298309
* @return the table
299310
*/
300-
public VirtualBaseTable findVbt(ClassID owner, List<ClassID> parentage) {
311+
public VirtualBaseTable findVbt(ClassID owner, List<ClassID> parentage, Integer ordinal) {
301312
OwnerParentage op = new OwnerParentage(owner, parentage);
302313
VirtualBaseTable vbt = vbtsByOwnerParentage.get(op);
303314
if (vbt != null) {
304315
return vbt;
305316
}
306-
vbt = searchVbtTree(owner, parentage);
317+
vbt = getVbtByAddressOrdinal(owner, ordinal);
307318
if (vbt == null) {
308-
vbt = new PlaceholderVirtualBaseTable(owner, parentage);
319+
vbt = searchVbtTree(owner, parentage);
320+
if (vbt == null) {
321+
vbt = new PlaceholderVirtualBaseTable(owner, parentage);
322+
}
309323
}
310324
vbtsByOwnerParentage.put(op, vbt);
311-
storeVbt(owner, vbt);
325+
storeVbt(owner, ordinal, vbt);
312326
return vbt;
313327
}
314328

329+
private VirtualBaseTable getVbtByAddressOrdinal(ClassID owner, Integer ordinal) {
330+
if (ordinal == null) {
331+
return null;
332+
}
333+
Map<Address, VirtualBaseTable> map = vbtByAddressByOwner.get(owner);
334+
if (map == null) {
335+
return null;
336+
}
337+
int count = 0;
338+
for (Map.Entry<Address, VirtualBaseTable> entry : map.entrySet()) {
339+
if (count == ordinal) {
340+
return entry.getValue();
341+
}
342+
count++;
343+
}
344+
return null;
345+
}
346+
347+
private VirtualFunctionTable getVftByAddressOrdinal(ClassID owner, Integer ordinal) {
348+
if (ordinal == null) {
349+
return null;
350+
}
351+
Map<Address, VirtualFunctionTable> map = vftByAddressByOwner.get(owner);
352+
if (map == null) {
353+
return null;
354+
}
355+
int count = 0;
356+
for (Map.Entry<Address, VirtualFunctionTable> entry : map.entrySet()) {
357+
if (count == ordinal) {
358+
return entry.getValue();
359+
}
360+
count++;
361+
}
362+
return null;
363+
}
364+
315365
private VirtualBaseTable searchVbtTree(ClassID owner, List<ClassID> parentage) {
316366
ParentageNode node = findNode(owner, parentage, vbtRoot);
317367
if (node == null) {
@@ -341,20 +391,24 @@ private VirtualBaseTable searchVbtTree(ClassID owner, List<ClassID> parentage) {
341391
* @param parentage the parentage for the desired table. The parentage must start with the
342392
* parent that contains the pointer to the table and should include the ordered lineage from
343393
* that class through all of its decendents to the owner, excluding the owner
394+
* @param ordinal ordinal of table for owner as sorted by address
344395
* @return the table
345396
*/
346-
public VirtualFunctionTable findVft(ClassID owner, List<ClassID> parentage) {
397+
public VirtualFunctionTable findVft(ClassID owner, List<ClassID> parentage, Integer ordinal) {
347398
OwnerParentage op = new OwnerParentage(owner, parentage);
348399
VirtualFunctionTable vft = vftsByOwnerParentage.get(op);
349400
if (vft != null) {
350401
return vft;
351402
}
352-
vft = searchVftTree(owner, parentage);
403+
vft = getVftByAddressOrdinal(owner, ordinal);
353404
if (vft == null) {
354-
vft = new PlaceholderVirtualFunctionTable(owner, parentage);
405+
vft = searchVftTree(owner, parentage);
406+
if (vft == null) {
407+
vft = new PlaceholderVirtualFunctionTable(owner, parentage);
408+
}
355409
}
356410
vftsByOwnerParentage.put(op, vft);
357-
storeVft(owner, vft);
411+
storeVft(owner, ordinal, vft);
358412
return vft;
359413
}
360414

@@ -463,7 +517,7 @@ public boolean createVirtualTable(CategoryPath categoryPath, String mangled, Add
463517
}
464518
node.setVBTable(prvbt);
465519
vbtByAddress.put(address, prvbt);
466-
storeVbt(owner, prvbt); // temp solution?
520+
storeVbt(owner, address, prvbt); // temp solution?
467521
break;
468522

469523
case VFT:
@@ -475,7 +529,7 @@ public boolean createVirtualTable(CategoryPath categoryPath, String mangled, Add
475529
}
476530
node.setVFTable(vft);
477531
vftByAddress.put(address, vft);
478-
storeVft(owner, vft); // temp solution?
532+
storeVft(owner, address, vft); // temp solution?
479533
break;
480534

481535
default:
@@ -484,9 +538,37 @@ public boolean createVirtualTable(CategoryPath categoryPath, String mangled, Add
484538
return true;
485539
}
486540

487-
private void storeVbt(ClassID owner, VirtualBaseTable vbt) {
488-
ClassID own = vbt.getOwner();
489-
List<VirtualBaseTable> list = vbtsByOwner.get(own);
541+
private void storeVbt(ClassID owner, Address address, VirtualBaseTable vbt) {
542+
List<VirtualBaseTable> list = vbtsByOwner.get(owner);
543+
if (list == null) {
544+
list = new ArrayList<>();
545+
vbtsByOwner.put(owner, list);
546+
}
547+
List<ClassID> parentage = vbt.getParentage();
548+
for (VirtualBaseTable table : list) {
549+
if (isEqual(table.getParentage(), parentage)) {
550+
return; // return without saving
551+
}
552+
}
553+
list.add(vbt);
554+
555+
// Part of next interim solution
556+
Map<Address, VirtualBaseTable> map = vbtByAddressByOwner.get(owner);
557+
if (map == null) {
558+
map = new TreeMap<>();
559+
vbtByAddressByOwner.put(owner, map);
560+
}
561+
if (map.containsKey(address)) {
562+
Msg.warn(this, String.format("VBT already exists for owner/address %s/%s",
563+
owner.getSymbolPath().toString(), address.toString()));
564+
return;
565+
}
566+
map.put(address, vbt);
567+
568+
}
569+
570+
private void storeVbt(ClassID owner, Integer ordinal, VirtualBaseTable vbt) {
571+
List<VirtualBaseTable> list = vbtsByOwner.get(owner);
490572
if (list == null) {
491573
list = new ArrayList<>();
492574
vbtsByOwner.put(owner, list);
@@ -498,9 +580,26 @@ private void storeVbt(ClassID owner, VirtualBaseTable vbt) {
498580
}
499581
}
500582
list.add(vbt);
583+
584+
// Part of next interim solution
585+
if (ordinal == null) {
586+
return;
587+
}
588+
Map<Integer, VirtualBaseTable> map = vbtByPtrOrdinalByOwner.get(owner);
589+
if (map == null) {
590+
map = new TreeMap<>();
591+
vbtByPtrOrdinalByOwner.put(owner, map);
592+
}
593+
if (map.containsKey(ordinal)) {
594+
Msg.warn(this, String.format("VBT already exists for owner/ordinal %s/%d ",
595+
owner.getSymbolPath().toString(), ordinal));
596+
return;
597+
}
598+
map.put(ordinal, vbt);
599+
501600
}
502601

503-
private void storeVft(ClassID owner, VirtualFunctionTable vft) {
602+
private void storeVft(ClassID owner, Address address, VirtualFunctionTable vft) {
504603
List<VirtualFunctionTable> list = vftsByOwner.get(owner);
505604
if (list == null) {
506605
list = new ArrayList<>();
@@ -513,6 +612,52 @@ private void storeVft(ClassID owner, VirtualFunctionTable vft) {
513612
}
514613
}
515614
list.add(vft);
615+
616+
// Part of next interim solution
617+
Map<Address, VirtualFunctionTable> map = vftByAddressByOwner.get(owner);
618+
if (map == null) {
619+
map = new TreeMap<>();
620+
vftByAddressByOwner.put(owner, map);
621+
}
622+
if (map.containsKey(address)) {
623+
Msg.warn(this, String.format("VFT already exists for owner/address %s/%s",
624+
owner.getSymbolPath().toString(), address.toString()));
625+
return;
626+
}
627+
map.put(address, vft);
628+
629+
}
630+
631+
private void storeVft(ClassID owner, Integer ordinal, VirtualFunctionTable vft) {
632+
List<VirtualFunctionTable> list = vftsByOwner.get(owner);
633+
if (list == null) {
634+
list = new ArrayList<>();
635+
vftsByOwner.put(owner, list);
636+
}
637+
List<ClassID> parentage = vft.getParentage();
638+
for (VirtualFunctionTable table : list) {
639+
if (isEqual(table.getParentage(), parentage)) {
640+
return; // return without saving
641+
}
642+
}
643+
list.add(vft);
644+
645+
// Part of next interim solution
646+
if (ordinal == null) {
647+
return;
648+
}
649+
Map<Integer, VirtualFunctionTable> map = vftByPtrOrdinalByOwner.get(owner);
650+
if (map == null) {
651+
map = new TreeMap<>();
652+
vftByPtrOrdinalByOwner.put(owner, map);
653+
}
654+
if (map.containsKey(ordinal)) {
655+
Msg.warn(this, String.format("VFT already exists for owner/ptrOffset %s/%d",
656+
owner.getSymbolPath().toString(), ordinal));
657+
return;
658+
}
659+
map.put(ordinal, vft);
660+
516661
}
517662

518663
private boolean isEqual(List<ClassID> parentage1, List<ClassID> parentage2) {

Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/classtype/VirtualBaseTable.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,10 @@ void emit(StringBuilder builder) {
216216
}
217217

218218
/**
219-
* Returns the built data type for this vftable for the current entries
219+
* Returns the built data type for this vbtable for the current entries
220220
* @param dtm the data type manager
221221
* @param categoryPath category path for the table
222-
* @return the structure of the vftable
222+
* @return the structure of the vbtable
223223
*/
224224
public Structure getLayout(DataTypeManager dtm, CategoryPath categoryPath) {
225225
if (!isBuilt) { // what if we want to rebuild... what should we do?

Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeType.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,7 +1453,7 @@ private void findOrAllocateMainVftPtr(MsftVxtManager vxtManager) {
14531453
myVftPtrOffset = vftPtrTypeByOffset.firstKey();
14541454
VxtPtrInfo info =
14551455
new VxtPtrInfo(myVftPtrOffset, myVftPtrOffset, myId, List.of(myId));
1456-
VirtualFunctionTable myVft = vxtManager.findVft(myId, info.parentage());
1456+
VirtualFunctionTable myVft = vxtManager.findVft(myId, info.parentage(), 0);
14571457
myVft.setPtrOffsetInClass(info.finalOffset());
14581458
propagatedSelfBaseVfts.add(info);
14591459
finalVftByOffset.put(info.finalOffset(), myVft);
@@ -1490,7 +1490,7 @@ private void findOrAllocateMainVbtPtr(MsftVxtManager vxtManager) {
14901490
Msg.warn(this, "Mismatch vbt location for " + myId);
14911491
}
14921492
VxtPtrInfo info = new VxtPtrInfo(vbtPtrOffset, vbtPtrOffset, myId, List.of(myId));
1493-
VirtualBaseTable myVbt = vxtManager.findVbt(myId, info.parentage());
1493+
VirtualBaseTable myVbt = vxtManager.findVbt(myId, info.parentage(), 0);
14941494
myVbt.setPtrOffsetInClass(info.finalOffset());
14951495
propagatedSelfBaseVbts.add(info);
14961496
finalVbtByOffset.put(info.finalOffset(), myVbt);
@@ -1548,16 +1548,16 @@ private VirtualFunctionTable updateVft(VxtManager vxtManager, ClassID baseId, Vx
15481548
Long finalOffset = info.finalOffset();
15491549
VirtualFunctionTable myVft = (VirtualFunctionTable) finalVftByOffset.get(finalOffset);
15501550
if (myVft == null) {
1551-
myVft = mvxtManager.findVft(myId, info.parentage());
1551+
Integer ordinal = getOrdinalOfKey(finalVftByOffset, finalOffset);
1552+
myVft = mvxtManager.findVft(myId, info.parentage(), ordinal);
15521553
if (myVft == null) {
15531554
return null;
15541555
}
15551556
finalVftByOffset.put(finalOffset, myVft);
15561557
}
15571558

15581559
myVft.setPtrOffsetInClass(finalOffset);
1559-
VirtualFunctionTable parentVft =
1560-
mvxtManager.findVft(parentId, parentParentage);
1560+
VirtualFunctionTable parentVft = mvxtManager.findVft(parentId, parentParentage, null);
15611561

15621562
if (parentVft == null) {
15631563
// this is an error
@@ -1669,16 +1669,16 @@ private VirtualBaseTable updateVbt(VxtManager vxtManager, ClassID baseId, VxtPtr
16691669
Long finalOffset = info.finalOffset();
16701670
VirtualBaseTable myVbt = (VirtualBaseTable) finalVbtByOffset.get(finalOffset);
16711671
if (myVbt == null) {
1672-
myVbt = mvxtManager.findVbt(myId, info.parentage());
1672+
Integer ordinal = getOrdinalOfKey(finalVbtByOffset, finalOffset);
1673+
myVbt = mvxtManager.findVbt(myId, info.parentage(), ordinal);
16731674
if (myVbt == null) {
16741675
return null;
16751676
}
16761677
finalVbtByOffset.put(finalOffset, myVbt);
16771678
}
16781679

16791680
myVbt.setPtrOffsetInClass(finalOffset);
1680-
VirtualBaseTable parentVbt =
1681-
mvxtManager.findVbt(parentId, parentParentage);
1681+
VirtualBaseTable parentVbt = mvxtManager.findVbt(parentId, parentParentage, null);
16821682
if (parentVbt == null) {
16831683
// this is an error
16841684
return null;
@@ -1693,6 +1693,17 @@ private VirtualBaseTable updateVbt(VxtManager vxtManager, ClassID baseId, VxtPtr
16931693
return myVbt;
16941694
}
16951695

1696+
private Integer getOrdinalOfKey(Map<Long, VXT> map, Long key) {
1697+
int index = 0;
1698+
for (Long offset : finalVftByOffset.keySet()) {
1699+
if (offset == key) {
1700+
return index;
1701+
}
1702+
index++;
1703+
}
1704+
return map.size();
1705+
}
1706+
16961707
/**
16971708
* Provides the Virtual Base Table to be used for placing virtual bases of this class
16981709
* @throws PdbException upon unrecognized vft type
@@ -1739,12 +1750,15 @@ else if (vbt instanceof PlaceholderVirtualBaseTable plvbt) {
17391750
}
17401751
}
17411752
}
1742-
long off = selfBaseType.getAlignedLength();
1753+
int off = selfBaseType.getAlignedLength();
17431754
for (VirtualLayoutBaseClass base : reorderedVirtualBases) {
17441755
CppCompositeType baseType = base.getBaseClassType();
1745-
addPlaceholderVirtualBaseTableEntry(plvbt, vxtManager, base, off);
1756+
int basePtrOff = base.getBasePointerOffset();
1757+
Composite baseComposite = baseType.getComposite();
1758+
off = DataOrganizationImpl.getAlignedOffset(baseComposite.getAlignment(), off);
1759+
addPlaceholderVirtualBaseTableEntry(plvbt, vxtManager, base, off - basePtrOff);
17461760
if (!baseType.hasZeroBaseSize) {
1747-
off += baseType.getSelfBaseType().getAlignedLength();
1761+
off += baseType.getSelfBaseType().getLength();
17481762
}
17491763
}
17501764
return plvbt;

0 commit comments

Comments
 (0)