Merge remote-tracking branch 'origin/GP-4535_emteere_FixStoreOfDefaultDisassemblyContext--SQUASHED'

This commit is contained in:
ghidra1 2024-05-02 20:21:52 -04:00
commit 5361b13e6f
7 changed files with 106 additions and 81 deletions

View file

@ -66,7 +66,7 @@ public class ConstantPropagationAnalyzer extends AbstractAnalyzer {
protected static final String MAX_THREAD_COUNT_OPTION_NAME = "Max Threads";
protected static final String MAX_THREAD_COUNT_OPTION_DESCRIPTION =
"Maximum threads for constant propagation. Too many threads causes thrashing in DB.";
protected static final int MAX_THREAD_COUNT_OPTION_DEFAULT_VALUE = 2;
protected static final int MAX_THREAD_COUNT_OPTION_DEFAULT_VALUE = 1;
protected static final String MIN_KNOWN_REFADDRESS_OPTION_NAME = "Min absolute reference";
protected static final String MIN_KNOWN_REFADDRESS_OPTION_DESCRIPTION =

View file

@ -184,25 +184,12 @@ public class DecompilerSwitchAnalysisCmd extends BackgroundCommand<Program> {
if (disSetList.contains(caseStart)) {
continue;
}
if (switchContext != null) {
try {
// Combine flowed switch context with context register value at case address
RegisterValue curContext =
programContext.getRegisterValue(baseContextRegister, caseStart);
if (curContext != null) {
curContext = curContext.combineValues(switchContext);
// lay down the new merged context
programContext.setRegisterValue(caseStart, caseStart, curContext);
}
else {
programContext.setRegisterValue(caseStart, caseStart, switchContext);
}
}
catch (ContextChangeException e) {
// This can occur when two or more threads are working on the same function
continue;
}
try {
setSwitchTargetContext(programContext, caseStart, switchContext);
}
catch (ContextChangeException e) {
// This can occur when two or more threads are working on the same function
continue;
}
disSetList.add(caseStart);
}
@ -229,6 +216,26 @@ public class DecompilerSwitchAnalysisCmd extends BackgroundCommand<Program> {
}
}
private void setSwitchTargetContext(ProgramContext programContext, Address targetStart, RegisterValue switchContext) throws ContextChangeException {
if (switchContext == null) {
return;
}
// Combine flowed switch context with context register value at case address
RegisterValue curContext =
programContext.getNonDefaultValue(switchContext.getRegister(), targetStart);
if (curContext != null) {
switchContext = curContext.combineValues(switchContext);
}
if (switchContext == null || !switchContext.hasAnyValue()) {
return;
}
// only store if different than what is already there, which could be a default value
program.getProgramContext().setRegisterValue(targetStart, targetStart, switchContext);
}
private void labelSwitch(JumpTable table, TaskMonitor monitor) throws CancelledException {
AddLabelCmd tableNameLabel =
new AddLabelCmd(table.getSwitchAddress(), "switchD", SourceType.ANALYSIS);

View file

@ -583,7 +583,7 @@ public class Table {
* @return record count
*/
public int getRecordCount() {
return tableRecord.getRecordCount();
return (tableRecord == null ? 0 : tableRecord.getRecordCount());
}
/**

View file

@ -250,7 +250,7 @@ class TableRecord implements Comparable<TableRecord> {
* @return table's record count
*/
int getRecordCount() {
return record.getIntValue(RECORD_COUNT_COLUMN);
return (record == null ? 0 : record.getIntValue(RECORD_COUNT_COLUMN));
}
/**

View file

@ -21,6 +21,7 @@ import java.util.List;
import db.*;
import db.util.ErrorHandler;
import generic.stl.Pair;
import ghidra.program.database.map.AddressKeyRecordIterator;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.address.*;
@ -85,9 +86,8 @@ public class AddressRangeMapDB implements DBListener {
private Schema rangeMapSchema;
private Table rangeMapTable;
// caching
private Field lastValue;
private AddressRange lastRange;
// caching, single value, so safer to check
private Pair<AddressRange, Field> lastValue;
private int modCount;
@ -136,10 +136,16 @@ public class AddressRangeMapDB implements DBListener {
* @throws DuplicateNameException if there is already range map with that name
*/
public boolean setName(String newName) throws DuplicateNameException {
String newTableName = RANGE_MAP_TABLE_PREFIX + newName;
if (rangeMapTable == null || rangeMapTable.setName(newTableName)) {
tableName = newTableName;
return true;
lock.acquire();
try {
String newTableName = RANGE_MAP_TABLE_PREFIX + newName;
if (rangeMapTable == null || rangeMapTable.setName(newTableName)) {
tableName = newTableName;
return true;
}
}
finally {
lock.release();
}
return false;
}
@ -149,13 +155,8 @@ public class AddressRangeMapDB implements DBListener {
* @return true if this map is empty
*/
public boolean isEmpty() {
lock.acquire();
try {
return rangeMapTable == null || rangeMapTable.getRecordCount() == 0;
}
finally {
lock.release();
}
Table localTable = rangeMapTable;
return localTable == null || localTable.getRecordCount() == 0;
}
/**
@ -165,7 +166,8 @@ public class AddressRangeMapDB implements DBListener {
* @return record count
*/
public int getRecordCount() {
return rangeMapTable != null ? rangeMapTable.getRecordCount() : 0;
Table localTable = rangeMapTable;
return localTable == null ? 0 : localTable.getRecordCount();
}
/**
@ -174,23 +176,26 @@ public class AddressRangeMapDB implements DBListener {
* @return value or null no value exists
*/
public Field getValue(Address address) {
if (isEmpty()) {
return null;
}
// check last cached range
Pair<AddressRange, Field> localValue = lastValue;
if (localValue != null && localValue.first.contains(address)) {
return localValue.second;
}
lock.acquire();
try {
if (rangeMapTable == null) {
return null;
}
// check last cached range
if (lastRange != null && lastRange.contains(address)) {
return lastValue;
}
DBRecord record = findRecordContaining(address);
List<AddressRange> ranges = getRangesForRecord(record);
for (AddressRange range : ranges) {
if (range.contains(address)) {
lastRange = range;
lastValue = record.getFieldValue(VALUE_COL);
return lastValue;
Field fieldValue = record.getFieldValue(VALUE_COL);
lastValue = new Pair<AddressRange, Field>(range, fieldValue);
return fieldValue;
}
}
}
@ -214,16 +219,19 @@ public class AddressRangeMapDB implements DBListener {
* @throws IllegalArgumentException if the end address is greater then the start address
*/
public void paintRange(Address startAddress, Address endAddress, Field value) {
if (value == null && isEmpty()) {
return;
}
AddressRange.checkValidRange(startAddress, endAddress);
lock.acquire();
try {
if (value == null && rangeMapTable == null) {
return;
}
clearCache();
++modCount;
if (rangeMapTable == null) {
if (value == null) {
return;
}
createTable();
}
doPaintRange(startAddress, endAddress, value);
@ -246,7 +254,7 @@ public class AddressRangeMapDB implements DBListener {
*/
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
throws CancelledException {
if (length <= 0 || rangeMapTable == null) {
if (length <= 0 || isEmpty()) {
return;
}
@ -254,6 +262,9 @@ public class AddressRangeMapDB implements DBListener {
AddressRangeMapDB tmpMap = null;
lock.acquire();
try {
if (rangeMapTable == null) {
return;
}
tmpDb = dbHandle.getScratchPad();
tmpMap = new AddressRangeMapDB(tmpDb, addressMap, lock, "TEMP", errHandler, valueField,
indexed);
@ -310,9 +321,15 @@ public class AddressRangeMapDB implements DBListener {
* @return set of addresses where a values has been set
*/
public AddressSet getAddressSet() {
AddressSet set = new AddressSet();
if (isEmpty()) {
return set;
}
lock.acquire();
try {
AddressSet set = new AddressSet();
if (rangeMapTable == null) {
return set;
}
AddressRangeIterator addressRanges = getAddressRanges();
for (AddressRange addressRange : addressRanges) {
set.add(addressRange);
@ -331,11 +348,15 @@ public class AddressRangeMapDB implements DBListener {
*/
public AddressSet getAddressSet(Field value) {
AddressSet set = new AddressSet();
if (rangeMapTable == null) {
if (isEmpty()) {
return set;
}
lock.acquire();
try {
if (rangeMapTable == null) {
return set;
}
RecordIterator it = rangeMapTable.indexIterator(VALUE_COL, value, value, true);
while (it.hasNext()) {
DBRecord record = it.next();
@ -357,7 +378,7 @@ public class AddressRangeMapDB implements DBListener {
* @return AddressRangeIterator that iterates over all occupied ranges in the map
*/
public AddressRangeIterator getAddressRanges() {
if (rangeMapTable == null) {
if (isEmpty()) {
return new EmptyAddressRangeIterator();
}
try {
@ -377,7 +398,7 @@ public class AddressRangeMapDB implements DBListener {
* given start address
*/
public AddressRangeIterator getAddressRanges(Address startAddress) {
if (rangeMapTable == null) {
if (isEmpty()) {
return new EmptyAddressRangeIterator();
}
try {
@ -398,7 +419,7 @@ public class AddressRangeMapDB implements DBListener {
* given start address
*/
public AddressRangeIterator getAddressRanges(Address startAddress, Address endAddr) {
if (rangeMapTable == null) {
if (isEmpty()) {
return new EmptyAddressRangeIterator();
}
try {
@ -492,14 +513,13 @@ public class AddressRangeMapDB implements DBListener {
* @return an address range that contains the given address and has all the same value
*/
public AddressRange getAddressRangeContaining(Address address) {
// check cache
Pair<AddressRange, Field> localValue = lastValue;
if (localValue != null && localValue.first.contains(address)) {
return localValue.first;
}
lock.acquire();
try {
// check cache
if (lastRange != null && lastRange.contains(address)) {
return lastRange;
}
// look for a stored value range that contains that address
AddressRange range = findValueRangeContainingAddress(address);
if (range == null) {
@ -522,8 +542,8 @@ public class AddressRangeMapDB implements DBListener {
List<AddressRange> rangesForRecord = getRangesForRecord(record);
for (AddressRange range : rangesForRecord) {
if (range.contains(address)) {
lastRange = range;
lastValue = record.getFieldValue(VALUE_COL);
Field fieldValue = record.getFieldValue(VALUE_COL);
lastValue = new Pair<AddressRange, Field>(range, fieldValue);
return range;
}
}
@ -786,14 +806,7 @@ public class AddressRangeMapDB implements DBListener {
* Clears the "last range" cache
*/
private void clearCache() {
lock.acquire();
try {
lastRange = null;
lastValue = null;
}
finally {
lock.release();
}
lastValue = null;
}
DBRecord getAddressWrappingRecord() throws IOException {

View file

@ -1389,7 +1389,12 @@ public class Disassembler implements DisassemblerConflictHandler {
RegisterValue contextValue = conflict.getParseContextValue();
if (contextValue != null) {
try {
program.getProgramContext().setRegisterValue(address, address, contextValue);
RegisterValue curContextValue = program.getProgramContext().getRegisterValue(contextValue.getRegister(), address);
// only store if different than what is already there, which could be a default value
if (!contextValue.equals(curContextValue)) {
program.getProgramContext().setRegisterValue(address, address, contextValue);
}
}
catch (ContextChangeException e) {
// ignore - existing instruction likely blocked context modification

View file

@ -143,7 +143,7 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
}
RegisterValueStore store = map.get(register.getBaseRegister());
if (store == null) {
if (store == null || store.isEmpty()) {
return null;
}
@ -153,8 +153,8 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
@Override
public AddressRangeIterator getRegisterValueAddressRanges(Register register) {
RegisterValueStore store = registerValueMap.get(register.getBaseRegister());
if (store == null) {
return new AddressSet().getAddressRanges();
if (store == null || store.isEmpty()) {
return new EmptyAddressRangeIterator();
}
return new RegisterAddressRangeIterator(register, store.getAddressRangeIterator(),
registerValueMap);
@ -163,7 +163,7 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
@Override
public AddressRange getRegisterValueRangeContaining(Register register, Address addr) {
RegisterValueStore store = registerValueMap.get(register.getBaseRegister());
if (store == null) {
if (store == null || store.isEmpty()) {
return new AddressRangeImpl(addr, addr);
}
return store.getValueRangeContaining(addr);
@ -173,8 +173,8 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
public AddressRangeIterator getRegisterValueAddressRanges(Register register, Address start,
Address end) {
RegisterValueStore store = registerValueMap.get(register.getBaseRegister());
if (store == null) {
return new AddressSet().getAddressRanges();
if (store == null || store.isEmpty()) {
return new EmptyAddressRangeIterator();
}
return new RegisterAddressRangeIterator(register, store.getAddressRangeIterator(start, end),
registerValueMap);
@ -183,8 +183,8 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
@Override
public AddressRangeIterator getDefaultRegisterValueAddressRanges(Register register) {
RegisterValueStore store = defaultRegisterValueMap.get(register.getBaseRegister());
if (store == null) {
return new AddressSet().getAddressRanges();
if (store == null || store.isEmpty()) {
return new EmptyAddressRangeIterator();
}
return new RegisterAddressRangeIterator(register, store.getAddressRangeIterator(),
defaultRegisterValueMap);
@ -194,8 +194,8 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
public AddressRangeIterator getDefaultRegisterValueAddressRanges(Register register,
Address start, Address end) {
RegisterValueStore store = defaultRegisterValueMap.get(register.getBaseRegister());
if (store == null) {
return new AddressSet().getAddressRanges();
if (store == null || store.isEmpty()) {
return new EmptyAddressRangeIterator();
}
return new RegisterAddressRangeIterator(register, store.getAddressRangeIterator(start, end),
defaultRegisterValueMap);