Merge remote-tracking branch 'origin/GP-1053_DecompilerConversion' into patch

This commit is contained in:
ghidra1 2021-07-06 14:22:07 -04:00
commit 2143c4961d
35 changed files with 2430 additions and 281 deletions

View file

@ -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()
*/

View file

@ -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());

View file

@ -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;
}
}

View file

@ -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 &lt;symbollist&gt; and &lt;mapsym&gt; 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);
}
}
}

View file

@ -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();
}