mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-5588 - PDB CPP - fix aligned base class calc; create another vxtable
locator temp work-around
This commit is contained in:
parent
1044bf5f7e
commit
63facf90f1
4 changed files with 433 additions and 274 deletions
|
@ -52,9 +52,9 @@ import mdemangler.typeinfo.*;
|
|||
* {@link #createVirtualTable(CategoryPath, String, Address, TaskMonitor)} methods demangle
|
||||
* the strings and created tables within a owner/parentage tree based on the demangled information.
|
||||
* <p><p>
|
||||
* The {@link #findVbt(ClassID, List)} and {@link #findVft(ClassID, List)} methods attempt
|
||||
* to find the VF/VB tables by finding the appropriate node in the tree based upon owner and
|
||||
* at-times-mismatched parentage information from the user. This mismatch is not necessarily
|
||||
* The {@link #findVbt(ClassID, List, Integer)} and {@link #findVft(ClassID, List, Integer)} methods
|
||||
* attempt to find the VF/VB tables by finding the appropriate node in the tree based upon owner
|
||||
* 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.
|
||||
* <p><p>
|
||||
* <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<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
|
||||
// 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
|
||||
|
@ -149,6 +155,10 @@ public class MsftVxtManager extends VxtManager {
|
|||
parentageNodeByMangled = new HashMap<>();
|
||||
vbtsByOwner = new HashMap<>();
|
||||
vftsByOwner = new HashMap<>();
|
||||
vbtByAddressByOwner = new HashMap<>();
|
||||
vftByAddressByOwner = new HashMap<>();
|
||||
vbtByPtrOrdinalByOwner = new HashMap<>();
|
||||
vftByPtrOrdinalByOwner = new HashMap<>();
|
||||
vbtRoot = new ParentageNode(null);
|
||||
vftRoot = new ParentageNode(null);
|
||||
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
|
||||
* 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
|
||||
* @param ordinal ordinal of table for owner as sorted by address
|
||||
* @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);
|
||||
VirtualBaseTable vbt = vbtsByOwnerParentage.get(op);
|
||||
if (vbt != null) {
|
||||
return vbt;
|
||||
}
|
||||
vbt = getVbtByAddressOrdinal(owner, ordinal);
|
||||
if (vbt == null) {
|
||||
vbt = searchVbtTree(owner, parentage);
|
||||
if (vbt == null) {
|
||||
vbt = new PlaceholderVirtualBaseTable(owner, parentage);
|
||||
}
|
||||
}
|
||||
vbtsByOwnerParentage.put(op, vbt);
|
||||
storeVbt(owner, vbt);
|
||||
storeVbt(owner, ordinal, 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) {
|
||||
ParentageNode node = findNode(owner, parentage, vbtRoot);
|
||||
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
|
||||
* 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
|
||||
* @param ordinal ordinal of table for owner as sorted by address
|
||||
* @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);
|
||||
VirtualFunctionTable vft = vftsByOwnerParentage.get(op);
|
||||
if (vft != null) {
|
||||
return vft;
|
||||
}
|
||||
vft = getVftByAddressOrdinal(owner, ordinal);
|
||||
if (vft == null) {
|
||||
vft = searchVftTree(owner, parentage);
|
||||
if (vft == null) {
|
||||
vft = new PlaceholderVirtualFunctionTable(owner, parentage);
|
||||
}
|
||||
}
|
||||
vftsByOwnerParentage.put(op, vft);
|
||||
storeVft(owner, vft);
|
||||
storeVft(owner, ordinal, vft);
|
||||
return vft;
|
||||
}
|
||||
|
||||
|
@ -463,7 +517,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
}
|
||||
node.setVBTable(prvbt);
|
||||
vbtByAddress.put(address, prvbt);
|
||||
storeVbt(owner, prvbt); // temp solution?
|
||||
storeVbt(owner, address, prvbt); // temp solution?
|
||||
break;
|
||||
|
||||
case VFT:
|
||||
|
@ -475,7 +529,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
}
|
||||
node.setVFTable(vft);
|
||||
vftByAddress.put(address, vft);
|
||||
storeVft(owner, vft); // temp solution?
|
||||
storeVft(owner, address, vft); // temp solution?
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -484,9 +538,8 @@ public class MsftVxtManager extends VxtManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void storeVbt(ClassID owner, VirtualBaseTable vbt) {
|
||||
ClassID own = vbt.getOwner();
|
||||
List<VirtualBaseTable> list = vbtsByOwner.get(own);
|
||||
private void storeVbt(ClassID owner, Address address, VirtualBaseTable vbt) {
|
||||
List<VirtualBaseTable> list = vbtsByOwner.get(owner);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
vbtsByOwner.put(owner, list);
|
||||
|
@ -498,9 +551,55 @@ public class MsftVxtManager extends VxtManager {
|
|||
}
|
||||
}
|
||||
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);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
|
@ -513,6 +612,52 @@ public class MsftVxtManager extends VxtManager {
|
|||
}
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -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 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) {
|
||||
if (!isBuilt) { // what if we want to rebuild... what should we do?
|
||||
|
|
|
@ -1453,7 +1453,7 @@ public class CppCompositeType {
|
|||
myVftPtrOffset = vftPtrTypeByOffset.firstKey();
|
||||
VxtPtrInfo info =
|
||||
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());
|
||||
propagatedSelfBaseVfts.add(info);
|
||||
finalVftByOffset.put(info.finalOffset(), myVft);
|
||||
|
@ -1490,7 +1490,7 @@ public class CppCompositeType {
|
|||
Msg.warn(this, "Mismatch vbt location for " + 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());
|
||||
propagatedSelfBaseVbts.add(info);
|
||||
finalVbtByOffset.put(info.finalOffset(), myVbt);
|
||||
|
@ -1548,7 +1548,8 @@ public class CppCompositeType {
|
|||
Long finalOffset = info.finalOffset();
|
||||
VirtualFunctionTable myVft = (VirtualFunctionTable) finalVftByOffset.get(finalOffset);
|
||||
if (myVft == null) {
|
||||
myVft = mvxtManager.findVft(myId, info.parentage());
|
||||
Integer ordinal = getOrdinalOfKey(finalVftByOffset, finalOffset);
|
||||
myVft = mvxtManager.findVft(myId, info.parentage(), ordinal);
|
||||
if (myVft == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1556,8 +1557,7 @@ public class CppCompositeType {
|
|||
}
|
||||
|
||||
myVft.setPtrOffsetInClass(finalOffset);
|
||||
VirtualFunctionTable parentVft =
|
||||
mvxtManager.findVft(parentId, parentParentage);
|
||||
VirtualFunctionTable parentVft = mvxtManager.findVft(parentId, parentParentage, null);
|
||||
|
||||
if (parentVft == null) {
|
||||
// this is an error
|
||||
|
@ -1669,7 +1669,8 @@ public class CppCompositeType {
|
|||
Long finalOffset = info.finalOffset();
|
||||
VirtualBaseTable myVbt = (VirtualBaseTable) finalVbtByOffset.get(finalOffset);
|
||||
if (myVbt == null) {
|
||||
myVbt = mvxtManager.findVbt(myId, info.parentage());
|
||||
Integer ordinal = getOrdinalOfKey(finalVbtByOffset, finalOffset);
|
||||
myVbt = mvxtManager.findVbt(myId, info.parentage(), ordinal);
|
||||
if (myVbt == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1677,8 +1678,7 @@ public class CppCompositeType {
|
|||
}
|
||||
|
||||
myVbt.setPtrOffsetInClass(finalOffset);
|
||||
VirtualBaseTable parentVbt =
|
||||
mvxtManager.findVbt(parentId, parentParentage);
|
||||
VirtualBaseTable parentVbt = mvxtManager.findVbt(parentId, parentParentage, null);
|
||||
if (parentVbt == null) {
|
||||
// this is an error
|
||||
return null;
|
||||
|
@ -1693,6 +1693,17 @@ public class CppCompositeType {
|
|||
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
|
||||
* @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) {
|
||||
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) {
|
||||
off += baseType.getSelfBaseType().getAlignedLength();
|
||||
off += baseType.getSelfBaseType().getLength();
|
||||
}
|
||||
}
|
||||
return plvbt;
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue