GP-5588 - PDB CPP - fix aligned base class calc; create another vxtable

locator temp work-around
This commit is contained in:
ghizard 2025-04-11 15:01:17 -04:00
parent 1044bf5f7e
commit 63facf90f1
4 changed files with 433 additions and 274 deletions

View file

@ -52,9 +52,9 @@ import mdemangler.typeinfo.*;
* {@link #createVirtualTable(CategoryPath, String, Address, TaskMonitor)} methods demangle * {@link #createVirtualTable(CategoryPath, String, Address, TaskMonitor)} methods demangle
* the strings and created tables within a owner/parentage tree based on the demangled information. * the strings and created tables within a owner/parentage tree based on the demangled information.
* <p><p> * <p><p>
* The {@link #findVbt(ClassID, List)} and {@link #findVft(ClassID, List)} methods attempt * The {@link #findVbt(ClassID, List, Integer)} and {@link #findVft(ClassID, List, Integer)} methods
* to find the VF/VB tables by finding the appropriate node in the tree based upon owner and * attempt to find the VF/VB tables by finding the appropriate node in the tree based upon owner
* at-times-mismatched parentage information from the user. This mismatch is not necessarily * and at-times-mismatched parentage information from the user. This mismatch is not necessarily
* the fault of the user, but more due to what parentage is incorporated into the mangled name. * the fault of the user, but more due to what parentage is incorporated into the mangled name.
* <p><p> * <p><p>
* <B> DESIGN of find mechanism</B> * <B> DESIGN of find mechanism</B>
@ -127,6 +127,12 @@ public class MsftVxtManager extends VxtManager {
private Map<ClassID, List<VirtualBaseTable>> vbtsByOwner; private Map<ClassID, List<VirtualBaseTable>> vbtsByOwner;
private Map<ClassID, List<VirtualFunctionTable>> vftsByOwner; private Map<ClassID, List<VirtualFunctionTable>> vftsByOwner;
// A new interim solution using the address order per owner.
private Map<ClassID, Map<Address, VirtualBaseTable>> vbtByAddressByOwner;
private Map<ClassID, Map<Address, VirtualFunctionTable>> vftByAddressByOwner;
private Map<ClassID, Map<Integer, VirtualBaseTable>> vbtByPtrOrdinalByOwner;
private Map<ClassID, Map<Integer, VirtualFunctionTable>> vftByPtrOrdinalByOwner;
// Used for locating vft and vbt // Used for locating vft and vbt
// These are explicitly used for storing/retrieving the "program" versions which result from // These are explicitly used for storing/retrieving the "program" versions which result from
// locating and parsing the mangled strings for these tables. It is possible that these // locating and parsing the mangled strings for these tables. It is possible that these
@ -149,6 +155,10 @@ public class MsftVxtManager extends VxtManager {
parentageNodeByMangled = new HashMap<>(); parentageNodeByMangled = new HashMap<>();
vbtsByOwner = new HashMap<>(); vbtsByOwner = new HashMap<>();
vftsByOwner = new HashMap<>(); vftsByOwner = new HashMap<>();
vbtByAddressByOwner = new HashMap<>();
vftByAddressByOwner = new HashMap<>();
vbtByPtrOrdinalByOwner = new HashMap<>();
vftByPtrOrdinalByOwner = new HashMap<>();
vbtRoot = new ParentageNode(null); vbtRoot = new ParentageNode(null);
vftRoot = new ParentageNode(null); vftRoot = new ParentageNode(null);
vbtsByOwnerParentage = new HashMap<>(); vbtsByOwnerParentage = new HashMap<>();
@ -295,23 +305,63 @@ public class MsftVxtManager extends VxtManager {
* @param parentage the parentage for the desired table. The parentage must start with the * @param parentage the parentage for the desired table. The parentage must start with the
* parent that contains the pointer to the table and should include the ordered lineage from * parent that contains the pointer to the table and should include the ordered lineage from
* that class through all of its decendents to the owner, excluding the owner * that class through all of its decendents to the owner, excluding the owner
* @param ordinal ordinal of table for owner as sorted by address
* @return the table * @return the table
*/ */
public VirtualBaseTable findVbt(ClassID owner, List<ClassID> parentage) { public VirtualBaseTable findVbt(ClassID owner, List<ClassID> parentage, Integer ordinal) {
OwnerParentage op = new OwnerParentage(owner, parentage); OwnerParentage op = new OwnerParentage(owner, parentage);
VirtualBaseTable vbt = vbtsByOwnerParentage.get(op); VirtualBaseTable vbt = vbtsByOwnerParentage.get(op);
if (vbt != null) { if (vbt != null) {
return vbt; return vbt;
} }
vbt = searchVbtTree(owner, parentage); vbt = getVbtByAddressOrdinal(owner, ordinal);
if (vbt == null) { if (vbt == null) {
vbt = new PlaceholderVirtualBaseTable(owner, parentage); vbt = searchVbtTree(owner, parentage);
if (vbt == null) {
vbt = new PlaceholderVirtualBaseTable(owner, parentage);
}
} }
vbtsByOwnerParentage.put(op, vbt); vbtsByOwnerParentage.put(op, vbt);
storeVbt(owner, vbt); storeVbt(owner, ordinal, vbt);
return vbt; return vbt;
} }
private VirtualBaseTable getVbtByAddressOrdinal(ClassID owner, Integer ordinal) {
if (ordinal == null) {
return null;
}
Map<Address, VirtualBaseTable> map = vbtByAddressByOwner.get(owner);
if (map == null) {
return null;
}
int count = 0;
for (Map.Entry<Address, VirtualBaseTable> entry : map.entrySet()) {
if (count == ordinal) {
return entry.getValue();
}
count++;
}
return null;
}
private VirtualFunctionTable getVftByAddressOrdinal(ClassID owner, Integer ordinal) {
if (ordinal == null) {
return null;
}
Map<Address, VirtualFunctionTable> map = vftByAddressByOwner.get(owner);
if (map == null) {
return null;
}
int count = 0;
for (Map.Entry<Address, VirtualFunctionTable> entry : map.entrySet()) {
if (count == ordinal) {
return entry.getValue();
}
count++;
}
return null;
}
private VirtualBaseTable searchVbtTree(ClassID owner, List<ClassID> parentage) { private VirtualBaseTable searchVbtTree(ClassID owner, List<ClassID> parentage) {
ParentageNode node = findNode(owner, parentage, vbtRoot); ParentageNode node = findNode(owner, parentage, vbtRoot);
if (node == null) { if (node == null) {
@ -341,20 +391,24 @@ public class MsftVxtManager extends VxtManager {
* @param parentage the parentage for the desired table. The parentage must start with the * @param parentage the parentage for the desired table. The parentage must start with the
* parent that contains the pointer to the table and should include the ordered lineage from * parent that contains the pointer to the table and should include the ordered lineage from
* that class through all of its decendents to the owner, excluding the owner * that class through all of its decendents to the owner, excluding the owner
* @param ordinal ordinal of table for owner as sorted by address
* @return the table * @return the table
*/ */
public VirtualFunctionTable findVft(ClassID owner, List<ClassID> parentage) { public VirtualFunctionTable findVft(ClassID owner, List<ClassID> parentage, Integer ordinal) {
OwnerParentage op = new OwnerParentage(owner, parentage); OwnerParentage op = new OwnerParentage(owner, parentage);
VirtualFunctionTable vft = vftsByOwnerParentage.get(op); VirtualFunctionTable vft = vftsByOwnerParentage.get(op);
if (vft != null) { if (vft != null) {
return vft; return vft;
} }
vft = searchVftTree(owner, parentage); vft = getVftByAddressOrdinal(owner, ordinal);
if (vft == null) { if (vft == null) {
vft = new PlaceholderVirtualFunctionTable(owner, parentage); vft = searchVftTree(owner, parentage);
if (vft == null) {
vft = new PlaceholderVirtualFunctionTable(owner, parentage);
}
} }
vftsByOwnerParentage.put(op, vft); vftsByOwnerParentage.put(op, vft);
storeVft(owner, vft); storeVft(owner, ordinal, vft);
return vft; return vft;
} }
@ -463,7 +517,7 @@ public class MsftVxtManager extends VxtManager {
} }
node.setVBTable(prvbt); node.setVBTable(prvbt);
vbtByAddress.put(address, prvbt); vbtByAddress.put(address, prvbt);
storeVbt(owner, prvbt); // temp solution? storeVbt(owner, address, prvbt); // temp solution?
break; break;
case VFT: case VFT:
@ -475,7 +529,7 @@ public class MsftVxtManager extends VxtManager {
} }
node.setVFTable(vft); node.setVFTable(vft);
vftByAddress.put(address, vft); vftByAddress.put(address, vft);
storeVft(owner, vft); // temp solution? storeVft(owner, address, vft); // temp solution?
break; break;
default: default:
@ -484,9 +538,8 @@ public class MsftVxtManager extends VxtManager {
return true; return true;
} }
private void storeVbt(ClassID owner, VirtualBaseTable vbt) { private void storeVbt(ClassID owner, Address address, VirtualBaseTable vbt) {
ClassID own = vbt.getOwner(); List<VirtualBaseTable> list = vbtsByOwner.get(owner);
List<VirtualBaseTable> list = vbtsByOwner.get(own);
if (list == null) { if (list == null) {
list = new ArrayList<>(); list = new ArrayList<>();
vbtsByOwner.put(owner, list); vbtsByOwner.put(owner, list);
@ -498,9 +551,55 @@ public class MsftVxtManager extends VxtManager {
} }
} }
list.add(vbt); list.add(vbt);
// Part of next interim solution
Map<Address, VirtualBaseTable> map = vbtByAddressByOwner.get(owner);
if (map == null) {
map = new TreeMap<>();
vbtByAddressByOwner.put(owner, map);
}
if (map.containsKey(address)) {
Msg.warn(this, String.format("VBT already exists for owner/address %s/%s",
owner.getSymbolPath().toString(), address.toString()));
return;
}
map.put(address, vbt);
} }
private void storeVft(ClassID owner, VirtualFunctionTable vft) { private void storeVbt(ClassID owner, Integer ordinal, VirtualBaseTable vbt) {
List<VirtualBaseTable> list = vbtsByOwner.get(owner);
if (list == null) {
list = new ArrayList<>();
vbtsByOwner.put(owner, list);
}
List<ClassID> parentage = vbt.getParentage();
for (VirtualBaseTable table : list) {
if (isEqual(table.getParentage(), parentage)) {
return; // return without saving
}
}
list.add(vbt);
// Part of next interim solution
if (ordinal == null) {
return;
}
Map<Integer, VirtualBaseTable> map = vbtByPtrOrdinalByOwner.get(owner);
if (map == null) {
map = new TreeMap<>();
vbtByPtrOrdinalByOwner.put(owner, map);
}
if (map.containsKey(ordinal)) {
Msg.warn(this, String.format("VBT already exists for owner/ordinal %s/%d ",
owner.getSymbolPath().toString(), ordinal));
return;
}
map.put(ordinal, vbt);
}
private void storeVft(ClassID owner, Address address, VirtualFunctionTable vft) {
List<VirtualFunctionTable> list = vftsByOwner.get(owner); List<VirtualFunctionTable> list = vftsByOwner.get(owner);
if (list == null) { if (list == null) {
list = new ArrayList<>(); list = new ArrayList<>();
@ -513,6 +612,52 @@ public class MsftVxtManager extends VxtManager {
} }
} }
list.add(vft); list.add(vft);
// Part of next interim solution
Map<Address, VirtualFunctionTable> map = vftByAddressByOwner.get(owner);
if (map == null) {
map = new TreeMap<>();
vftByAddressByOwner.put(owner, map);
}
if (map.containsKey(address)) {
Msg.warn(this, String.format("VFT already exists for owner/address %s/%s",
owner.getSymbolPath().toString(), address.toString()));
return;
}
map.put(address, vft);
}
private void storeVft(ClassID owner, Integer ordinal, VirtualFunctionTable vft) {
List<VirtualFunctionTable> list = vftsByOwner.get(owner);
if (list == null) {
list = new ArrayList<>();
vftsByOwner.put(owner, list);
}
List<ClassID> parentage = vft.getParentage();
for (VirtualFunctionTable table : list) {
if (isEqual(table.getParentage(), parentage)) {
return; // return without saving
}
}
list.add(vft);
// Part of next interim solution
if (ordinal == null) {
return;
}
Map<Integer, VirtualFunctionTable> map = vftByPtrOrdinalByOwner.get(owner);
if (map == null) {
map = new TreeMap<>();
vftByPtrOrdinalByOwner.put(owner, map);
}
if (map.containsKey(ordinal)) {
Msg.warn(this, String.format("VFT already exists for owner/ptrOffset %s/%d",
owner.getSymbolPath().toString(), ordinal));
return;
}
map.put(ordinal, vft);
} }
private boolean isEqual(List<ClassID> parentage1, List<ClassID> parentage2) { private boolean isEqual(List<ClassID> parentage1, List<ClassID> parentage2) {

View file

@ -216,10 +216,10 @@ public abstract class VirtualBaseTable implements VBTable {
} }
/** /**
* Returns the built data type for this vftable for the current entries * Returns the built data type for this vbtable for the current entries
* @param dtm the data type manager * @param dtm the data type manager
* @param categoryPath category path for the table * @param categoryPath category path for the table
* @return the structure of the vftable * @return the structure of the vbtable
*/ */
public Structure getLayout(DataTypeManager dtm, CategoryPath categoryPath) { public Structure getLayout(DataTypeManager dtm, CategoryPath categoryPath) {
if (!isBuilt) { // what if we want to rebuild... what should we do? if (!isBuilt) { // what if we want to rebuild... what should we do?

View file

@ -1453,7 +1453,7 @@ public class CppCompositeType {
myVftPtrOffset = vftPtrTypeByOffset.firstKey(); myVftPtrOffset = vftPtrTypeByOffset.firstKey();
VxtPtrInfo info = VxtPtrInfo info =
new VxtPtrInfo(myVftPtrOffset, myVftPtrOffset, myId, List.of(myId)); new VxtPtrInfo(myVftPtrOffset, myVftPtrOffset, myId, List.of(myId));
VirtualFunctionTable myVft = vxtManager.findVft(myId, info.parentage()); VirtualFunctionTable myVft = vxtManager.findVft(myId, info.parentage(), 0);
myVft.setPtrOffsetInClass(info.finalOffset()); myVft.setPtrOffsetInClass(info.finalOffset());
propagatedSelfBaseVfts.add(info); propagatedSelfBaseVfts.add(info);
finalVftByOffset.put(info.finalOffset(), myVft); finalVftByOffset.put(info.finalOffset(), myVft);
@ -1490,7 +1490,7 @@ public class CppCompositeType {
Msg.warn(this, "Mismatch vbt location for " + myId); Msg.warn(this, "Mismatch vbt location for " + myId);
} }
VxtPtrInfo info = new VxtPtrInfo(vbtPtrOffset, vbtPtrOffset, myId, List.of(myId)); VxtPtrInfo info = new VxtPtrInfo(vbtPtrOffset, vbtPtrOffset, myId, List.of(myId));
VirtualBaseTable myVbt = vxtManager.findVbt(myId, info.parentage()); VirtualBaseTable myVbt = vxtManager.findVbt(myId, info.parentage(), 0);
myVbt.setPtrOffsetInClass(info.finalOffset()); myVbt.setPtrOffsetInClass(info.finalOffset());
propagatedSelfBaseVbts.add(info); propagatedSelfBaseVbts.add(info);
finalVbtByOffset.put(info.finalOffset(), myVbt); finalVbtByOffset.put(info.finalOffset(), myVbt);
@ -1548,7 +1548,8 @@ public class CppCompositeType {
Long finalOffset = info.finalOffset(); Long finalOffset = info.finalOffset();
VirtualFunctionTable myVft = (VirtualFunctionTable) finalVftByOffset.get(finalOffset); VirtualFunctionTable myVft = (VirtualFunctionTable) finalVftByOffset.get(finalOffset);
if (myVft == null) { if (myVft == null) {
myVft = mvxtManager.findVft(myId, info.parentage()); Integer ordinal = getOrdinalOfKey(finalVftByOffset, finalOffset);
myVft = mvxtManager.findVft(myId, info.parentage(), ordinal);
if (myVft == null) { if (myVft == null) {
return null; return null;
} }
@ -1556,8 +1557,7 @@ public class CppCompositeType {
} }
myVft.setPtrOffsetInClass(finalOffset); myVft.setPtrOffsetInClass(finalOffset);
VirtualFunctionTable parentVft = VirtualFunctionTable parentVft = mvxtManager.findVft(parentId, parentParentage, null);
mvxtManager.findVft(parentId, parentParentage);
if (parentVft == null) { if (parentVft == null) {
// this is an error // this is an error
@ -1669,7 +1669,8 @@ public class CppCompositeType {
Long finalOffset = info.finalOffset(); Long finalOffset = info.finalOffset();
VirtualBaseTable myVbt = (VirtualBaseTable) finalVbtByOffset.get(finalOffset); VirtualBaseTable myVbt = (VirtualBaseTable) finalVbtByOffset.get(finalOffset);
if (myVbt == null) { if (myVbt == null) {
myVbt = mvxtManager.findVbt(myId, info.parentage()); Integer ordinal = getOrdinalOfKey(finalVbtByOffset, finalOffset);
myVbt = mvxtManager.findVbt(myId, info.parentage(), ordinal);
if (myVbt == null) { if (myVbt == null) {
return null; return null;
} }
@ -1677,8 +1678,7 @@ public class CppCompositeType {
} }
myVbt.setPtrOffsetInClass(finalOffset); myVbt.setPtrOffsetInClass(finalOffset);
VirtualBaseTable parentVbt = VirtualBaseTable parentVbt = mvxtManager.findVbt(parentId, parentParentage, null);
mvxtManager.findVbt(parentId, parentParentage);
if (parentVbt == null) { if (parentVbt == null) {
// this is an error // this is an error
return null; return null;
@ -1693,6 +1693,17 @@ public class CppCompositeType {
return myVbt; return myVbt;
} }
private Integer getOrdinalOfKey(Map<Long, VXT> map, Long key) {
int index = 0;
for (Long offset : finalVftByOffset.keySet()) {
if (offset == key) {
return index;
}
index++;
}
return map.size();
}
/** /**
* Provides the Virtual Base Table to be used for placing virtual bases of this class * Provides the Virtual Base Table to be used for placing virtual bases of this class
* @throws PdbException upon unrecognized vft type * @throws PdbException upon unrecognized vft type
@ -1739,12 +1750,15 @@ public class CppCompositeType {
} }
} }
} }
long off = selfBaseType.getAlignedLength(); int off = selfBaseType.getAlignedLength();
for (VirtualLayoutBaseClass base : reorderedVirtualBases) { for (VirtualLayoutBaseClass base : reorderedVirtualBases) {
CppCompositeType baseType = base.getBaseClassType(); CppCompositeType baseType = base.getBaseClassType();
addPlaceholderVirtualBaseTableEntry(plvbt, vxtManager, base, off); int basePtrOff = base.getBasePointerOffset();
Composite baseComposite = baseType.getComposite();
off = DataOrganizationImpl.getAlignedOffset(baseComposite.getAlignment(), off);
addPlaceholderVirtualBaseTableEntry(plvbt, vxtManager, base, off - basePtrOff);
if (!baseType.hasZeroBaseSize) { if (!baseType.hasZeroBaseSize) {
off += baseType.getSelfBaseType().getAlignedLength(); off += baseType.getSelfBaseType().getLength();
} }
} }
return plvbt; return plvbt;