mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 01:39:21 +02:00
GP-5323 - PDB - improve vxtables and test set up
This commit is contained in:
parent
73b74cced5
commit
c6a3300fe8
6 changed files with 515 additions and 217 deletions
|
@ -25,7 +25,7 @@ import ghidra.app.util.demangler.microsoft.MicrosoftMangledContext;
|
|||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.CategoryPath;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -52,7 +52,7 @@ import mdemangler.typeinfo.*;
|
|||
*/
|
||||
public class MsftVxtManager extends VxtManager {
|
||||
|
||||
private Memory memory;
|
||||
private Program program;
|
||||
private Map<String, Address> vxtAddressByMangled;
|
||||
private Map<String, ParentageNode> parentageNodeByMangled;
|
||||
|
||||
|
@ -72,11 +72,11 @@ public class MsftVxtManager extends VxtManager {
|
|||
/**
|
||||
* Constructor for this class
|
||||
* @param ctm the class type manager
|
||||
* @param memory the memory of the program
|
||||
* @param program the program
|
||||
*/
|
||||
public MsftVxtManager(ClassTypeManager ctm, Memory memory) {
|
||||
public MsftVxtManager(ClassTypeManager ctm, Program program) {
|
||||
super(ctm);
|
||||
this.memory = memory;
|
||||
this.program = program;
|
||||
vxtAddressByMangled = new HashMap<>();
|
||||
parentageNodeByMangled = new HashMap<>();
|
||||
vbtsByOwner = new HashMap<>();
|
||||
|
@ -110,6 +110,54 @@ public class MsftVxtManager extends VxtManager {
|
|||
return map.firstEntry().getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class IDs of all owners of VBTs
|
||||
* @return the IDs
|
||||
*/
|
||||
public ClassID[] getAllVbtOwners() {
|
||||
ClassID ids[] = new ClassID[vbtsByOwner.size()];
|
||||
Set<ClassID> set = vbtsByOwner.keySet();
|
||||
return set.toArray(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class IDs of all owners of VFTs
|
||||
* @return the IDs
|
||||
*/
|
||||
public ClassID[] getAllVftOwners() {
|
||||
ClassID ids[] = new ClassID[vbtsByOwner.size()];
|
||||
Set<ClassID> set = vftsByOwner.keySet();
|
||||
return set.toArray(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ordered in-memory {@link VBTable}s for the owning class
|
||||
* @param owner the owning class of the table
|
||||
* @return the tables
|
||||
*/
|
||||
public VBTable[] getVbts(ClassID owner) {
|
||||
TreeMap<Address, VBTable> map = vbtsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<VBTable> values = map.values();
|
||||
return values.toArray(new VBTable[values.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ordered in-memory {@link VFTable}s for the owning class
|
||||
* @param owner the owning class of the table
|
||||
* @return the tables
|
||||
*/
|
||||
public VFTable[] getVfts(ClassID owner) {
|
||||
TreeMap<Address, VFTable> map = vftsByOwner.get(owner);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<VFTable> values = map.values();
|
||||
return values.toArray(new VFTable[values.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the putative {@link VBTable} in memory requested for the owning class and the
|
||||
* specified parentage
|
||||
|
@ -245,7 +293,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
switch (demanglerResults.vtType()) {
|
||||
case VBT:
|
||||
ProgramVirtualBaseTable prvbt = new ProgramVirtualBaseTable(owner, parentage,
|
||||
memory, address, ctm.getDefaultVbtTableElementSize(), ctm, mangled);
|
||||
program, address, ctm.getDefaultVbtTableElementSize(), ctm, mangled);
|
||||
if (node.getVBTable() != null) {
|
||||
Msg.warn(this, "VBT already exists at node for " + mangled);
|
||||
return false;
|
||||
|
@ -257,7 +305,7 @@ public class MsftVxtManager extends VxtManager {
|
|||
|
||||
case VFT:
|
||||
ProgramVirtualFunctionTable vft = new ProgramVirtualFunctionTable(owner, parentage,
|
||||
memory, address, ctm.getDefaultVftTableElementSize(), mangled);
|
||||
program, address, ctm.getDefaultVftTableElementSize(), mangled);
|
||||
if (node.getVFTable() != null) {
|
||||
Msg.warn(this, "VFT already exists at node for " + mangled);
|
||||
return false;
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.*;
|
|||
|
||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
|
||||
|
@ -27,7 +28,7 @@ import ghidra.program.model.mem.MemoryAccessException;
|
|||
*/
|
||||
public class ProgramVirtualBaseTable extends VirtualBaseTable {
|
||||
|
||||
private Memory memory;
|
||||
private Program program;
|
||||
private Address address;
|
||||
private int entrySize;
|
||||
private String mangledName; // remove?
|
||||
|
@ -44,19 +45,19 @@ public class ProgramVirtualBaseTable extends VirtualBaseTable {
|
|||
* Constructor
|
||||
* @param owner the class that owns the table
|
||||
* @param parentage the parentage of the base class(es) of the table
|
||||
* @param memory the program memory
|
||||
* @param program the program
|
||||
* @param address the address of the table
|
||||
* @param entrySize the size for each table entry
|
||||
* @param ctm the class type manager
|
||||
* @param mangledName the mangled name of the table
|
||||
*/
|
||||
public ProgramVirtualBaseTable(ClassID owner, List<ClassID> parentage, Memory memory,
|
||||
public ProgramVirtualBaseTable(ClassID owner, List<ClassID> parentage, Program program,
|
||||
Address address, int entrySize, ClassTypeManager ctm, String mangledName) {
|
||||
super(owner, parentage);
|
||||
if (entrySize != 4 && entrySize != 8) {
|
||||
throw new IllegalArgumentException("Invalid size (" + entrySize + "): must be 4 or 8.");
|
||||
}
|
||||
this.memory = memory;
|
||||
this.program = program;
|
||||
this.address = address;
|
||||
this.entrySize = entrySize;
|
||||
this.mangledName = mangledName;
|
||||
|
@ -98,6 +99,7 @@ public class ProgramVirtualBaseTable extends VirtualBaseTable {
|
|||
|
||||
@Override
|
||||
public Long getBaseOffset(int index) throws PdbException {
|
||||
Memory memory = program.getMemory();
|
||||
Address entryAddress = address.add(index * entrySize);
|
||||
try {
|
||||
Long offset = (entrySize == 4) ? (long) memory.getInt(entryAddress)
|
||||
|
|
|
@ -20,14 +20,16 @@ import java.util.List;
|
|||
import ghidra.app.util.SymbolPath;
|
||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
|
||||
/**
|
||||
* Manages virtual function table lookups.
|
||||
*/
|
||||
public class ProgramVirtualFunctionTable extends VirtualFunctionTable {
|
||||
|
||||
private Memory memory;
|
||||
private Program program;
|
||||
private Address address;
|
||||
private int defaultEntrySize; // Might go away, as would constructor param
|
||||
private String mangledName;
|
||||
|
@ -36,19 +38,19 @@ public class ProgramVirtualFunctionTable extends VirtualFunctionTable {
|
|||
* Constructor
|
||||
* @param owner the owner class
|
||||
* @param parentage the parentage for the table
|
||||
* @param memory the program memory
|
||||
* @param program the program
|
||||
* @param address the address of the table in memory
|
||||
* @param defaultEntrySize the default entry size
|
||||
* @param mangledName the mangled name for the table
|
||||
*/
|
||||
public ProgramVirtualFunctionTable(ClassID owner, List<ClassID> parentage, Memory memory,
|
||||
public ProgramVirtualFunctionTable(ClassID owner, List<ClassID> parentage, Program program,
|
||||
Address address, int defaultEntrySize, String mangledName) {
|
||||
super(owner, parentage);
|
||||
if (defaultEntrySize != 4 && defaultEntrySize != 8) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid size (" + defaultEntrySize + "): must be 4 or 8.");
|
||||
}
|
||||
this.memory = memory;
|
||||
this.program = program;
|
||||
this.address = address;
|
||||
this.defaultEntrySize = defaultEntrySize;
|
||||
this.mangledName = mangledName;
|
||||
|
@ -72,7 +74,24 @@ public class ProgramVirtualFunctionTable extends VirtualFunctionTable {
|
|||
|
||||
@Override
|
||||
public Address getAddress(int ordinal) throws PdbException {
|
||||
throw new UnsupportedOperationException();
|
||||
Memory memory = program.getMemory();
|
||||
Address entryAddress = address.add(ordinal * defaultEntrySize);
|
||||
try {
|
||||
long offset =
|
||||
(defaultEntrySize == 4) ? Integer.toUnsignedLong(memory.getInt(entryAddress))
|
||||
: memory.getLong(entryAddress);
|
||||
if (offset == 0L) {
|
||||
return null;
|
||||
}
|
||||
Address result = address.getNewAddress(offset, false);
|
||||
return result;
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
throw new PdbException(
|
||||
"MemoryAccessException while trying to parse virtual function table entry at address: " +
|
||||
entryAddress);
|
||||
}
|
||||
//throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -638,7 +638,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
|||
if (program != null) {
|
||||
// Currently, this must happen after symbolGroups are created.
|
||||
MsftVxtManager msftVxtManager =
|
||||
new MsftVxtManager(getClassTypeManager(), program.getMemory());
|
||||
new MsftVxtManager(getClassTypeManager(), program);
|
||||
msftVxtManager.createVirtualTables(getRootPdbCategory(), findVirtualTableSymbols(), log,
|
||||
monitor);
|
||||
vxtManager = msftVxtManager;
|
||||
|
|
|
@ -19,14 +19,18 @@ import static org.junit.Assert.*;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.plugin.core.checksums.MyTestMemory;
|
||||
import ghidra.app.util.SymbolPath;
|
||||
import ghidra.app.util.SymbolPathParser;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressIterator;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.LittleEndianDataConverter;
|
||||
|
@ -51,31 +55,100 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
private static ClassTypeManager ctm32;
|
||||
private static ClassTypeManager ctm64;
|
||||
|
||||
private ClassID a1Id = new ProgramClassID(CategoryPath.ROOT, sp("A1NS::A1"));
|
||||
private ClassID a2Id = new ProgramClassID(CategoryPath.ROOT, sp("A2NS::A2"));
|
||||
private ClassID aId = new ProgramClassID(CategoryPath.ROOT, sp("ANS::A"));
|
||||
private ClassID b1Id = new ProgramClassID(CategoryPath.ROOT, sp("B1NS::B1"));
|
||||
private ClassID b2Id = new ProgramClassID(CategoryPath.ROOT, sp("B2NS::B2"));
|
||||
private ClassID bId = new ProgramClassID(CategoryPath.ROOT, sp("BNS::B"));
|
||||
private ClassID cId = new ProgramClassID(CategoryPath.ROOT, sp("CNS::C"));
|
||||
private ClassID dId = new ProgramClassID(CategoryPath.ROOT, sp("DNS::D"));
|
||||
private ClassID eId = new ProgramClassID(CategoryPath.ROOT, sp("ENS::E"));
|
||||
private ClassID fId = new ProgramClassID(CategoryPath.ROOT, sp("FNS::F"));
|
||||
private ClassID gId = new ProgramClassID(CategoryPath.ROOT, sp("GNS::G"));
|
||||
private ClassID hId = new ProgramClassID(CategoryPath.ROOT, sp("HNS::H"));
|
||||
private ClassID iId = new ProgramClassID(CategoryPath.ROOT, sp("INS::I"));
|
||||
private ClassID jId = new ProgramClassID(CategoryPath.ROOT, sp("JNS::J"));
|
||||
private ClassID kId = new ProgramClassID(CategoryPath.ROOT, sp("KNS::K"));
|
||||
private ClassID lId = new ProgramClassID(CategoryPath.ROOT, sp("LNS::L"));
|
||||
private ClassID mId = new ProgramClassID(CategoryPath.ROOT, sp("MNS::M"));
|
||||
private static int[] dummyVftMeta = new int[] { 0 };
|
||||
|
||||
private static ClassID A1_ID = new ProgramClassID(CategoryPath.ROOT, sp("A1NS::A1"));
|
||||
private static ClassID A2_ID = new ProgramClassID(CategoryPath.ROOT, sp("A2NS::A2"));
|
||||
private static ClassID A_ID = new ProgramClassID(CategoryPath.ROOT, sp("ANS::A"));
|
||||
private static ClassID B1_ID = new ProgramClassID(CategoryPath.ROOT, sp("B1NS::B1"));
|
||||
private static ClassID B2_ID = new ProgramClassID(CategoryPath.ROOT, sp("B2NS::B2"));
|
||||
private static ClassID B_ID = new ProgramClassID(CategoryPath.ROOT, sp("BNS::B"));
|
||||
private static ClassID C_ID = new ProgramClassID(CategoryPath.ROOT, sp("CNS::C"));
|
||||
private static ClassID D_ID = new ProgramClassID(CategoryPath.ROOT, sp("DNS::D"));
|
||||
private static ClassID E_ID = new ProgramClassID(CategoryPath.ROOT, sp("ENS::E"));
|
||||
private static ClassID F_ID = new ProgramClassID(CategoryPath.ROOT, sp("FNS::F"));
|
||||
private static ClassID G_ID = new ProgramClassID(CategoryPath.ROOT, sp("GNS::G"));
|
||||
private static ClassID H_ID = new ProgramClassID(CategoryPath.ROOT, sp("HNS::H"));
|
||||
private static ClassID I_ID = new ProgramClassID(CategoryPath.ROOT, sp("INS::I"));
|
||||
private static ClassID J_ID = new ProgramClassID(CategoryPath.ROOT, sp("JNS::J"));
|
||||
private static ClassID K_ID = new ProgramClassID(CategoryPath.ROOT, sp("KNS::K"));
|
||||
private static ClassID L_ID = new ProgramClassID(CategoryPath.ROOT, sp("LNS::L"));
|
||||
private static ClassID M_ID = new ProgramClassID(CategoryPath.ROOT, sp("MNS::M"));
|
||||
|
||||
private static Function A1NS_A1_fa1_1 = new FunctionTestDouble("A1NS::A1::fa1_1");
|
||||
private static Function A1NS_A1_fa1_2 = new FunctionTestDouble("A1NS::A1::fa1_2");
|
||||
private static Function A1NS_A1_fa1_3 = new FunctionTestDouble("A1NS::A1::fa1_3");
|
||||
private static Function A2NS_A2_fa2_1 = new FunctionTestDouble("A2NS::A2::fa2_1");
|
||||
private static Function A2NS_A2_fa2_2 = new FunctionTestDouble("A2NS::A2::fa2_2");
|
||||
private static Function A2NS_A2_fa2_3 = new FunctionTestDouble("A2NS::A2::fa2_3");
|
||||
private static Function ANS_A_fa1_1 = new FunctionTestDouble("ANS::A::fa1_1");
|
||||
private static Function ANS_A_fa2_1 = new FunctionTestDouble("ANS::A::fa2_1");
|
||||
private static Function ANS_A_fa_1 = new FunctionTestDouble("ANS::A::fa_1");
|
||||
private static Function ANS_A_fa1_1_thunkThisMinus16 =
|
||||
new FunctionTestDouble("ANS::A::fa1_1_thunkThisMinus16");
|
||||
private static Function ANS_A_fa2_1_thunkThisMinus4 =
|
||||
new FunctionTestDouble("ANS::A::fa2_1_thunkThisMinus4");
|
||||
private static Function B1NS_B1_fb1_1 = new FunctionTestDouble("B1NS::B1::fb1_1");
|
||||
private static Function B1NS_B1_fb1_2 = new FunctionTestDouble("B1NS::B1::fb1_2");
|
||||
private static Function B1NS_B1_fb1_3 = new FunctionTestDouble("B1NS::B1::fb1_3");
|
||||
private static Function B2NS_B2_fb2_1 = new FunctionTestDouble("B2NS::B2::fb2_1");
|
||||
private static Function B2NS_B2_fb2_2 = new FunctionTestDouble("B2NS::B2::fb2_2");
|
||||
private static Function B2NS_B2_fb2_3 = new FunctionTestDouble("B2NS::B2::fb2_3");
|
||||
private static Function BNS_B_fb1_1 = new FunctionTestDouble("BNS::B::fb1_1");
|
||||
private static Function BNS_B_fb2_1 = new FunctionTestDouble("BNS::B::fb2_1");
|
||||
private static Function BNS_B_fb_1 = new FunctionTestDouble("BNS::B::fb_1");
|
||||
private static Function BNS_B_fb1_1_thunkThisMinus16 =
|
||||
new FunctionTestDouble("BNS::B::fb1_1_thunkThisMinus16");
|
||||
private static Function BNS_B_fb1_1_thunkThisPlus28 =
|
||||
new FunctionTestDouble("BNS::B::fb1_1_thunkThisPlus28");
|
||||
private static Function BNS_B_fb2_1_thunkThisPlus28 =
|
||||
new FunctionTestDouble("BNS::B::fb2_1_thunkThisPlus28");
|
||||
private static Function CNS_C_fa1_2 = new FunctionTestDouble("CNS::C::fa1_2");
|
||||
private static Function CNS_C_fa2_1 = new FunctionTestDouble("CNS::C::fa2_1");
|
||||
private static Function CNS_C_fb1_2 = new FunctionTestDouble("CNS::C::fb1_2");
|
||||
private static Function CNS_C_fb2_1 = new FunctionTestDouble("CNS::C::fb2_1");
|
||||
private static Function CNS_C_fc_1 = new FunctionTestDouble("CNS::C::fc_1");
|
||||
private static Function CNS_C_fa1_2_thunkThisMinus28 =
|
||||
new FunctionTestDouble("CNS::C::fa1_2_thunkThisMinus28");
|
||||
private static Function CNS_C_fb1_2_thunkThisMinus28 =
|
||||
new FunctionTestDouble("CNS::C::fb1_2_thunkThisMinus28");
|
||||
private static Function CNS_C_fa1_2_thunkThisMinus84 =
|
||||
new FunctionTestDouble("CNS::C::fa1_2_thunkThisMinus84");
|
||||
private static Function CNS_C_fb1_2_thunkThisMinus84 =
|
||||
new FunctionTestDouble("CNS::C::fb1_2_thunkThisMinus84");
|
||||
private static Function DNS_D_fa2_1 = new FunctionTestDouble("DNS::D::fa2_1");
|
||||
private static Function DNS_D_fb2_1 = new FunctionTestDouble("DNS::D::fb2_1");
|
||||
private static Function ENS_E_fa1_1 = new FunctionTestDouble("ENS::E::fa1_1");
|
||||
private static Function FNS_F_fa1_1 = new FunctionTestDouble("FNS::F::fa1_1");
|
||||
private static Function GNS_G_fa1_1 = new FunctionTestDouble("GNS::G::fa1_1");
|
||||
private static Function HNS_H_fa1_1 = new FunctionTestDouble("HNS::H::fa1_1");
|
||||
private static Function INS_I_fa1_1 = new FunctionTestDouble("INS::I::fa1_1");
|
||||
private static Function JNS_J_fa1_1 = new FunctionTestDouble("JNS::J::fa1_1");
|
||||
private static Function KNS_K_fa1_1 = new FunctionTestDouble("KNS::K::fa1_1");
|
||||
private static Function LNS_L_fa1_1 = new FunctionTestDouble("LNS::L::fa1_1");
|
||||
private static Function N1NS_N1_fn1_1 = new FunctionTestDouble("N1NS::N1::fn1_1");
|
||||
private static Function N1NS_N1_fn1_2 = new FunctionTestDouble("N1NS::N1::fn1_2");
|
||||
private static Function N2NS_N2_fn2_1 = new FunctionTestDouble("N2NS::N2::fn2_1");
|
||||
private static Function N2NS_N2_fn2_2 = new FunctionTestDouble("N2NS::N2::fn2_2");
|
||||
private static Function MNS_M_fa1_1 = new FunctionTestDouble("MNS::M::fa1_1");
|
||||
private static Function MNS_M_fa2_1 = new FunctionTestDouble("MNS::M::fa2_1");
|
||||
private static Function MNS_M_fb1_1 = new FunctionTestDouble("MNS::M::fb1_1");
|
||||
private static Function MNS_M_fb2_1 = new FunctionTestDouble("MNS::M::fb1_2");
|
||||
private static Function MNS_M_fn1_1 = new FunctionTestDouble("MNS::M::fn1_1");
|
||||
|
||||
private static Memory memory32;
|
||||
private static Memory memory64;
|
||||
private static Program program32;
|
||||
private static Program program64;
|
||||
private static List<Address> addresses32;
|
||||
private static List<Address> addresses64;
|
||||
|
||||
private static List<Function> functions;
|
||||
private static Map<Function, Integer> offsetsByFunction32 = new HashMap<>();
|
||||
private static Map<Function, Integer> offsetsByFunction64 = new HashMap<>();
|
||||
|
||||
private static List<String> vbtSymbols = new ArrayList<>();
|
||||
private static List<String> vftSymbols = new ArrayList<>();
|
||||
private static List<Address> vxtAddresses32;
|
||||
private static List<Address> vxtAddresses64;
|
||||
|
||||
private static Map<String, Address> addressByVxtMangledName32;
|
||||
private static Map<String, Address> addressByVxtMangledName64;
|
||||
|
@ -184,10 +257,10 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
// vbtptr32 = new PointerDataType(new IntegerDataType(dtm32));
|
||||
// vbtptr64 = new PointerDataType(new IntegerDataType(dtm64));
|
||||
|
||||
createVxTables();
|
||||
createMemoryAndPrograms();
|
||||
|
||||
mVxtManager32 = new MsftVxtManager(ctm32, memory32);
|
||||
mVxtManager64 = new MsftVxtManager(ctm64, memory64);
|
||||
mVxtManager32 = new MsftVxtManager(ctm32, program32);
|
||||
mVxtManager64 = new MsftVxtManager(ctm64, program64);
|
||||
|
||||
try {
|
||||
mVxtManager32.createVirtualTables(CategoryPath.ROOT, addressByVxtMangledName32, log,
|
||||
|
@ -201,6 +274,44 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
|
||||
}
|
||||
|
||||
private static class MyStubFunctionManager extends StubFunctionManager {
|
||||
|
||||
private Map<Address, Function> myFunctions;
|
||||
|
||||
private MyStubFunctionManager() {
|
||||
myFunctions = new HashMap<>();
|
||||
}
|
||||
|
||||
private void addFunction(Address address, Function function) {
|
||||
myFunctions.put(address, function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function getFunctionAt(Address entryPoint) {
|
||||
return myFunctions.get(entryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyStubProgram extends StubProgram {
|
||||
private Memory myMemory;
|
||||
private FunctionManager myFunctionManager;
|
||||
|
||||
private MyStubProgram(Memory mem, FunctionManager fm) {
|
||||
this.myMemory = mem;
|
||||
this.myFunctionManager = fm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionManager getFunctionManager() {
|
||||
return myFunctionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Memory getMemory() {
|
||||
return myMemory;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
private static SymbolPath sp(String s) {
|
||||
return new SymbolPath(SymbolPathParser.parse(s));
|
||||
|
@ -216,46 +327,69 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
}
|
||||
}
|
||||
|
||||
static class MemoryPreparer {
|
||||
private static class MemoryPreparer {
|
||||
private int nextOffset = 0;
|
||||
private List<int[]> intArrays = new ArrayList<>();
|
||||
private List<Integer> offsets = new ArrayList<>();
|
||||
private List<Integer> myOffsets = new ArrayList<>();
|
||||
private List<Address> addresses = new ArrayList<>();
|
||||
private MyTestMemory memory = null;
|
||||
private int mockAddressCounter = 0;
|
||||
|
||||
void addAddresses(int numAddresses, boolean is64bit) {
|
||||
private int addAddresses(int[] offsetsArg, boolean is64bit) {
|
||||
int[] integers;
|
||||
int startCount = mockAddressCounter;
|
||||
if (is64bit) {
|
||||
integers = new int[numAddresses * 2];
|
||||
for (int i = 0; i < numAddresses; i++) {
|
||||
integers[i * 2] = mockAddressCounter;
|
||||
integers = new int[offsetsArg.length * 2];
|
||||
for (int i = 0; i < offsetsArg.length; i++) {
|
||||
integers[i * 2] = offsetsArg[i];
|
||||
integers[i * 2 + 1] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
integers = offsetsArg;
|
||||
}
|
||||
addIntegers(integers);
|
||||
return startCount;
|
||||
}
|
||||
|
||||
private int addAddresses(int numAddresses, boolean is64bit) {
|
||||
int[] integers;
|
||||
int startCount = mockAddressCounter;
|
||||
if (is64bit) {
|
||||
integers = new int[numAddresses * 2];
|
||||
for (int i = 0; i < numAddresses; i++) {
|
||||
integers[i] = mockAddressCounter;
|
||||
integers[i * 2] = mockAddressCounter++;
|
||||
integers[i * 2 + 1] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
integers = new int[numAddresses];
|
||||
for (int i = 0; i < numAddresses; i++) {
|
||||
integers[i] = mockAddressCounter++;
|
||||
}
|
||||
}
|
||||
addIntegers(integers);
|
||||
return startCount;
|
||||
}
|
||||
|
||||
void addIntegers(int[] integers) {
|
||||
offsets.add(nextOffset);
|
||||
private int getNextOffset() {
|
||||
return nextOffset;
|
||||
}
|
||||
|
||||
private void addIntegers(int[] integers) {
|
||||
myOffsets.add(nextOffset);
|
||||
intArrays.add(integers);
|
||||
nextOffset += 4 * integers.length;
|
||||
}
|
||||
|
||||
List<Integer> getOffsets() {
|
||||
return offsets;
|
||||
private List<Integer> getOffsets() {
|
||||
return myOffsets;
|
||||
}
|
||||
|
||||
void finalizeMemory() {
|
||||
private void finalizeMemory() {
|
||||
byte[] bytes = new byte[nextOffset];
|
||||
for (int index = 0; index < offsets.size(); index++) {
|
||||
addBytesForIntegers(intArrays.get(index), bytes, offsets.get(index));
|
||||
for (int index = 0; index < myOffsets.size(); index++) {
|
||||
addBytesForIntegers(intArrays.get(index), bytes, myOffsets.get(index));
|
||||
}
|
||||
memory = new CppCompositeTestMemory(bytes);
|
||||
AddressIterator iter = memory.getAddresses(true);
|
||||
|
@ -263,16 +397,16 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
return;
|
||||
}
|
||||
Address address = iter.next();
|
||||
for (Integer offset : offsets) {
|
||||
for (Integer offset : myOffsets) {
|
||||
addresses.add(address.add(offset));
|
||||
}
|
||||
}
|
||||
|
||||
Memory getMemory() {
|
||||
private Memory getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
List<Address> getAddresses() {
|
||||
private List<Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
|
@ -299,7 +433,30 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
}
|
||||
}
|
||||
|
||||
static void createVxTables() {
|
||||
/**
|
||||
* Prepares Virtual Function Table for 32-bit and 64-bit memory models
|
||||
* @param preparer32 the MemoryPreparer for 32-bit
|
||||
* @param preparer64 the MemoryPreparer for 64-bit
|
||||
* @param mangledName the mangled name for the table
|
||||
* @param functionsArg varargs of functions for the table
|
||||
*/
|
||||
private static void prepareVfts(MemoryPreparer preparer32, MemoryPreparer preparer64,
|
||||
String mangledName, Function... functionsArg) {
|
||||
int offsets32[] = new int[functionsArg.length];
|
||||
int offsets64[] = new int[functionsArg.length];
|
||||
for (int i = 0; i < functionsArg.length; i++) {
|
||||
Function fn = functionsArg[i];
|
||||
offsets32[i] = offsetsByFunction32.get(fn);
|
||||
offsets64[i] = offsetsByFunction32.get(fn);
|
||||
}
|
||||
preparer32.addAddresses(dummyVftMeta, false);
|
||||
preparer64.addAddresses(dummyVftMeta, true);
|
||||
vftSymbols.add(mangledName);
|
||||
preparer32.addAddresses(offsets32, false);
|
||||
preparer64.addAddresses(offsets64, true);
|
||||
}
|
||||
|
||||
private static void createMemoryAndPrograms() {
|
||||
MemoryPreparer preparer32 = new MemoryPreparer();
|
||||
MemoryPreparer preparer64 = new MemoryPreparer();
|
||||
|
||||
|
@ -308,6 +465,30 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
|
||||
//==========================================================================================
|
||||
|
||||
functions = List.of(A1NS_A1_fa1_1, A1NS_A1_fa1_2, A1NS_A1_fa1_3, A2NS_A2_fa2_1,
|
||||
A2NS_A2_fa2_2, A2NS_A2_fa2_3, ANS_A_fa1_1, ANS_A_fa2_1, ANS_A_fa_1,
|
||||
ANS_A_fa1_1_thunkThisMinus16, ANS_A_fa2_1_thunkThisMinus4, B1NS_B1_fb1_1, B1NS_B1_fb1_2,
|
||||
B1NS_B1_fb1_3, B2NS_B2_fb2_1, B2NS_B2_fb2_2, B2NS_B2_fb2_3, BNS_B_fb1_1, BNS_B_fb2_1,
|
||||
BNS_B_fb_1, BNS_B_fb1_1_thunkThisMinus16, BNS_B_fb1_1_thunkThisPlus28,
|
||||
BNS_B_fb2_1_thunkThisPlus28, CNS_C_fa1_2, CNS_C_fa2_1, CNS_C_fb1_2, CNS_C_fb2_1,
|
||||
CNS_C_fc_1, CNS_C_fa1_2_thunkThisMinus28, CNS_C_fb1_2_thunkThisMinus28,
|
||||
CNS_C_fa1_2_thunkThisMinus84, CNS_C_fb1_2_thunkThisMinus84, DNS_D_fa2_1, DNS_D_fb2_1,
|
||||
ENS_E_fa1_1, FNS_F_fa1_1, GNS_G_fa1_1, HNS_H_fa1_1, INS_I_fa1_1, JNS_J_fa1_1,
|
||||
KNS_K_fa1_1, LNS_L_fa1_1, N1NS_N1_fn1_1, N1NS_N1_fn1_2, N2NS_N2_fn2_1, N2NS_N2_fn2_2,
|
||||
MNS_M_fa1_1, MNS_M_fa2_1, MNS_M_fb1_1, MNS_M_fb2_1, MNS_M_fn1_1);
|
||||
|
||||
for (Function f : functions) {
|
||||
int addressOffset32 = preparer32.getNextOffset();
|
||||
int addressOffset64 = preparer64.getNextOffset();
|
||||
int count32 = preparer32.addAddresses(1, false);
|
||||
int count64 = preparer64.addAddresses(1, true);
|
||||
assertEquals(count32, count64);
|
||||
offsetsByFunction32.put(f, addressOffset32);
|
||||
offsetsByFunction64.put(f, addressOffset64);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
||||
vbtSymbols.add("??_8A@ANS@@7B@");
|
||||
preparer32.addIntegers(new int[] { -4, 8, 16 });
|
||||
preparer64.addIntegers(new int[] { -8, 16, 32 });
|
||||
|
@ -373,32 +554,32 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
preparer64.addIntegers(new int[] { 0, 32 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BA@ANS@@E@ENS@@@");
|
||||
preparer32.addIntegers(new int[] { -4, 100, 108, 116, 124, 132 });
|
||||
preparer64.addIntegers(new int[] { -8, 200, 216, 232, 248, 264 });
|
||||
preparer32.addIntegers(new int[] { -4, 108, 116, 124, 132, 140, 100, 152 });
|
||||
preparer64.addIntegers(new int[] { -8, 216, 232, 248, 264, 280, 200, 304 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BC@CNS@@@");
|
||||
preparer32.addIntegers(new int[] { -4, 84, 92, 100, 108 });
|
||||
preparer64.addIntegers(new int[] { -8, 168, 184, 200, 216 });
|
||||
preparer32.addIntegers(new int[] { -4, 92, 100, 108, 116 });
|
||||
preparer64.addIntegers(new int[] { -8, 184, 200, 216, 232 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BA@ANS@@D@DNS@@@");
|
||||
preparer32.addIntegers(new int[] { -4, 72, 80 });
|
||||
preparer64.addIntegers(new int[] { -8, 144, 160 });
|
||||
preparer32.addIntegers(new int[] { -4, 80, 88 });
|
||||
preparer64.addIntegers(new int[] { -8, 160, 176 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BB@BNS@@D@DNS@@@");
|
||||
preparer32.addIntegers(new int[] { -4, 76, 84 });
|
||||
preparer64.addIntegers(new int[] { -8, 152, 168 });
|
||||
preparer32.addIntegers(new int[] { -4, 84, 92 });
|
||||
preparer64.addIntegers(new int[] { -8, 168, 184 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BG@GNS@@@");
|
||||
preparer32.addIntegers(new int[] { 0, 48 });
|
||||
preparer64.addIntegers(new int[] { 0, 96 });
|
||||
preparer32.addIntegers(new int[] { 0, 56 });
|
||||
preparer64.addIntegers(new int[] { 0, 112 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BH@HNS@@@");
|
||||
preparer32.addIntegers(new int[] { 0, 36 });
|
||||
preparer64.addIntegers(new int[] { 0, 72 });
|
||||
preparer32.addIntegers(new int[] { 0, 44 });
|
||||
preparer64.addIntegers(new int[] { 0, 88 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7B@");
|
||||
preparer32.addIntegers(new int[] { 0, 20 });
|
||||
preparer64.addIntegers(new int[] { 0, 40 });
|
||||
preparer32.addIntegers(new int[] { 0, 28 });
|
||||
preparer64.addIntegers(new int[] { 0, 56 });
|
||||
|
||||
vbtSymbols.add("??_8M@MNS@@7BB@BNS@@E@ENS@@@");
|
||||
preparer32.addIntegers(new int[] { -4, -20, -12 });
|
||||
|
@ -408,181 +589,133 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
// Below: writing one int to simulate one address for 32-bit and tow ints for 64-bit (lsb)
|
||||
// Later... mock up even better
|
||||
|
||||
vftSymbols.add("??_7A1@A1NS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7A1@A1NS@@6B@", A1NS_A1_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7A2@A2NS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7A2@A2NS@@6B@", A2NS_A2_fa2_1, A2NS_A2_fa2_2,
|
||||
A2NS_A2_fa2_3);
|
||||
|
||||
vftSymbols.add("??_7A@ANS@@6B01@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7A@ANS@@6B01@@", ANS_A_fa_1);
|
||||
|
||||
vftSymbols.add("??_7A@ANS@@6BA1@A1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7A@ANS@@6BA1@A1NS@@@", ANS_A_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7A@ANS@@6BA2@A2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7A@ANS@@6BA2@A2NS@@@", ANS_A_fa2_1, A2NS_A2_fa2_2,
|
||||
A2NS_A2_fa2_3);
|
||||
|
||||
vftSymbols.add("??_7B1@B1NS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7B1@B1NS@@6B@", B1NS_B1_fb1_1, B1NS_B1_fb1_2,
|
||||
B1NS_B1_fb1_3);
|
||||
|
||||
vftSymbols.add("??_7B2@B2NS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7B2@B2NS@@6B@", B2NS_B2_fb2_1, B2NS_B2_fb2_2,
|
||||
B2NS_B2_fb2_3);
|
||||
|
||||
vftSymbols.add("??_7B@BNS@@6B01@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7B@BNS@@6B01@@", BNS_B_fb_1);
|
||||
|
||||
vftSymbols.add("??_7B@BNS@@6BB1@B1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7B@BNS@@6BB1@B1NS@@@", BNS_B_fb1_1, B1NS_B1_fb1_2,
|
||||
B1NS_B1_fb1_3);
|
||||
|
||||
vftSymbols.add("??_7B@BNS@@6BB2@B2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7B@BNS@@6BB2@B2NS@@@", BNS_B_fb2_1, B2NS_B2_fb2_2,
|
||||
B2NS_B2_fb2_3);
|
||||
|
||||
vftSymbols.add("??_7C@CNS@@6B01@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7C@CNS@@6B01@@", CNS_C_fc_1);
|
||||
|
||||
vftSymbols.add("??_7C@CNS@@6BA1@A1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7C@CNS@@6BA1@A1NS@@@", A1NS_A1_fa1_1, CNS_C_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7C@CNS@@6BA2@A2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7C@CNS@@6BA2@A2NS@@@", CNS_C_fa2_1, A2NS_A2_fa2_2,
|
||||
A2NS_A2_fa2_3);
|
||||
|
||||
vftSymbols.add("??_7C@CNS@@6BB1@B1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7C@CNS@@6BB1@B1NS@@@", B1NS_B1_fb1_1, CNS_C_fb1_2,
|
||||
B1NS_B1_fb1_3);
|
||||
|
||||
vftSymbols.add("??_7C@CNS@@6BB2@B2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7C@CNS@@6BB2@B2NS@@@", CNS_C_fb2_1, B2NS_B2_fb2_2,
|
||||
B2NS_B2_fb2_3);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BC@CNS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BC@CNS@@@", CNS_C_fc_1);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BA@ANS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BA@ANS@@@", ANS_A_fa_1);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BB@BNS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BB@BNS@@@", BNS_B_fb_1);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BA1@A1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BA1@A1NS@@@", ANS_A_fa1_1_thunkThisMinus16,
|
||||
CNS_C_fa1_2_thunkThisMinus28, A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BA2@A2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BA2@A2NS@@@", DNS_D_fa2_1, A2NS_A2_fa2_2,
|
||||
A2NS_A2_fa2_3);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BB1@B1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BB1@B1NS@@@", BNS_B_fb1_1_thunkThisMinus16,
|
||||
CNS_C_fb1_2_thunkThisMinus28, B1NS_B1_fb1_3);
|
||||
|
||||
vftSymbols.add("??_7D@DNS@@6BB2@B2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7D@DNS@@6BB2@B2NS@@@", DNS_D_fb2_1, B2NS_B2_fb2_2,
|
||||
B2NS_B2_fb2_3);
|
||||
|
||||
vftSymbols.add("??_7E@ENS@@6BA@ANS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7E@ENS@@6BA@ANS@@@", ANS_A_fa_1);
|
||||
|
||||
vftSymbols.add("??_7E@ENS@@6BA1@A1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7E@ENS@@6BA1@A1NS@@@", ENS_E_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7E@ENS@@6BA2@A2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7E@ENS@@6BA2@A2NS@@@", ANS_A_fa2_1_thunkThisMinus4,
|
||||
A2NS_A2_fa2_2, A2NS_A2_fa2_3);
|
||||
|
||||
vftSymbols.add("??_7E@ENS@@6BB1@B1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7E@ENS@@6BB1@B1NS@@@", BNS_B_fb1_1_thunkThisPlus28,
|
||||
B1NS_B1_fb1_2, B1NS_B1_fb1_3);
|
||||
|
||||
vftSymbols.add("??_7E@ENS@@6BB2@B2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7E@ENS@@6BB2@B2NS@@@", BNS_B_fb2_1_thunkThisPlus28,
|
||||
B2NS_B2_fb2_2, B2NS_B2_fb2_3);
|
||||
|
||||
vftSymbols.add("??_7E@ENS@@6BB@BNS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7E@ENS@@6BB@BNS@@@", BNS_B_fb_1);
|
||||
|
||||
vftSymbols.add("??_7F@FNS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7F@FNS@@6B@", FNS_F_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7G@GNS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7G@GNS@@6B@", GNS_G_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7H@HNS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7H@HNS@@6B@", HNS_H_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7I@INS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7I@INS@@6B@", INS_I_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7J@JNS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7J@JNS@@6B@", JNS_J_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7K@KNS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7K@KNS@@6B@", KNS_K_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7L@LNS@@6B@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7L@LNS@@6B@", LNS_L_fa1_1, A1NS_A1_fa1_2,
|
||||
A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BA@ANS@@E@ENS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7N1@N1NS@@6B@", N1NS_N1_fn1_1, N1NS_N1_fn1_2);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BC@CNS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7N2@N2NS@@6B@", N2NS_N2_fn2_1, N2NS_N2_fn2_2);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BA@ANS@@D@DNS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BA@ANS@@E@ENS@@@", ANS_A_fa_1);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BB@BNS@@D@DNS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BC@CNS@@@", CNS_C_fc_1);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BA1@A1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BA@ANS@@D@DNS@@@", ANS_A_fa_1);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BA2@A2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BB@BNS@@D@DNS@@@", BNS_B_fb_1);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BB1@B1NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BN1@N1NS@@@", MNS_M_fn1_1, N1NS_N1_fn1_2);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BB2@B2NS@@@");
|
||||
preparer32.addAddresses(3, false);
|
||||
preparer64.addAddresses(3, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BA1@A1NS@@@", MNS_M_fa1_1,
|
||||
CNS_C_fa1_2_thunkThisMinus84, A1NS_A1_fa1_3);
|
||||
|
||||
vftSymbols.add("??_7M@MNS@@6BB@BNS@@E@ENS@@@");
|
||||
preparer32.addAddresses(1, false);
|
||||
preparer64.addAddresses(1, true);
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BA2@A2NS@@@", MNS_M_fa2_1, A2NS_A2_fa2_2,
|
||||
A2NS_A2_fa2_3);
|
||||
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BB1@B1NS@@@", MNS_M_fb1_1,
|
||||
CNS_C_fb1_2_thunkThisMinus84, B1NS_B1_fb1_3);
|
||||
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BB2@B2NS@@@", MNS_M_fb2_1, B2NS_B2_fb2_2,
|
||||
B2NS_B2_fb2_3);
|
||||
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BB@BNS@@E@ENS@@@", BNS_B_fb_1);
|
||||
|
||||
prepareVfts(preparer32, preparer64, "??_7M@MNS@@6BN2@N2NS@@@", N2NS_N2_fn2_1,
|
||||
N2NS_N2_fn2_2);
|
||||
|
||||
//==========================================================================================
|
||||
|
||||
|
@ -592,32 +725,79 @@ public class MsftVxtManagerTest extends AbstractGenericTest {
|
|||
memory32 = preparer32.getMemory();
|
||||
memory64 = preparer64.getMemory();
|
||||
|
||||
vxtAddresses32 = preparer32.getAddresses();
|
||||
vxtAddresses64 = preparer64.getAddresses();
|
||||
MyStubFunctionManager functionManager32 = new MyStubFunctionManager();
|
||||
MyStubFunctionManager functionManager64 = new MyStubFunctionManager();
|
||||
|
||||
program32 = new MyStubProgram(memory32, functionManager32);
|
||||
program64 = new MyStubProgram(memory64, functionManager64);
|
||||
|
||||
addresses32 = preparer32.getAddresses();
|
||||
addresses64 = preparer64.getAddresses();
|
||||
|
||||
addressByVxtMangledName32 = new HashMap<>();
|
||||
addressByVxtMangledName64 = new HashMap<>();
|
||||
|
||||
if (vbtSymbols.size() + vftSymbols.size() != vxtAddresses32.size() ||
|
||||
vbtSymbols.size() + vftSymbols.size() != vxtAddresses64.size()) {
|
||||
if (functions.size() + vbtSymbols.size() + 2 * vftSymbols.size() != addresses32.size() ||
|
||||
functions.size() + vbtSymbols.size() + 2 * vftSymbols.size() != addresses64.size()) {
|
||||
throw new AssertException("Fatal: list sizes do not match");
|
||||
}
|
||||
int aCount = 0;
|
||||
int accumulatedCount = 0;
|
||||
for (Function f : functions) {
|
||||
functionManager32.addFunction(addresses32.get(accumulatedCount), f);
|
||||
functionManager64.addFunction(addresses64.get(accumulatedCount), f);
|
||||
accumulatedCount++;
|
||||
}
|
||||
for (String vbtSymbol : vbtSymbols) {
|
||||
addressByVxtMangledName32.put(vbtSymbol, vxtAddresses32.get(aCount));
|
||||
addressByVxtMangledName64.put(vbtSymbol, vxtAddresses64.get(aCount));
|
||||
aCount++;
|
||||
addressByVxtMangledName32.put(vbtSymbol, addresses32.get(accumulatedCount));
|
||||
addressByVxtMangledName64.put(vbtSymbol, addresses64.get(accumulatedCount));
|
||||
accumulatedCount++;
|
||||
}
|
||||
for (String vftSymbol : vftSymbols) {
|
||||
addressByVxtMangledName32.put(vftSymbol, vxtAddresses32.get(aCount));
|
||||
addressByVxtMangledName64.put(vftSymbol, vxtAddresses64.get(aCount));
|
||||
aCount++;
|
||||
// skip an extra for each meta
|
||||
addressByVxtMangledName32.put(vftSymbol, addresses32.get(accumulatedCount + 1));
|
||||
addressByVxtMangledName64.put(vftSymbol, addresses64.get(accumulatedCount + 1));
|
||||
accumulatedCount += 2;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
//==============================================================================================
|
||||
|
||||
// No tests at this point because of need to rework the design
|
||||
// Not many tests at this point because of need to rework the design of finding tables
|
||||
// based on parentage (which is not the necessarily the same as nesting in the layout).
|
||||
|
||||
@Test
|
||||
public void testMVbt_temp() throws Exception {
|
||||
|
||||
ProgramVirtualBaseTable vbt;
|
||||
|
||||
vbt = (ProgramVirtualBaseTable) mVxtManager32.findVbt(M_ID, List.of(M_ID));
|
||||
assertEquals(addresses32.get(73), vbt.getAddress());
|
||||
// Not certain that this one is a valid query... depends on the design work that needs
|
||||
// to be done
|
||||
// vbt = (ProgramVirtualBaseTable) mVxtManager32.findVbt(mId, List.of(eId));
|
||||
// assertEquals(addresses32.get(73), vbt.getAddress());
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
@Test
|
||||
public void testMVft_temp() throws Exception {
|
||||
|
||||
ProgramVirtualFunctionTable vft;
|
||||
Address address;
|
||||
Function function;
|
||||
|
||||
// Test with and without parentage referencing owner type. We are treating them as the
|
||||
// same for now. If we can tease out more information or encounter difficulties, we
|
||||
// need to split these out accordingly (within the work of findVft (and findVbt)).
|
||||
vft = (ProgramVirtualFunctionTable) mVxtManager32.findVft(A_ID, List.of(A_ID));
|
||||
assertEquals(addresses32.get(80), vft.getAddress());
|
||||
address = vft.getAddress(0);
|
||||
function = program32.getFunctionManager().getFunctionAt(address);
|
||||
assertEquals(ANS_A_fa_1, function);
|
||||
function.getName().equals(ANS_A_fa_1.getName());
|
||||
vft = (ProgramVirtualFunctionTable) mVxtManager32.findVft(A_ID, List.of());
|
||||
assertEquals(addresses32.get(80), vft.getAddress());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,9 +27,12 @@ import ghidra.app.plugin.core.checksums.MyTestMemory;
|
|||
import ghidra.app.util.SymbolPath;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.app.util.pdb.classtype.*;
|
||||
import ghidra.program.model.StubFunctionManager;
|
||||
import ghidra.program.model.StubProgram;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressIterator;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.LittleEndianDataConverter;
|
||||
|
@ -54,6 +57,8 @@ public class CppCompositeTypeTest extends AbstractGenericTest {
|
|||
private static ClassTypeManager ctm64;
|
||||
private static Memory memory32;
|
||||
private static Memory memory64;
|
||||
private static Program program32;
|
||||
private static Program program64;
|
||||
private static Map<String, Address> addressByMangledName32;
|
||||
private static Map<String, Address> addressByMangledName64;
|
||||
private static DataType vftptr32;
|
||||
|
@ -180,8 +185,8 @@ public class CppCompositeTypeTest extends AbstractGenericTest {
|
|||
|
||||
createVbTables();
|
||||
|
||||
msftVxtManager32 = new MsftVxtManager(ctm32, memory32);
|
||||
msftVxtManager64 = new MsftVxtManager(ctm64, memory64);
|
||||
msftVxtManager32 = new MsftVxtManager(ctm32, program32);
|
||||
msftVxtManager64 = new MsftVxtManager(ctm64, program64);
|
||||
try {
|
||||
msftVxtManager32.createVirtualTables(CategoryPath.ROOT, addressByMangledName32, log,
|
||||
monitor);
|
||||
|
@ -268,6 +273,44 @@ public class CppCompositeTypeTest extends AbstractGenericTest {
|
|||
}
|
||||
}
|
||||
|
||||
private static class MyStubFunctionManager extends StubFunctionManager {
|
||||
|
||||
private Map<Address, Function> myFunctions;
|
||||
|
||||
private MyStubFunctionManager() {
|
||||
myFunctions = new HashMap<>();
|
||||
}
|
||||
|
||||
private void addFunction(Address address, Function function) {
|
||||
myFunctions.put(address, function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function getFunctionAt(Address entryPoint) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyStubProgram extends StubProgram {
|
||||
private Memory myMemory;
|
||||
private FunctionManager myFunctionManager;
|
||||
|
||||
private MyStubProgram(Memory mem, FunctionManager fm) {
|
||||
this.myMemory = mem;
|
||||
this.myFunctionManager = fm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionManager getFunctionManager() {
|
||||
return myFunctionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Memory getMemory() {
|
||||
return myMemory;
|
||||
}
|
||||
}
|
||||
|
||||
static void createVbTables() {
|
||||
MemoryPreparer preparer32 = new MemoryPreparer();
|
||||
MemoryPreparer preparer64 = new MemoryPreparer();
|
||||
|
@ -484,6 +527,12 @@ public class CppCompositeTypeTest extends AbstractGenericTest {
|
|||
memory32 = preparer32.getMemory();
|
||||
memory64 = preparer64.getMemory();
|
||||
|
||||
MyStubFunctionManager functionManager32 = new MyStubFunctionManager();
|
||||
MyStubFunctionManager functionManager64 = new MyStubFunctionManager();
|
||||
|
||||
program32 = new MyStubProgram(memory32, functionManager32);
|
||||
program64 = new MyStubProgram(memory64, functionManager64);
|
||||
|
||||
List<Address> addresses32 = preparer32.getAddresses();
|
||||
List<Address> addresses64 = preparer64.getAddresses();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue