mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Merge remote-tracking branch 'origin/GP-1053_DecompilerConversion' into patch
This commit is contained in:
commit
2143c4961d
35 changed files with 2430 additions and 281 deletions
|
@ -16,6 +16,8 @@
|
|||
package ghidra.program.database.symbol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.program.database.DBObjectCache;
|
||||
|
@ -73,15 +75,18 @@ public class EquateDB extends DatabaseObject implements Equate {
|
|||
try {
|
||||
Instruction instr = equateMgr.getProgram().getCodeManager().getInstructionAt(refAddr);
|
||||
long dynamicHash;
|
||||
if (instr == null)
|
||||
if (instr == null) {
|
||||
dynamicHash = 0;
|
||||
}
|
||||
else {
|
||||
long value = record.getLongValue(EquateDBAdapter.VALUE_COL);
|
||||
long hashArray[] = DynamicHash.calcConstantHash(instr, value);
|
||||
if (hashArray.length != 1)
|
||||
dynamicHash = 0;
|
||||
else
|
||||
dynamicHash = hashArray[0];
|
||||
long hashArray[] = DynamicHash.calcConstantHash(instr, value);
|
||||
if (hashArray.length != 1) {
|
||||
dynamicHash = 0;
|
||||
}
|
||||
else {
|
||||
dynamicHash = hashArray[0];
|
||||
}
|
||||
}
|
||||
equateMgr.addReference(key, refAddr, (short) opIndex, dynamicHash);
|
||||
}
|
||||
|
@ -112,9 +117,11 @@ public class EquateDB extends DatabaseObject implements Equate {
|
|||
}
|
||||
long value = record.getLongValue(EquateDBAdapter.VALUE_COL);
|
||||
long checkHash[] = DynamicHash.calcConstantHash(instr, value);
|
||||
for (long element : checkHash)
|
||||
if (element == dynamicHash)
|
||||
for (long element : checkHash) {
|
||||
if (element == dynamicHash) {
|
||||
return findScalarOpIndex(instr);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -201,6 +208,27 @@ public class EquateDB extends DatabaseObject implements Equate {
|
|||
return new EquateReference[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Equate#getReferences(Address)
|
||||
*/
|
||||
@Override
|
||||
public List<EquateReference> getReferences(Address refAddr) {
|
||||
Lock lock = equateMgr.getLock();
|
||||
lock.acquire();
|
||||
try {
|
||||
if (checkIsValid()) {
|
||||
return equateMgr.getReferences(key, refAddr);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
equateMgr.getProgram().dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Equate#getValue()
|
||||
*/
|
||||
|
|
|
@ -24,8 +24,7 @@ import ghidra.program.database.*;
|
|||
import ghidra.program.database.map.AddressKeyAddressIterator;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.symbol.Equate;
|
||||
import ghidra.program.model.symbol.EquateTable;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ChangeManager;
|
||||
import ghidra.program.util.EquateInfo;
|
||||
import ghidra.util.Lock;
|
||||
|
@ -328,11 +327,10 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
|||
list.add(ref);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
for (EquateRefDB ref : list) {
|
||||
if (monitor.isCancelled()) {
|
||||
throw new CancelledException();
|
||||
}
|
||||
EquateRefDB ref = list.get(i);
|
||||
EquateDB equateDB = getEquateDB(ref.getEquateID());
|
||||
|
||||
removeRef(equateDB, ref);
|
||||
|
@ -454,6 +452,22 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
|||
return getReferences(equateID).length;
|
||||
}
|
||||
|
||||
List<EquateReference> getReferences(long equateID, Address reference) throws IOException {
|
||||
List<EquateReference> refs = new ArrayList<>();
|
||||
long refAddr = addrMap.getKey(reference, false);
|
||||
if (refAddr == AddressMap.INVALID_ADDRESS_KEY) {
|
||||
return refs;
|
||||
}
|
||||
Field[] keys = refAdapter.getRecordKeysForAddr(refAddr);
|
||||
for (Field key : keys) {
|
||||
EquateRefDB ref = getEquateRefDB(key.getLongValue());
|
||||
if (ref.getEquateID() == equateID) {
|
||||
refs.add(ref);
|
||||
}
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
void removeReference(EquateDB equateDB, Address refAddr, short opIndex) throws IOException {
|
||||
|
||||
Field[] keys = refAdapter.getRecordKeysForEquateID(equateDB.getKey());
|
||||
|
|
|
@ -32,7 +32,7 @@ public class EquateSymbol extends HighSymbol {
|
|||
|
||||
private long value; // Value of the equate
|
||||
private int convert; // Non-zero if this is a conversion equate
|
||||
|
||||
|
||||
public EquateSymbol(HighFunction func) {
|
||||
super(func);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class EquateSymbol extends HighSymbol {
|
|||
DynamicEntry entry = new DynamicEntry(this, addr, hash);
|
||||
addMapEntry(entry);
|
||||
}
|
||||
|
||||
|
||||
public EquateSymbol(long uniqueId, int conv, long val, HighFunction func, Address addr,
|
||||
long hash) {
|
||||
super(uniqueId, "", DataType.DEFAULT, func);
|
||||
|
@ -57,7 +57,9 @@ public class EquateSymbol extends HighSymbol {
|
|||
addMapEntry(entry);
|
||||
}
|
||||
|
||||
public long getValue() { return value; }
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getConvert() {
|
||||
return convert;
|
||||
|
@ -121,8 +123,18 @@ public class EquateSymbol extends HighSymbol {
|
|||
buf.append("</value>\n");
|
||||
buf.append("</equatesymbol>\n");
|
||||
}
|
||||
|
||||
public static int convertName(String nm,long val) {
|
||||
|
||||
/**
|
||||
* Determine what format a given equate name is in.
|
||||
* Integer format conversions are stored using an Equate object, where the name of the equate
|
||||
* is the actual conversion String. So the only way to tell what kind of conversion is being performed
|
||||
* is by examining the name of the equate. The format code of the conversion is returned, or if
|
||||
* the name is not a conversion, FORMAT_DEFAULT is returned indicating a normal String equate.
|
||||
* @param nm is the name of the equate
|
||||
* @param val is the value being equated
|
||||
* @return the format code for the conversion or FORMAT_DEFAULT if not a conversion
|
||||
*/
|
||||
public static int convertName(String nm, long val) {
|
||||
int pos = 0;
|
||||
char firstChar = nm.charAt(pos++);
|
||||
if (firstChar == '-') {
|
||||
|
@ -133,32 +145,53 @@ public class EquateSymbol extends HighSymbol {
|
|||
return FORMAT_DEFAULT; // Bad equate name, just print number normally
|
||||
}
|
||||
}
|
||||
if (firstChar == '\'') {
|
||||
return FORMAT_CHAR;
|
||||
}
|
||||
if (firstChar == '"') { // Multi-character conversion
|
||||
return FORMAT_DEC; // not currently supported, just format in decimal
|
||||
}
|
||||
if (firstChar < '0' || firstChar > '9') {
|
||||
return -1; // Don't treat as a conversion
|
||||
}
|
||||
char lastChar = nm.charAt(nm.length() - 1);
|
||||
if (lastChar == 'b') {
|
||||
return FORMAT_BIN;
|
||||
}
|
||||
else if (lastChar == 'o') {
|
||||
return FORMAT_OCT;
|
||||
}
|
||||
int format = FORMAT_DEC;
|
||||
if (firstChar == '0') {
|
||||
format = FORMAT_DEC;
|
||||
if (nm.length() >= (pos + 1)) {
|
||||
char c = nm.charAt(pos);
|
||||
if (c == 'x') {
|
||||
format = FORMAT_HEX;
|
||||
switch (firstChar) {
|
||||
case '\'':
|
||||
case '"':
|
||||
return FORMAT_CHAR;
|
||||
case '0':
|
||||
if (nm.length() >= (pos + 1) && nm.charAt(pos) == 'x') {
|
||||
return FORMAT_HEX;
|
||||
}
|
||||
}
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
if (nm.length() >= 3 && nm.charAt(2) == 'h') {
|
||||
char secondChar = nm.charAt(1);
|
||||
if (secondChar >= '0' && secondChar <= '9') {
|
||||
return FORMAT_CHAR;
|
||||
}
|
||||
if (secondChar >= 'A' && secondChar <= 'F') {
|
||||
return FORMAT_CHAR;
|
||||
}
|
||||
}
|
||||
return FORMAT_DEFAULT;
|
||||
default:
|
||||
return FORMAT_DEFAULT; // Don't treat as a conversion
|
||||
}
|
||||
return format;
|
||||
switch (nm.charAt(nm.length() - 1)) {
|
||||
case 'b':
|
||||
return FORMAT_BIN;
|
||||
case 'o':
|
||||
return FORMAT_OCT;
|
||||
case '\'':
|
||||
case '"':
|
||||
case 'h': // The 'h' encoding is used for "unrepresentable" characters
|
||||
return FORMAT_CHAR;
|
||||
}
|
||||
return FORMAT_DEC;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,8 @@ public class LocalSymbolMap {
|
|||
public LocalSymbolMap(HighFunction highFunc, String spcname) {
|
||||
func = highFunc;
|
||||
spacename = spcname;
|
||||
addrMappedSymbols = new HashMap<MappedVarKey, HighSymbol>();
|
||||
symbolMap = new HashMap<Long, HighSymbol>();
|
||||
addrMappedSymbols = new HashMap<>();
|
||||
symbolMap = new HashMap<>();
|
||||
paramSymbols = new HighSymbol[0];
|
||||
uniqueSymbolId = 0;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public class LocalSymbolMap {
|
|||
* @return the new name to symbol map
|
||||
*/
|
||||
public Map<String, HighSymbol> getNameToSymbolMap() {
|
||||
Map<String, HighSymbol> newMap = new TreeMap<String, HighSymbol>();
|
||||
Map<String, HighSymbol> newMap = new TreeMap<>();
|
||||
for (HighSymbol highSymbol : symbolMap.values()) {
|
||||
newMap.put(highSymbol.getName(), highSymbol);
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ public class LocalSymbolMap {
|
|||
// An indication of names like "name", "name@1", "name@2"
|
||||
if (name.charAt(name.length() - 1) == '1') {
|
||||
if (mergeNames == null) {
|
||||
mergeNames = new ArrayList<String>();
|
||||
mergeNames = new ArrayList<>();
|
||||
}
|
||||
mergeNames.add(name);
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ public class LocalSymbolMap {
|
|||
Address pcaddr = dbFunction.getEntryPoint();
|
||||
pcaddr = pcaddr.subtractWrap(1);
|
||||
|
||||
List<HighSymbol> paramList = new ArrayList<HighSymbol>();
|
||||
List<HighSymbol> paramList = new ArrayList<>();
|
||||
for (int i = 0; i < p.length; ++i) {
|
||||
Parameter var = p[i];
|
||||
if (!var.isValid()) {
|
||||
|
@ -220,7 +220,7 @@ public class LocalSymbolMap {
|
|||
// An indication of names like "name", "name@1", "name@2"
|
||||
if (name.charAt(name.length() - 1) == '1') {
|
||||
if (mergeNames == null) {
|
||||
mergeNames = new ArrayList<String>();
|
||||
mergeNames = new ArrayList<>();
|
||||
}
|
||||
mergeNames.add(name);
|
||||
}
|
||||
|
@ -297,13 +297,12 @@ public class LocalSymbolMap {
|
|||
parser.end(el);
|
||||
}
|
||||
|
||||
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR =
|
||||
new Comparator<HighSymbol>() {
|
||||
@Override
|
||||
public int compare(HighSymbol sym1, HighSymbol sym2) {
|
||||
return sym1.getCategoryIndex() - sym2.getCategoryIndex();
|
||||
}
|
||||
};
|
||||
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR = new Comparator<>() {
|
||||
@Override
|
||||
public int compare(HighSymbol sym1, HighSymbol sym2) {
|
||||
return sym1.getCategoryIndex() - sym2.getCategoryIndex();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add mapped symbols to this LocalVariableMap, by parsing the <symbollist> and <mapsym> tags.
|
||||
|
@ -312,7 +311,7 @@ public class LocalSymbolMap {
|
|||
*/
|
||||
public void parseSymbolList(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("symbollist");
|
||||
ArrayList<HighSymbol> parms = new ArrayList<HighSymbol>();
|
||||
ArrayList<HighSymbol> parms = new ArrayList<>();
|
||||
while (parser.peek().isStart()) {
|
||||
HighSymbol sym = parseSymbolXML(parser);
|
||||
if (sym.isParameter()) {
|
||||
|
@ -483,7 +482,7 @@ public class LocalSymbolMap {
|
|||
uniqueId = getNextId();
|
||||
}
|
||||
int conv = EquateSymbol.convertName(nm, val);
|
||||
if (conv < 0) {
|
||||
if (conv == EquateSymbol.FORMAT_DEFAULT) {
|
||||
eqSymbol = new EquateSymbol(uniqueId, nm, val, func, addr, hash);
|
||||
eqSymbol.setNameLock(true);
|
||||
}
|
||||
|
@ -507,25 +506,37 @@ public class LocalSymbolMap {
|
|||
while (equateAddresses.hasNext()) {
|
||||
Address defAddr = equateAddresses.next();
|
||||
for (Equate eq : equateTable.getEquates(defAddr)) {
|
||||
Instruction instr = listing.getInstructionAt(defAddr);
|
||||
if (instr == null) {
|
||||
continue;
|
||||
}
|
||||
long hash[] = DynamicHash.calcConstantHash(instr, eq.getValue());
|
||||
if (hash.length == 0) {
|
||||
continue;
|
||||
}
|
||||
Arrays.sort(hash); // Sort in preparation for deduping
|
||||
List<EquateReference> references = eq.getReferences(defAddr);
|
||||
String displayName = eq.getDisplayName();
|
||||
long eqValue = eq.getValue();
|
||||
|
||||
EquateSymbol eqSymbol;
|
||||
for (int i = 0; i < hash.length; ++i) {
|
||||
if (i != 0 && hash[i - 1] == hash[i]) {
|
||||
continue; // Found a duplicate, skip it
|
||||
for (EquateReference ref : references) {
|
||||
long hashVal = ref.getDynamicHashValue();
|
||||
if (hashVal == 0) {
|
||||
// Multiple varnodes of the same constant
|
||||
Instruction instr = listing.getInstructionAt(defAddr);
|
||||
if (instr == null) {
|
||||
continue;
|
||||
}
|
||||
long hash[] = DynamicHash.calcConstantHash(instr, eqValue);
|
||||
if (hash.length == 0) {
|
||||
continue;
|
||||
}
|
||||
Arrays.sort(hash); // Sort in preparation for deduping
|
||||
for (int i = 0; i < hash.length; ++i) {
|
||||
if (i != 0 && hash[i - 1] == hash[i]) {
|
||||
continue; // Found a duplicate, skip it
|
||||
}
|
||||
// Emit each varnode copy as a separate EquateSymbol
|
||||
eqSymbol = newEquateSymbol(0, displayName, eqValue, hash[i], defAddr);
|
||||
symbolMap.put(eqSymbol.getId(), eqSymbol);
|
||||
}
|
||||
}
|
||||
else {
|
||||
eqSymbol = newEquateSymbol(0, displayName, eqValue, hashVal, defAddr);
|
||||
symbolMap.put(eqSymbol.getId(), eqSymbol);
|
||||
}
|
||||
eqSymbol = newEquateSymbol(0, displayName, eqValue, hash[i], defAddr);
|
||||
symbolMap.put(eqSymbol.getId(), eqSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.program.model.symbol;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.UniversalID;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
/**
|
||||
* An Equate associates a string with a scalar value in the program,
|
||||
* and contains a list of addresses and operand positions that refer
|
||||
|
@ -45,7 +48,7 @@ public interface Equate {
|
|||
/**
|
||||
* Get the value of this equate.
|
||||
*/
|
||||
public long getValue();
|
||||
public long getValue();
|
||||
|
||||
/**
|
||||
* Gets a more accurate representation of the equate value. Used for rendering as close to the
|
||||
|
@ -57,7 +60,7 @@ public interface Equate {
|
|||
/**
|
||||
* Get the number of references to this equate.
|
||||
*/
|
||||
public int getReferenceCount();
|
||||
public int getReferenceCount();
|
||||
|
||||
/**
|
||||
* Add a reference (at the given operand position) to this equate. If a reference already
|
||||
|
@ -67,9 +70,9 @@ public interface Equate {
|
|||
* @param refAddr the address where the equate is used.
|
||||
* @param opndPosition the operand index where the equate is used.
|
||||
*/
|
||||
public void addReference(Address refAddr,int opndPosition);
|
||||
|
||||
/**
|
||||
public void addReference(Address refAddr, int opndPosition);
|
||||
|
||||
/**
|
||||
* Add a reference (at the given dynamic hash position) to this equate. If a reference already
|
||||
* exists for the instruction at this address, then the old reference will be removed
|
||||
* before the new reference is added.
|
||||
|
@ -77,39 +80,45 @@ public interface Equate {
|
|||
* @param dynamicHash constant varnode dynamic hash value
|
||||
* @param refAddr the address where the equate is used.
|
||||
*/
|
||||
public void addReference(long dynamicHash, Address refAddr);
|
||||
public void addReference(long dynamicHash, Address refAddr);
|
||||
|
||||
/**
|
||||
* Changes the name associated with the equate.
|
||||
* @param newName the new name for this equate.
|
||||
* @exception DuplicateNameException thrown if newName is already
|
||||
* used by another equate.
|
||||
* @throws InvalidInputException if newName contains blank characters,
|
||||
* is zero length, or is null
|
||||
*/
|
||||
void renameEquate(String newName) throws DuplicateNameException,
|
||||
InvalidInputException;
|
||||
/**
|
||||
* Changes the name associated with the equate.
|
||||
* @param newName the new name for this equate.
|
||||
* @exception DuplicateNameException thrown if newName is already
|
||||
* used by another equate.
|
||||
* @throws InvalidInputException if newName contains blank characters,
|
||||
* is zero length, or is null
|
||||
*/
|
||||
void renameEquate(String newName) throws DuplicateNameException, InvalidInputException;
|
||||
|
||||
/**
|
||||
* Get the references for this equate.
|
||||
* @return a array of EquateReferences.
|
||||
*/
|
||||
public EquateReference[] getReferences();
|
||||
public EquateReference[] getReferences();
|
||||
|
||||
/**
|
||||
* Get references for this equate attached to a specific address
|
||||
* @param refAddr is the address
|
||||
* @return the list of EquateReferences
|
||||
*/
|
||||
public List<EquateReference> getReferences(Address refAddr);
|
||||
|
||||
/**
|
||||
* Remove the reference at the given operand position.
|
||||
* @param refAddr the address that was using this equate
|
||||
* @param opndPosition the operand index of the operand that was using this eqate.
|
||||
*/
|
||||
public void removeReference(Address refAddr, int opndPosition);
|
||||
|
||||
/**
|
||||
public void removeReference(Address refAddr, int opndPosition);
|
||||
|
||||
/**
|
||||
* Remove the reference at the given address
|
||||
* @param dynamicHash the hash of the reference
|
||||
* @param refAddr the reference's address
|
||||
*/
|
||||
public void removeReference(long dynamicHash, Address refAddr);
|
||||
|
||||
public void removeReference(long dynamicHash, Address refAddr);
|
||||
|
||||
/**
|
||||
* Checks if equate is based off an enum's universal id and checks if the enum still exists.
|
||||
* The equate is still valid if the equate is not based off an enum.
|
||||
|
@ -129,10 +138,10 @@ public interface Equate {
|
|||
*/
|
||||
public UniversalID getEnumUUID();
|
||||
|
||||
/**
|
||||
* Get the name of this equate.
|
||||
* @see #getName()
|
||||
*/
|
||||
@Override
|
||||
/**
|
||||
* Get the name of this equate.
|
||||
* @see #getName()
|
||||
*/
|
||||
@Override
|
||||
public String toString();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue