mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-5505 Improved RecoverClassesFromRTTIScript abilty to use the LowCodeModeBit to find code references.
This commit is contained in:
parent
fa554361d5
commit
2f83e26c0e
3 changed files with 217 additions and 246 deletions
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -16,52 +16,21 @@
|
||||||
//DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS.
|
//DO NOT RUN. THIS IS NOT A SCRIPT! THIS IS A CLASS THAT IS USED BY SCRIPTS.
|
||||||
package classrecovery;
|
package classrecovery;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||||
import ghidra.app.plugin.core.analysis.ReferenceAddressPair;
|
import ghidra.app.plugin.core.analysis.ReferenceAddressPair;
|
||||||
import ghidra.app.util.PseudoDisassembler;
|
import ghidra.app.util.PseudoDisassembler;
|
||||||
import ghidra.program.flatapi.FlatProgramAPI;
|
import ghidra.program.flatapi.FlatProgramAPI;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
|
||||||
import ghidra.program.model.address.AddressSet;
|
|
||||||
import ghidra.program.model.address.AddressSetView;
|
|
||||||
import ghidra.program.model.block.CodeBlock;
|
import ghidra.program.model.block.CodeBlock;
|
||||||
import ghidra.program.model.block.IsolatedEntrySubModel;
|
import ghidra.program.model.block.IsolatedEntrySubModel;
|
||||||
import ghidra.program.model.data.CategoryPath;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.IBO32DataType;
|
|
||||||
import ghidra.program.model.data.LongDataType;
|
|
||||||
import ghidra.program.model.data.Pointer;
|
|
||||||
import ghidra.program.model.data.PointerDataType;
|
|
||||||
import ghidra.program.model.data.Structure;
|
|
||||||
import ghidra.program.model.data.Undefined4DataType;
|
|
||||||
import ghidra.program.model.data.Undefined8DataType;
|
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.listing.Instruction;
|
|
||||||
import ghidra.program.model.listing.InstructionIterator;
|
|
||||||
import ghidra.program.model.listing.Listing;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.model.mem.DumbMemBufferImpl;
|
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
|
||||||
import ghidra.program.model.mem.Memory;
|
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.program.model.symbol.FlowType;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.model.symbol.Namespace;
|
|
||||||
import ghidra.program.model.symbol.Reference;
|
|
||||||
import ghidra.program.model.symbol.ReferenceIterator;
|
|
||||||
import ghidra.program.model.symbol.SourceType;
|
|
||||||
import ghidra.program.model.symbol.Symbol;
|
|
||||||
import ghidra.program.model.symbol.SymbolIterator;
|
|
||||||
import ghidra.program.model.symbol.SymbolTable;
|
|
||||||
import ghidra.program.model.symbol.SymbolType;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
@ -133,6 +102,97 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to determine if the given address contains a possible function pointer
|
||||||
|
* @param program the given program
|
||||||
|
*
|
||||||
|
* @param address the given address
|
||||||
|
* @return true if the given address contains a possible function pointer or
|
||||||
|
* false otherwise
|
||||||
|
* @throws CancelledException if cancelled
|
||||||
|
*/
|
||||||
|
public boolean isPossibleFunctionPointer(Program program, Address address)
|
||||||
|
throws CancelledException {
|
||||||
|
|
||||||
|
Address referencedAddress = getPointer(address);
|
||||||
|
|
||||||
|
if (referencedAddress == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Address normalizedReferencedAddress =
|
||||||
|
PseudoDisassembler.getNormalizedDisassemblyAddress(program, referencedAddress);
|
||||||
|
|
||||||
|
if (normalizedReferencedAddress == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function function = getFunctionAt(normalizedReferencedAddress);
|
||||||
|
if (function != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressSetView executeSet = program.getMemory().getExecuteSet();
|
||||||
|
|
||||||
|
if (!executeSet.contains(normalizedReferencedAddress)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction instruction = getInstructionAt(normalizedReferencedAddress);
|
||||||
|
if (instruction != null) {
|
||||||
|
createFunction(normalizedReferencedAddress, null);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean disassemble = disassemble(normalizedReferencedAddress);
|
||||||
|
if (disassemble) {
|
||||||
|
|
||||||
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
|
// check for the case where there is conflicting data at the thumb offset function
|
||||||
|
// pointer and if so clear the data and redisassemble and remove the bad bookmark
|
||||||
|
// long originalLongValue = extendedFlatAPI.getLongValueAt(address);
|
||||||
|
if (!referencedAddress.equals(normalizedReferencedAddress)) {
|
||||||
|
|
||||||
|
Data dataAt = listing.getDataAt(referencedAddress);
|
||||||
|
if (dataAt != null && dataAt.isDefined()) {
|
||||||
|
clearListing(referencedAddress);
|
||||||
|
disassemble = disassemble(address);
|
||||||
|
|
||||||
|
Bookmark bookmark =
|
||||||
|
getBookmarkAt(program, normalizedReferencedAddress, BookmarkType.ERROR,
|
||||||
|
"Bad Instruction", "conflicting data");
|
||||||
|
if (bookmark != null) {
|
||||||
|
removeBookmark(bookmark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createFunction(normalizedReferencedAddress, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bookmark getBookmarkAt(Program program, Address address, String bookmarkType,
|
||||||
|
String category,
|
||||||
|
String commentContains) throws CancelledException {
|
||||||
|
|
||||||
|
Bookmark[] bookmarks = program.getBookmarkManager().getBookmarks(address);
|
||||||
|
|
||||||
|
for (Bookmark bookmark : bookmarks) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
if (bookmark.getType().getTypeString().equals(bookmarkType) &&
|
||||||
|
bookmark.getCategory().equals(category) &&
|
||||||
|
bookmark.getComment().contains(commentContains)) {
|
||||||
|
return bookmark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to check to see if there is a valid function pointer at the given address. If it is
|
* Method to check to see if there is a valid function pointer at the given address. If it is
|
||||||
* valid but not created, create it
|
* valid but not created, create it
|
||||||
|
@ -254,18 +314,16 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
if (referencesFrom.size() != 1) {
|
if (referencesFrom.size() != 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Address functionAddress = referencesFrom.get(0);
|
Address functionAddress = referencesFrom.get(0);
|
||||||
|
|
||||||
Register lowBitCodeMode = currentProgram.getRegister("LowBitCodeMode");
|
Register lowBitCodeMode = currentProgram.getRegister("LowBitCodeMode");
|
||||||
if(lowBitCodeMode != null) {
|
if (lowBitCodeMode != null) {
|
||||||
long longValue = functionAddress.getOffset();
|
long longValue = functionAddress.getOffset();
|
||||||
longValue = longValue & ~0x1;
|
longValue = longValue & ~0x1;
|
||||||
functionAddress = functionAddress.getNewAddress(longValue);
|
functionAddress = functionAddress.getNewAddress(longValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function function = getFunctionAt(functionAddress);
|
Function function = getFunctionAt(functionAddress);
|
||||||
if (function == null) {
|
if (function == null) {
|
||||||
// try to create function
|
// try to create function
|
||||||
|
@ -581,7 +639,6 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
return subroutineAddresses;
|
return subroutineAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to get a list of symbols either matching exactly (if exact flag is true) or containing (if exact flag is false) the given symbol name
|
* Method to get a list of symbols either matching exactly (if exact flag is true) or containing (if exact flag is false) the given symbol name
|
||||||
* @param addressSet the address set to find matching symbols in
|
* @param addressSet the address set to find matching symbols in
|
||||||
|
@ -641,7 +698,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
if (addressSize == 32) {
|
if (addressSize == 32) {
|
||||||
long offset32 = getInt(address);
|
long offset32 = getInt(address);
|
||||||
Address newAddr = address.getNewAddress(offset32);
|
Address newAddr = address.getNewAddress(offset32);
|
||||||
if(currentProgram.getMemory().contains(newAddr)) {
|
if (currentProgram.getMemory().contains(newAddr)) {
|
||||||
return newAddr;
|
return newAddr;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -651,7 +708,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
|
|
||||||
long offset64 = getLong(address);
|
long offset64 = getLong(address);
|
||||||
Address newAddr = address.getNewAddress(offset64);
|
Address newAddr = address.getNewAddress(offset64);
|
||||||
if(currentProgram.getMemory().contains(newAddr)) {
|
if (currentProgram.getMemory().contains(newAddr)) {
|
||||||
return newAddr;
|
return newAddr;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -666,11 +723,11 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLongValueAt(Address address) {
|
public long getLongValueAt(Address address) {
|
||||||
|
|
||||||
MemBuffer buf = new DumbMemBufferImpl(currentProgram.getMemory(), address);
|
MemBuffer buf = new DumbMemBufferImpl(currentProgram.getMemory(), address);
|
||||||
|
|
||||||
LongDataType longDT = new LongDataType();
|
LongDataType longDT = new LongDataType();
|
||||||
|
|
||||||
Scalar value =
|
Scalar value =
|
||||||
|
@ -856,7 +913,6 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to retrieve a single referenced address from the given address
|
* Method to retrieve a single referenced address from the given address
|
||||||
* @param address the given address to look for a single referenced address
|
* @param address the given address to look for a single referenced address
|
||||||
|
@ -1363,5 +1419,4 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import ghidra.app.cmd.label.DemanglerCmd;
|
import ghidra.app.cmd.label.DemanglerCmd;
|
||||||
import ghidra.app.plugin.core.analysis.ReferenceAddressPair;
|
import ghidra.app.plugin.core.analysis.ReferenceAddressPair;
|
||||||
import ghidra.app.util.NamespaceUtils;
|
import ghidra.app.util.NamespaceUtils;
|
||||||
|
import ghidra.app.util.PseudoDisassembler;
|
||||||
import ghidra.app.util.demangler.DemangledObject;
|
import ghidra.app.util.demangler.DemangledObject;
|
||||||
import ghidra.app.util.demangler.DemanglerUtil;
|
import ghidra.app.util.demangler.DemanglerUtil;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
|
@ -31,7 +32,6 @@ import ghidra.program.flatapi.FlatProgramAPI;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
import ghidra.program.model.lang.Register;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
@ -4395,68 +4395,59 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||||
*/
|
*/
|
||||||
private boolean isPossibleFunctionPointer(Address address) throws CancelledException {
|
private boolean isPossibleFunctionPointer(Address address) throws CancelledException {
|
||||||
|
|
||||||
// TODO: make one that works for all casea in helper
|
Address referencedAddress = extendedFlatAPI.getSingleReferencedAddress(address);
|
||||||
|
if (referencedAddress == null) {
|
||||||
long longValue = extendedFlatAPI.getLongValueAt(address);
|
|
||||||
|
|
||||||
Register lowBitCodeMode = program.getRegister("LowBitCodeMode");
|
|
||||||
if (lowBitCodeMode != null) {
|
|
||||||
longValue = longValue & ~0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Address possibleFunctionPointer = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
possibleFunctionPointer = address.getNewAddress(longValue);
|
|
||||||
}
|
|
||||||
catch (AddressOutOfBoundsException e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (possibleFunctionPointer == null) {
|
Address normalizedReferencedAddress =
|
||||||
|
PseudoDisassembler.getNormalizedDisassemblyAddress(program, referencedAddress);
|
||||||
|
|
||||||
|
if (normalizedReferencedAddress == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Function function = api.getFunctionAt(possibleFunctionPointer);
|
Function function = api.getFunctionAt(normalizedReferencedAddress);
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressSetView executeSet = program.getMemory().getExecuteSet();
|
AddressSetView executeSet = program.getMemory().getExecuteSet();
|
||||||
|
|
||||||
if (!executeSet.contains(possibleFunctionPointer)) {
|
if (!executeSet.contains(normalizedReferencedAddress)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction instruction = api.getInstructionAt(possibleFunctionPointer);
|
Instruction instruction = api.getInstructionAt(normalizedReferencedAddress);
|
||||||
if (instruction != null) {
|
if (instruction != null) {
|
||||||
api.createFunction(possibleFunctionPointer, null);
|
api.createFunction(normalizedReferencedAddress, null);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean disassemble = api.disassemble(possibleFunctionPointer);
|
boolean disassemble = api.disassemble(normalizedReferencedAddress);
|
||||||
if (disassemble) {
|
if (disassemble) {
|
||||||
|
|
||||||
// check for the case where there is conflicting data at the thumb offset function
|
// check for the case where there is conflicting data at the thumb offset function
|
||||||
// pointer and if so clear the data and redisassemble and remove the bad bookmark
|
// pointer and if so clear the data and redisassemble and remove the bad bookmark
|
||||||
long originalLongValue = extendedFlatAPI.getLongValueAt(address);
|
// long originalLongValue = extendedFlatAPI.getLongValueAt(address);
|
||||||
if (originalLongValue != longValue) {
|
if (!referencedAddress.equals(normalizedReferencedAddress)) {
|
||||||
Address offsetPointer = address.getNewAddress(originalLongValue);
|
|
||||||
Data dataAt = listing.getDataAt(offsetPointer);
|
Data dataAt = listing.getDataAt(referencedAddress);
|
||||||
if (dataAt != null && dataAt.isDefined()) {
|
if (dataAt != null && dataAt.isDefined()) {
|
||||||
api.clearListing(offsetPointer);
|
api.clearListing(referencedAddress);
|
||||||
disassemble = api.disassemble(address);
|
disassemble = api.disassemble(address);
|
||||||
|
|
||||||
Bookmark bookmark = getBookmarkAt(possibleFunctionPointer, BookmarkType.ERROR,
|
Bookmark bookmark =
|
||||||
"Bad Instruction", "conflicting data");
|
getBookmarkAt(normalizedReferencedAddress, BookmarkType.ERROR,
|
||||||
|
"Bad Instruction", "conflicting data");
|
||||||
if (bookmark != null) {
|
if (bookmark != null) {
|
||||||
api.removeBookmark(bookmark);
|
api.removeBookmark(bookmark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.createFunction(possibleFunctionPointer, null);
|
api.createFunction(normalizedReferencedAddress, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -20,7 +20,6 @@ import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.Register;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -64,9 +63,8 @@ public class Vtable {
|
||||||
DataTypeManager dataTypeManager;
|
DataTypeManager dataTypeManager;
|
||||||
Listing listing;
|
Listing listing;
|
||||||
|
|
||||||
|
public Vtable(Program program, Address vtableAddress, GccTypeinfoRef typeinfoRef,
|
||||||
|
boolean isSpecial, boolean inExternalMemory,
|
||||||
public Vtable(Program program, Address vtableAddress, GccTypeinfoRef typeinfoRef, boolean isSpecial, boolean inExternalMemory,
|
|
||||||
Vtable primaryVtable, Boolean isConstruction, TaskMonitor monitor)
|
Vtable primaryVtable, Boolean isConstruction, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
|
@ -92,21 +90,24 @@ public class Vtable {
|
||||||
functionManager = program.getFunctionManager();
|
functionManager = program.getFunctionManager();
|
||||||
dataTypeManager = program.getDataTypeManager();
|
dataTypeManager = program.getDataTypeManager();
|
||||||
listing = program.getListing();
|
listing = program.getListing();
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vtable(Program program, Address vtableAddress, GccTypeinfoRef typeinfoRef, boolean isSpecial, boolean inExternalMemory, TaskMonitor monitor)
|
public Vtable(Program program, Address vtableAddress, GccTypeinfoRef typeinfoRef,
|
||||||
|
boolean isSpecial, boolean inExternalMemory, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
this(program, vtableAddress, typeinfoRef, isSpecial, inExternalMemory, null, null, monitor);
|
this(program, vtableAddress, typeinfoRef, isSpecial, inExternalMemory, null, null, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vtable(Program program, Address vtableAddress, GccTypeinfoRef typeinfoRef, boolean isSpecial, boolean inExternalMemory, boolean isConstruction,
|
public Vtable(Program program, Address vtableAddress, GccTypeinfoRef typeinfoRef,
|
||||||
|
boolean isSpecial, boolean inExternalMemory, boolean isConstruction,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
this(program, vtableAddress, typeinfoRef, isSpecial, inExternalMemory, null, isConstruction, monitor);
|
this(program, vtableAddress, typeinfoRef, isSpecial, inExternalMemory, null, isConstruction,
|
||||||
|
monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setup() throws CancelledException {
|
protected void setup() throws CancelledException {
|
||||||
|
|
||||||
checkValidTop();
|
checkValidTop();
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ public class Vtable {
|
||||||
}
|
}
|
||||||
|
|
||||||
figureOutNamespace();
|
figureOutNamespace();
|
||||||
|
|
||||||
setHasVfunctions();
|
setHasVfunctions();
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
|
@ -143,10 +144,11 @@ public class Vtable {
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
applyVtableData();
|
applyVtableData();
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,16 +198,15 @@ public class Vtable {
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Address getTypeinfoRefAddress() {
|
public Address getTypeinfoRefAddress() {
|
||||||
return typeinfoRef.getAddress();
|
return typeinfoRef.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GccTypeinfo getReferencedTypeinfo() {
|
public GccTypeinfo getReferencedTypeinfo() {
|
||||||
return (GccTypeinfo) typeinfoRef.getReferencedTypeinfo();
|
return (GccTypeinfo) typeinfoRef.getReferencedTypeinfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setTypeinfoAddress() {
|
protected void setTypeinfoAddress() {
|
||||||
|
|
||||||
typeinfoAddress = typeinfo.getAddress();
|
typeinfoAddress = typeinfo.getAddress();
|
||||||
typeinfoNamespace = typeinfo.getNamespace();
|
typeinfoNamespace = typeinfo.getNamespace();
|
||||||
|
@ -221,13 +222,14 @@ public class Vtable {
|
||||||
try {
|
try {
|
||||||
Address topOffset = typeinfoRefAddress.subtract(defaultPointerSize);
|
Address topOffset = typeinfoRefAddress.subtract(defaultPointerSize);
|
||||||
if (topOffset.getOffset() < vtableAddress.getOffset()) {
|
if (topOffset.getOffset() < vtableAddress.getOffset()) {
|
||||||
Msg.debug(this,"No offset field in vtable at " + vtableAddress.toString());
|
Msg.debug(this, "No offset field in vtable at " + vtableAddress.toString());
|
||||||
isValid = false;
|
isValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
topOffsetValue = extendedFlatAPI.getLongValueAt(topOffset);
|
topOffsetValue = extendedFlatAPI.getLongValueAt(topOffset);
|
||||||
} catch (IllegalArgumentException e) {
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
Msg.debug(this, "Invalid vtable: " + vtableAddress.toString() + " No offset field");
|
Msg.debug(this, "Invalid vtable: " + vtableAddress.toString() + " No offset field");
|
||||||
isValid = false;
|
isValid = false;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +254,8 @@ public class Vtable {
|
||||||
// otherwise, use the topOffsetValue to figure it out
|
// otherwise, use the topOffsetValue to figure it out
|
||||||
if (topOffsetValue == 0L) {
|
if (topOffsetValue == 0L) {
|
||||||
isPrimary = true;
|
isPrimary = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
isPrimary = false;
|
isPrimary = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,15 +292,17 @@ public class Vtable {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Address possVfunctionTop = typeinfoRefAddress.add(defaultPointerSize);
|
Address possVfunctionTop = typeinfoRefAddress.add(defaultPointerSize);
|
||||||
|
|
||||||
numVfunctions = getNumFunctionPointers(possVfunctionTop, true, false);
|
numVfunctions = getNumFunctionPointers(possVfunctionTop, true, false);
|
||||||
if (numVfunctions == 0) {
|
if (numVfunctions == 0) {
|
||||||
hasVfunctions = false;
|
hasVfunctions = false;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
hasVfunctions = true;
|
hasVfunctions = true;
|
||||||
vfunctionTop = possVfunctionTop;
|
vfunctionTop = possVfunctionTop;
|
||||||
}
|
}
|
||||||
} catch (AddressOutOfBoundsException e) {
|
}
|
||||||
|
catch (AddressOutOfBoundsException e) {
|
||||||
hasVfunctions = false;
|
hasVfunctions = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,17 +313,19 @@ public class Vtable {
|
||||||
|
|
||||||
int numFunctionPointers = 0;
|
int numFunctionPointers = 0;
|
||||||
Address address = topAddress;
|
Address address = topAddress;
|
||||||
|
|
||||||
// if it has a primary non-default symbol and it isn't "vftable" then it isn't a vftable
|
// if it has a primary non-default symbol and it isn't "vftable" then it isn't a vftable
|
||||||
Symbol primarySymbol = symbolTable.getPrimarySymbol(topAddress);
|
Symbol primarySymbol = symbolTable.getPrimarySymbol(topAddress);
|
||||||
if(primarySymbol != null && primarySymbol.getSource() != SourceType.DEFAULT && !primarySymbol.getName().contains("vftable")) {
|
if (primarySymbol != null && primarySymbol.getSource() != SourceType.DEFAULT &&
|
||||||
|
!primarySymbol.getName().contains("vftable")) {
|
||||||
return numFunctionPointers;
|
return numFunctionPointers;
|
||||||
}
|
}
|
||||||
MemoryBlock currentBlock = program.getMemory().getBlock(topAddress);
|
MemoryBlock currentBlock = program.getMemory().getBlock(topAddress);
|
||||||
|
|
||||||
boolean stillInCurrentTable = true;
|
boolean stillInCurrentTable = true;
|
||||||
while (address != null && currentBlock.contains(address) && stillInCurrentTable
|
while (address != null && currentBlock.contains(address) && stillInCurrentTable &&
|
||||||
&& (isPossibleFunctionPointer(address) || (allowNullFunctionPtrs && isPossibleNullPointer(address)))) {
|
(extendedFlatAPI.isPossibleFunctionPointer(program, address) ||
|
||||||
|
(allowNullFunctionPtrs && isPossibleNullPointer(address)))) {
|
||||||
|
|
||||||
numFunctionPointers++;
|
numFunctionPointers++;
|
||||||
address = address.add(defaultPointerSize);
|
address = address.add(defaultPointerSize);
|
||||||
|
@ -336,33 +343,34 @@ public class Vtable {
|
||||||
stillInCurrentTable = false;
|
stillInCurrentTable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//NEW: TESTING Don't allow single null pointer at top of vftable
|
//NEW: TESTING Don't allow single null pointer at top of vftable
|
||||||
//OR test to see if nulls then typeinfo ptr
|
//OR test to see if nulls then typeinfo ptr
|
||||||
// if(isPossibleNullPointer(topAddress) && numFunctionPointers == 1) {
|
// if(isPossibleNullPointer(topAddress) && numFunctionPointers == 1) {
|
||||||
// return 0;
|
// return 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// check to see if last is null ptr and next addr after that is typeinfo ref - indicating the null is really top of next vtable
|
// check to see if last is null ptr and next addr after that is typeinfo ref - indicating the null is really top of next vtable
|
||||||
Address lastAddress = topAddress.add((numFunctionPointers-1)*defaultPointerSize);
|
Address lastAddress = topAddress.add((numFunctionPointers - 1) * defaultPointerSize);
|
||||||
if(isPossibleNullPointer(lastAddress) && (isTypeinfoRef(lastAddress.add(defaultPointerSize)))){
|
if (isPossibleNullPointer(lastAddress) &&
|
||||||
|
(isTypeinfoRef(lastAddress.add(defaultPointerSize)))) {
|
||||||
numFunctionPointers--;
|
numFunctionPointers--;
|
||||||
}
|
}
|
||||||
return numFunctionPointers;
|
return numFunctionPointers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTypeinfoRef(Address addr) {
|
private boolean isTypeinfoRef(Address addr) {
|
||||||
|
|
||||||
Address referencedAddress = getReferencedAddress(addr);
|
Address referencedAddress = getReferencedAddress(addr);
|
||||||
if(referencedAddress == null) {
|
if (referencedAddress == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Data data = program.getListing().getDataAt(referencedAddress);
|
Data data = program.getListing().getDataAt(referencedAddress);
|
||||||
if(data == null) {
|
if (data == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.getBaseDataType().getName().contains("ClassTypeInfoStructure")) {
|
if (data.getBaseDataType().getName().contains("ClassTypeInfoStructure")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -382,97 +390,6 @@ public class Vtable {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to determine if the given address contains a possible function pointer
|
|
||||||
*
|
|
||||||
* @param address the given address
|
|
||||||
* @return true if the given address contains a possible function pointer or
|
|
||||||
* false otherwise
|
|
||||||
* @throws CancelledException if cancelled
|
|
||||||
*/
|
|
||||||
private boolean isPossibleFunctionPointer(Address address) throws CancelledException {
|
|
||||||
|
|
||||||
long longValue = extendedFlatAPI.getLongValueAt(address);
|
|
||||||
|
|
||||||
Register lowBitCodeMode = program.getRegister("LowBitCodeMode");
|
|
||||||
if (lowBitCodeMode != null) {
|
|
||||||
longValue = longValue & ~0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Address possibleFunctionPointer = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
possibleFunctionPointer = address.getNewAddress(longValue);
|
|
||||||
} catch (AddressOutOfBoundsException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (possibleFunctionPointer == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Function function = extendedFlatAPI.getFunctionAt(possibleFunctionPointer);
|
|
||||||
if (function != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressSetView executeSet = program.getMemory().getExecuteSet();
|
|
||||||
|
|
||||||
if (!executeSet.contains(possibleFunctionPointer)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction instruction = extendedFlatAPI.getInstructionAt(possibleFunctionPointer);
|
|
||||||
if (instruction != null) {
|
|
||||||
extendedFlatAPI.createFunction(possibleFunctionPointer, null);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean disassemble = extendedFlatAPI.disassemble(possibleFunctionPointer);
|
|
||||||
if (disassemble) {
|
|
||||||
|
|
||||||
// check for the case where there is conflicting data at the thumb offset
|
|
||||||
// function
|
|
||||||
// pointer and if so clear the data and redisassemble and remove the bad
|
|
||||||
// bookmark
|
|
||||||
long originalLongValue = extendedFlatAPI.getLongValueAt(address);
|
|
||||||
if (originalLongValue != longValue) {
|
|
||||||
Address offsetPointer = address.getNewAddress(originalLongValue);
|
|
||||||
if (extendedFlatAPI.getDataAt(offsetPointer) != null) {
|
|
||||||
extendedFlatAPI.clearListing(offsetPointer);
|
|
||||||
disassemble = extendedFlatAPI.disassemble(address);
|
|
||||||
|
|
||||||
Bookmark bookmark = getBookmarkAt(possibleFunctionPointer, BookmarkType.ERROR, "Bad Instruction",
|
|
||||||
"conflicting data");
|
|
||||||
if (bookmark != null) {
|
|
||||||
extendedFlatAPI.removeBookmark(bookmark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extendedFlatAPI.createFunction(possibleFunctionPointer, null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bookmark getBookmarkAt(Address address, String bookmarkType, String category, String commentContains)
|
|
||||||
throws CancelledException {
|
|
||||||
|
|
||||||
Bookmark[] bookmarks = program.getBookmarkManager().getBookmarks(address);
|
|
||||||
|
|
||||||
for (Bookmark bookmark : bookmarks) {
|
|
||||||
monitor.checkCancelled();
|
|
||||||
|
|
||||||
if (bookmark.getType().getTypeString().equals(bookmarkType) && bookmark.getCategory().equals(category)
|
|
||||||
&& bookmark.getComment().contains(commentContains)) {
|
|
||||||
return bookmark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHasVfunctions(boolean flag) {
|
public void setHasVfunctions(boolean flag) {
|
||||||
hasVfunctions = flag;
|
hasVfunctions = flag;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +409,8 @@ public class Vtable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!hasVfunctions) {
|
if (!hasVfunctions) {
|
||||||
length = (int) (typeinfoRefAddress.getOffset() + defaultPointerSize - vtableAddress.getOffset());
|
length = (int) (typeinfoRefAddress.getOffset() + defaultPointerSize -
|
||||||
|
vtableAddress.getOffset());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +457,7 @@ public class Vtable {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean keepChecking = true;
|
boolean keepChecking = true;
|
||||||
|
|
||||||
int limit = length;
|
int limit = length;
|
||||||
|
|
||||||
while (keepChecking) {
|
while (keepChecking) {
|
||||||
|
@ -547,20 +465,22 @@ public class Vtable {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
|
|
||||||
Address nextAddr = vtableAddress.add(length);
|
Address nextAddr = vtableAddress.add(length);
|
||||||
|
|
||||||
|
|
||||||
Address typeinfoAddr = typeinfo.getAddress();
|
Address typeinfoAddr = typeinfo.getAddress();
|
||||||
|
|
||||||
int alignment = nextAddr.getSize()/8;
|
int alignment = nextAddr.getSize() / 8;
|
||||||
Address nextTypeinfoRefAddr = getNextReferenceTo(nextAddr, typeinfoAddr, alignment, limit);
|
Address nextTypeinfoRefAddr =
|
||||||
if(nextTypeinfoRefAddr == null) {
|
getNextReferenceTo(nextAddr, typeinfoAddr, alignment, limit);
|
||||||
|
if (nextTypeinfoRefAddr == null) {
|
||||||
keepChecking = false;
|
keepChecking = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GccTypeinfoRef internalTypenfoRef = new GccTypeinfoRef(nextTypeinfoRefAddr, typeinfo, true);
|
|
||||||
|
|
||||||
Vtable possibleInternalVtable = new Vtable(program, nextAddr,internalTypenfoRef, isSpecial, inExternalMemory,
|
GccTypeinfoRef internalTypenfoRef =
|
||||||
|
new GccTypeinfoRef(nextTypeinfoRefAddr, typeinfo, true);
|
||||||
|
|
||||||
|
Vtable possibleInternalVtable =
|
||||||
|
new Vtable(program, nextAddr, internalTypenfoRef, isSpecial, inExternalMemory,
|
||||||
this, isConstruction, monitor);
|
this, isConstruction, monitor);
|
||||||
if (!possibleInternalVtable.isValid()) {
|
if (!possibleInternalVtable.isValid()) {
|
||||||
keepChecking = false;
|
keepChecking = false;
|
||||||
|
@ -575,20 +495,22 @@ public class Vtable {
|
||||||
Namespace internalVtableNamespace = possibleInternalVtable.getNamespace();
|
Namespace internalVtableNamespace = possibleInternalVtable.getNamespace();
|
||||||
if (internalVtableNamespace != null && internalVtableNamespace.equals(classNamespace)) {
|
if (internalVtableNamespace != null && internalVtableNamespace.equals(classNamespace)) {
|
||||||
addInternalVtable(possibleInternalVtable);
|
addInternalVtable(possibleInternalVtable);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
keepChecking = false;
|
keepChecking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address getNextReferenceTo(Address startAddress, Address refdAddress, int alignment, int limit) {
|
private Address getNextReferenceTo(Address startAddress, Address refdAddress, int alignment,
|
||||||
|
int limit) {
|
||||||
|
|
||||||
int offset = alignment;
|
int offset = alignment;
|
||||||
while(offset < limit) {
|
while (offset < limit) {
|
||||||
Address addr = startAddress.add(offset);
|
Address addr = startAddress.add(offset);
|
||||||
Address referencedAddress = getReferencedAddress(addr);
|
Address referencedAddress = getReferencedAddress(addr);
|
||||||
if(referencedAddress != null && referencedAddress.equals(refdAddress)) {
|
if (referencedAddress != null && referencedAddress.equals(refdAddress)) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
offset += alignment;
|
offset += alignment;
|
||||||
|
@ -604,7 +526,7 @@ public class Vtable {
|
||||||
public List<Vtable> getInternalVtables() {
|
public List<Vtable> getInternalVtables() {
|
||||||
return internalVtables;
|
return internalVtables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIsConstructionVtable(Boolean setting) {
|
public void setIsConstructionVtable(Boolean setting) {
|
||||||
isConstruction = setting;
|
isConstruction = setting;
|
||||||
}
|
}
|
||||||
|
@ -614,8 +536,8 @@ public class Vtable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void figureOutNamespace() {
|
private void figureOutNamespace() {
|
||||||
|
|
||||||
if(isConstruction == null) {
|
if (isConstruction == null) {
|
||||||
setNamespace(globalNamespace);
|
setNamespace(globalNamespace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -635,7 +557,8 @@ public class Vtable {
|
||||||
// if not primary and the primary has same namespace then it is an internal
|
// if not primary and the primary has same namespace then it is an internal
|
||||||
// vtable and can
|
// vtable and can
|
||||||
// set the namespace to the typeinfo namespace
|
// set the namespace to the typeinfo namespace
|
||||||
if (!primaryVtable.getNamespace().isGlobal() && primaryVtable.getNamespace().equals(typeinfoNamespace)) {
|
if (!primaryVtable.getNamespace().isGlobal() &&
|
||||||
|
primaryVtable.getNamespace().equals(typeinfoNamespace)) {
|
||||||
setNamespace(typeinfoNamespace);
|
setNamespace(typeinfoNamespace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -647,7 +570,7 @@ public class Vtable {
|
||||||
public void setNamespace(Namespace namespace) {
|
public void setNamespace(Namespace namespace) {
|
||||||
|
|
||||||
classNamespace = namespace;
|
classNamespace = namespace;
|
||||||
for(Vtable internalVtable : internalVtables) {
|
for (Vtable internalVtable : internalVtables) {
|
||||||
internalVtable.setNamespace(namespace);
|
internalVtable.setNamespace(namespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +580,7 @@ public class Vtable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean applyVtableData() throws CancelledException, Exception {
|
protected boolean applyVtableData() throws CancelledException, Exception {
|
||||||
|
|
||||||
Data dataAt = listing.getDataAt(vtableAddress);
|
Data dataAt = listing.getDataAt(vtableAddress);
|
||||||
|
|
||||||
// first check to see it is an erroneous vtable that has been made a byte array
|
// first check to see it is an erroneous vtable that has been made a byte array
|
||||||
|
@ -699,15 +622,16 @@ public class Vtable {
|
||||||
throws AddressOutOfBoundsException {
|
throws AddressOutOfBoundsException {
|
||||||
|
|
||||||
listing.clearCodeUnits(vftableAddress,
|
listing.clearCodeUnits(vftableAddress,
|
||||||
vftableAddress.add((numFunctionPointers * defaultPointerSize - 1)), false);
|
vftableAddress.add((numFunctionPointers * defaultPointerSize - 1)), false);
|
||||||
|
|
||||||
DataType pointerDataType = dataTypeManager.getPointer(null);
|
DataType pointerDataType = dataTypeManager.getPointer(null);
|
||||||
ArrayDataType vftableArrayDataType = new ArrayDataType(pointerDataType, numFunctionPointers,
|
ArrayDataType vftableArrayDataType = new ArrayDataType(pointerDataType, numFunctionPointers,
|
||||||
defaultPointerSize);
|
defaultPointerSize);
|
||||||
try {
|
try {
|
||||||
Data vftableArrayData = listing.createData(vftableAddress, vftableArrayDataType);
|
Data vftableArrayData = listing.createData(vftableAddress, vftableArrayDataType);
|
||||||
return vftableArrayData;
|
return vftableArrayData;
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,21 +649,21 @@ public class Vtable {
|
||||||
private void createLongs(Address start, Address end) throws CancelledException, Exception {
|
private void createLongs(Address start, Address end) throws CancelledException, Exception {
|
||||||
|
|
||||||
DataType longDT = new LongDataType(dataTypeManager);
|
DataType longDT = new LongDataType(dataTypeManager);
|
||||||
if (defaultPointerSize == 8) {
|
if (defaultPointerSize == 8) {
|
||||||
longDT = new LongLongDataType();
|
longDT = new LongLongDataType();
|
||||||
}
|
}
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
Address address = start;
|
Address address = start;
|
||||||
while (address != null && !address.equals(end)) {
|
while (address != null && !address.equals(end)) {
|
||||||
|
|
||||||
listing.clearCodeUnits(address, address.add(defaultPointerSize - 1),false);
|
listing.clearCodeUnits(address, address.add(defaultPointerSize - 1), false);
|
||||||
listing.createData(address, longDT);
|
listing.createData(address, longDT);
|
||||||
offset += defaultPointerSize;
|
offset += defaultPointerSize;
|
||||||
address = getAddress(start, offset);
|
address = getAddress(start, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to get address at address + offset
|
* Method to get address at address + offset
|
||||||
*
|
*
|
||||||
|
@ -751,21 +675,22 @@ public class Vtable {
|
||||||
try {
|
try {
|
||||||
Address newAddress = address.add(offset);
|
Address newAddress = address.add(offset);
|
||||||
return newAddress;
|
return newAddress;
|
||||||
} catch (AddressOutOfBoundsException e) {
|
}
|
||||||
|
catch (AddressOutOfBoundsException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address getReferencedAddress(Address address) {
|
private Address getReferencedAddress(Address address) {
|
||||||
|
|
||||||
int addressSize = address.getSize();
|
int addressSize = address.getSize();
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (addressSize == 32) {
|
if (addressSize == 32) {
|
||||||
long offset32 = memory.getInt(address);
|
long offset32 = memory.getInt(address);
|
||||||
Address newAddr = address.getNewAddress(offset32);
|
Address newAddr = address.getNewAddress(offset32);
|
||||||
if(memory.contains(newAddr)) {
|
if (memory.contains(newAddr)) {
|
||||||
return newAddr;
|
return newAddr;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -775,7 +700,7 @@ public class Vtable {
|
||||||
|
|
||||||
long offset64 = memory.getLong(address);
|
long offset64 = memory.getLong(address);
|
||||||
Address newAddr = address.getNewAddress(offset64);
|
Address newAddr = address.getNewAddress(offset64);
|
||||||
if(memory.contains(newAddr)) {
|
if (memory.contains(newAddr)) {
|
||||||
return newAddr;
|
return newAddr;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue