mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-5559 - PDB - Work around issue with finding primary vxt by symbol
This commit is contained in:
parent
e4036f04b9
commit
c32bc2a129
2 changed files with 150 additions and 74 deletions
|
@ -124,8 +124,8 @@ public class MsftVxtManager extends VxtManager {
|
|||
// memory are the same order that their pointers appear in the classes... this is based solely
|
||||
// on limited experience. The solution stinks and would benefit from the original direction
|
||||
// of using the parentage. We will try to use the parentage as a litmus test on retrieval
|
||||
private Map<ClassID, TreeMap<Address, VirtualBaseTable>> vbtsByOwner;
|
||||
private Map<ClassID, TreeMap<Address, VirtualFunctionTable>> vftsByOwner;
|
||||
private Map<ClassID, List<VirtualBaseTable>> vbtsByOwner;
|
||||
private Map<ClassID, List<VirtualFunctionTable>> vftsByOwner;
|
||||
|
||||
// Used for locating vft and vbt
|
||||
// These are explicitly used for storing/retrieving the "program" versions which result from
|
||||
|
@ -173,27 +173,73 @@ public class MsftVxtManager extends VxtManager {
|
|||
/**
|
||||
* Finds the putative {@link VirtualBaseTable} in memory requested for the owning class
|
||||
* @param owner the owning class of the table
|
||||
* @param parentage the primary parentage (only used if creating placeholder)
|
||||
* @return the table
|
||||
*/
|
||||
public VirtualBaseTable findPrimaryVbt(ClassID owner) {
|
||||
TreeMap<Address, VirtualBaseTable> map = vbtsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
public VirtualBaseTable findPrimaryVbt(ClassID owner, List<ClassID> parentage) {
|
||||
List<VirtualBaseTable> list = vbtsByOwner.get(owner);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
return map.firstEntry().getValue();
|
||||
VirtualBaseTable result = null;
|
||||
VirtualBaseTable firstPlaceholder = null;
|
||||
Address addrResult = null;
|
||||
for (VirtualBaseTable table : list) {
|
||||
if (table instanceof ProgramVirtualBaseTable pvbt) {
|
||||
Address addr = pvbt.getAddress();
|
||||
if (addrResult == null || addr.compareTo(addrResult) < 0) {
|
||||
addrResult = addr;
|
||||
result = table;
|
||||
}
|
||||
}
|
||||
else if (firstPlaceholder == null) {
|
||||
firstPlaceholder = table;
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
if (firstPlaceholder != null) {
|
||||
return firstPlaceholder;
|
||||
}
|
||||
result = new PlaceholderVirtualBaseTable(owner, parentage);
|
||||
list.add(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the putative {@link VirtualFunctionTable} in memory requested for the owning class
|
||||
* @param owner the owning class of the table
|
||||
* @param parentage the primary parentage (only used if creating placeholder)
|
||||
* @return the table
|
||||
*/
|
||||
public VirtualFunctionTable findPrimaryVft(ClassID owner) {
|
||||
TreeMap<Address, VirtualFunctionTable> map = vftsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
public VirtualFunctionTable findPrimaryVft(ClassID owner, List<ClassID> parentage) {
|
||||
List<VirtualFunctionTable> list = vftsByOwner.get(owner);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
return map.firstEntry().getValue();
|
||||
VirtualFunctionTable result = null;
|
||||
VirtualFunctionTable firstPlaceholder = null;
|
||||
Address addrResult = null;
|
||||
for (VirtualFunctionTable table : list) {
|
||||
if (table instanceof ProgramVirtualFunctionTable pvft) {
|
||||
Address addr = pvft.getAddress();
|
||||
if (addrResult == null || addr.compareTo(addrResult) < 0) {
|
||||
addrResult = addr;
|
||||
result = table;
|
||||
}
|
||||
}
|
||||
else if (firstPlaceholder == null) {
|
||||
firstPlaceholder = table;
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
if (firstPlaceholder != null) {
|
||||
return firstPlaceholder;
|
||||
}
|
||||
result = new PlaceholderVirtualFunctionTable(owner, parentage);
|
||||
list.add(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,7 +257,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
* @return the IDs
|
||||
*/
|
||||
public ClassID[] getAllVftOwners() {
|
||||
ClassID ids[] = new ClassID[vbtsByOwner.size()];
|
||||
ClassID ids[] = new ClassID[vftsByOwner.size()];
|
||||
Set<ClassID> set = vftsByOwner.keySet();
|
||||
return set.toArray(ids);
|
||||
}
|
||||
|
@ -222,12 +268,11 @@ public class MsftVxtManager extends VxtManager {
|
|||
* @return the tables
|
||||
*/
|
||||
public VirtualBaseTable[] getVbts(ClassID owner) {
|
||||
TreeMap<Address, VirtualBaseTable> map = vbtsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
List<VirtualBaseTable> list = vbtsByOwner.get(owner);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<VirtualBaseTable> values = map.values();
|
||||
return values.toArray(new VirtualBaseTable[values.size()]);
|
||||
return list.toArray(new VirtualBaseTable[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,12 +281,11 @@ public class MsftVxtManager extends VxtManager {
|
|||
* @return the tables
|
||||
*/
|
||||
public VirtualFunctionTable[] getVfts(ClassID owner) {
|
||||
TreeMap<Address, VirtualFunctionTable> map = vftsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
List<VirtualFunctionTable> list = vftsByOwner.get(owner);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<VirtualFunctionTable> values = map.values();
|
||||
return values.toArray(new VirtualFunctionTable[values.size()]);
|
||||
return list.toArray(new VirtualFunctionTable[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,6 +308,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
vbt = new PlaceholderVirtualBaseTable(owner, parentage);
|
||||
}
|
||||
vbtsByOwnerParentage.put(op, vbt);
|
||||
storeVbt(owner, vbt);
|
||||
return vbt;
|
||||
}
|
||||
|
||||
|
@ -309,6 +354,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
vft = new PlaceholderVirtualFunctionTable(owner, parentage);
|
||||
}
|
||||
vftsByOwnerParentage.put(op, vft);
|
||||
storeVft(owner, vft);
|
||||
return vft;
|
||||
}
|
||||
|
||||
|
@ -417,7 +463,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
}
|
||||
node.setVBTable(prvbt);
|
||||
vbtByAddress.put(address, prvbt);
|
||||
storeVbt(owner, address, prvbt); // temp solution?
|
||||
storeVbt(owner, prvbt); // temp solution?
|
||||
break;
|
||||
|
||||
case VFT:
|
||||
|
@ -429,7 +475,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
}
|
||||
node.setVFTable(vft);
|
||||
vftByAddress.put(address, vft);
|
||||
storeVft(owner, address, vft); // temp solution?
|
||||
storeVft(owner, vft); // temp solution?
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -438,22 +484,49 @@ public class MsftVxtManager extends VxtManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void storeVbt(ClassID owner, Address address, VirtualBaseTable vbt) {
|
||||
TreeMap<Address, VirtualBaseTable> map = vbtsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
map = new TreeMap<>();
|
||||
vbtsByOwner.put(owner, map);
|
||||
private void storeVbt(ClassID owner, VirtualBaseTable vbt) {
|
||||
ClassID own = vbt.getOwner();
|
||||
List<VirtualBaseTable> list = vbtsByOwner.get(own);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
vbtsByOwner.put(owner, list);
|
||||
}
|
||||
map.put(address, vbt);
|
||||
List<ClassID> parentage = vbt.getParentage();
|
||||
for (VirtualBaseTable table : list) {
|
||||
if (isEqual(table.getParentage(), parentage)) {
|
||||
return; // return without saving
|
||||
}
|
||||
}
|
||||
list.add(vbt);
|
||||
}
|
||||
|
||||
private void storeVft(ClassID owner, Address address, VirtualFunctionTable vft) {
|
||||
TreeMap<Address, VirtualFunctionTable> map = vftsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
map = new TreeMap<>();
|
||||
vftsByOwner.put(owner, map);
|
||||
private void storeVft(ClassID owner, VirtualFunctionTable vft) {
|
||||
List<VirtualFunctionTable> list = vftsByOwner.get(owner);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
vftsByOwner.put(owner, list);
|
||||
}
|
||||
map.put(address, vft);
|
||||
List<ClassID> parentage = vft.getParentage();
|
||||
for (VirtualFunctionTable table : list) {
|
||||
if (isEqual(table.getParentage(), parentage)) {
|
||||
return; // return without saving
|
||||
}
|
||||
}
|
||||
list.add(vft);
|
||||
}
|
||||
|
||||
private boolean isEqual(List<ClassID> parentage1, List<ClassID> parentage2) {
|
||||
int diff = parentage1.size() - parentage2.size();
|
||||
if (diff != 0) {
|
||||
return false;
|
||||
}
|
||||
Iterator<ClassID> iter2 = parentage2.iterator();
|
||||
for (ClassID element : parentage1) {
|
||||
if (!element.equals(iter2.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ParentageNode findNode(ClassID owner, List<ClassID> parentage, ParentageNode root) {
|
||||
|
|
|
@ -1231,30 +1231,37 @@ public class CppCompositeType {
|
|||
// Note that if the parent has already had its layout done, it will not have
|
||||
// used the vxtManager that we are passing in here; it will have used whatever
|
||||
// was passed to the layout method for that class
|
||||
if (cppBaseType.getPropagatedSelfBaseVfts() != null) {
|
||||
for (VxtPtrInfo parentInfo : cppBaseType.getPropagatedSelfBaseVfts()) {
|
||||
VxtPtrInfo newInfo =
|
||||
createSelfOwnedDirectVxtPtrInfo(parentInfo, baseId, baseOffset);
|
||||
updateVft(vxtManager, baseId, newInfo, parentInfo);
|
||||
storeVxtInfo(propagatedSelfBaseVfts, finalVftPtrInfoByOffset, vftTableIdByOffset,
|
||||
storeVxtInfo(propagatedSelfBaseVfts, finalVftPtrInfoByOffset,
|
||||
vftTableIdByOffset,
|
||||
vftOffsetByTableId, newInfo);
|
||||
}
|
||||
}
|
||||
if (cppBaseType.getPropagatedSelfBaseVbts() != null) {
|
||||
for (VxtPtrInfo parentInfo : cppBaseType.getPropagatedSelfBaseVbts()) {
|
||||
VxtPtrInfo newInfo =
|
||||
createSelfOwnedDirectVxtPtrInfo(parentInfo, baseId, baseOffset);
|
||||
updateVbt(vxtManager, baseId, newInfo, parentInfo);
|
||||
storeVxtInfo(propagatedSelfBaseVbts, finalVbtPtrInfoByOffset, vbtTableIdByOffset,
|
||||
storeVxtInfo(propagatedSelfBaseVbts, finalVbtPtrInfoByOffset,
|
||||
vbtTableIdByOffset,
|
||||
vbtOffsetByTableId, newInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all virtual base and virtual function pointers in the hierarchy of this class's
|
||||
* virtual bases. Gathers results from the accumulation of all "direct" virtual base classes;
|
||||
* we are not relying on the "indirect" virtual base class information from the PDB. This
|
||||
* is done this way so that we can collect parentage information for the pointers.
|
||||
* @throws PdbException upon issue finding base offset
|
||||
*/
|
||||
private void findVirtualBaseVxtPtrs(MsftVxtManager vxtManager) {
|
||||
private void findVirtualBaseVxtPtrs(MsftVxtManager vxtManager) throws PdbException {
|
||||
// Walk direct bases to find vxts of virtual bases. TODO: also notate all rolled up
|
||||
// virtuals for each direct base.
|
||||
for (DirectLayoutBaseClass base : directLayoutBaseClasses) {
|
||||
|
@ -1396,10 +1403,16 @@ public class CppCompositeType {
|
|||
* Converts VxtPtrInfo from virtual-based-owned direct or indirect virtual base for this class
|
||||
* @param baseInfo the vxt info from the base
|
||||
* @return the new VxtPtrInfo for this class
|
||||
* @throws PdbException upon issue getting base offset
|
||||
*/
|
||||
private VxtPtrInfo createVirtualOwnedVirtualVxtPtrInfo(VxtPtrInfo baseInfo) {
|
||||
private VxtPtrInfo createVirtualOwnedVirtualVxtPtrInfo(VxtPtrInfo baseInfo)
|
||||
throws PdbException {
|
||||
Long accumOffset = baseInfo.accumOffset();
|
||||
Long finalOffset = accumOffset + baseOffsetById.get(baseInfo.baseId());
|
||||
Long baseOffset = baseOffsetById.get(baseInfo.baseId());
|
||||
if (baseOffset == null) {
|
||||
throw new PdbException("Cannot find base offset");
|
||||
}
|
||||
Long finalOffset = accumOffset + baseOffset;
|
||||
return new VxtPtrInfo(finalOffset, accumOffset, baseInfo.baseId(),
|
||||
updateParentage(baseInfo));
|
||||
}
|
||||
|
@ -1440,20 +1453,10 @@ public class CppCompositeType {
|
|||
myVftPtrOffset = vftPtrTypeByOffset.firstKey();
|
||||
VxtPtrInfo info =
|
||||
new VxtPtrInfo(myVftPtrOffset, myVftPtrOffset, myId, List.of(myId));
|
||||
VirtualFunctionTable myVft =
|
||||
vxtManager.findVft(myId, List.of(myId));
|
||||
if (myVft != null) {
|
||||
VirtualFunctionTable myVft = vxtManager.findVft(myId, info.parentage());
|
||||
myVft.setPtrOffsetInClass(info.finalOffset());
|
||||
propagatedSelfBaseVfts.add(info);
|
||||
finalVftByOffset.put(info.finalOffset(), myVft);
|
||||
}
|
||||
else {
|
||||
PlaceholderVirtualFunctionTable t = new PlaceholderVirtualFunctionTable(
|
||||
myId, List.of(myId));
|
||||
t.setPtrOffsetInClass(info.finalOffset());
|
||||
propagatedSelfBaseVfts.add(info);
|
||||
finalVftByOffset.put(info.finalOffset(), t);
|
||||
}
|
||||
finalVftPtrInfoByOffset.put(info.accumOffset(), info);
|
||||
OwnerParentage op = new OwnerParentage(info.baseId(), info.parentage());
|
||||
vftTableIdByOffset.put(info.accumOffset(), op);
|
||||
|
@ -1473,8 +1476,8 @@ public class CppCompositeType {
|
|||
* structure
|
||||
*/
|
||||
private void findOrAllocateMainVbtPtr(MsftVxtManager vxtManager) {
|
||||
if (propagatedSelfBaseVbts.isEmpty()) {
|
||||
if (!virtualLayoutBaseClasses.isEmpty()) {
|
||||
if (propagatedSelfBaseVbts.isEmpty()) { // a pointer might be available in a direct base
|
||||
if (!virtualLayoutBaseClasses.isEmpty()) { // there is a need for a main vbtptr
|
||||
TreeSet<Long> vbtOffsets = new TreeSet<>();
|
||||
for (VirtualLayoutBaseClass base : virtualLayoutBaseClasses) {
|
||||
vbtOffsets.add((long) base.getBasePointerOffset());
|
||||
|
@ -1487,12 +1490,10 @@ 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, List.of(myId));
|
||||
if (myVbt != null) {
|
||||
VirtualBaseTable myVbt = vxtManager.findVbt(myId, info.parentage());
|
||||
myVbt.setPtrOffsetInClass(info.finalOffset());
|
||||
propagatedSelfBaseVbts.add(info);
|
||||
finalVbtByOffset.put(info.finalOffset(), myVbt);
|
||||
}
|
||||
finalVbtPtrInfoByOffset.put(info.accumOffset(), info);
|
||||
OwnerParentage op = new OwnerParentage(info.baseId(), info.parentage());
|
||||
vbtTableIdByOffset.put(info.accumOffset(), op);
|
||||
|
@ -1699,7 +1700,7 @@ public class CppCompositeType {
|
|||
private VirtualFunctionTable getMainVft(MsftVxtManager vxtManager) throws PdbException {
|
||||
if (!finalVftPtrInfoByOffset.isEmpty()) {
|
||||
VxtPtrInfo firstVftPtrInfo = finalVftPtrInfoByOffset.firstEntry().getValue();
|
||||
VirtualFunctionTable vft = vxtManager.findVft(myId, firstVftPtrInfo.parentage());
|
||||
VirtualFunctionTable vft = vxtManager.findPrimaryVft(myId, firstVftPtrInfo.parentage());
|
||||
return vft;
|
||||
// Following is for consideration for testing without a program:
|
||||
// if (vft instanceof ProgramVirtualFunctionTable pvft) {
|
||||
|
@ -1723,7 +1724,7 @@ public class CppCompositeType {
|
|||
private VirtualBaseTable getMainVbt(MsftVxtManager vxtManager) throws PdbException {
|
||||
if (!finalVbtPtrInfoByOffset.isEmpty()) {
|
||||
VxtPtrInfo firstVbtPtrInfo = finalVbtPtrInfoByOffset.firstEntry().getValue();
|
||||
VirtualBaseTable vbt = vxtManager.findVbt(myId, firstVbtPtrInfo.parentage());
|
||||
VirtualBaseTable vbt = vxtManager.findPrimaryVbt(myId, firstVbtPtrInfo.parentage());
|
||||
if (vbt instanceof ProgramVirtualBaseTable pvbt) {
|
||||
return pvbt;
|
||||
}
|
||||
|
@ -1747,10 +1748,12 @@ public class CppCompositeType {
|
|||
return plvbt;
|
||||
}
|
||||
else {
|
||||
if (vbt != null) {
|
||||
throw new PdbException(
|
||||
"VBT type not expected: " + vbt.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue