GP-38 Refactored language/context related APIs to return unmodifiable

lists instead of arrays for some register related methods
This commit is contained in:
ghidra1 2020-07-21 19:10:19 -04:00
parent 0386895578
commit e39b2e9ea9
43 changed files with 346 additions and 389 deletions

View file

@ -29,7 +29,6 @@ src/main/java/ghidra/program/database/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/address/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/block/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/data/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/graph/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/lang/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/listing/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/mem/package.html||GHIDRA||||END|

View file

@ -16,6 +16,7 @@
package ghidra.app.plugin.assembler.sleigh.sem;
import java.math.BigInteger;
import java.util.List;
import ghidra.app.plugin.assembler.sleigh.util.DbgTimer;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
@ -117,7 +118,7 @@ public class AssemblyDefaultContext implements DisassemblerContext, DefaultProgr
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return lang.getRegisters();
}

View file

@ -1276,7 +1276,7 @@ public class SleighDebugLogger {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
if (originalContext != null) {
return originalContext.getRegisters();
}

View file

@ -266,7 +266,7 @@ public class SleighLanguage implements Language {
}
@Override
public Register[] getContextRegisters() {
public List<Register> getContextRegisters() {
return getRegisterManager().getContextRegisters();
}
@ -336,12 +336,12 @@ public class SleighLanguage implements Language {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return getRegisterManager().getRegisters();
}
@Override
public String[] getRegisterNames() {
public List<String> getRegisterNames() {
return getRegisterManager().getRegisterNames();
}
@ -1080,11 +1080,8 @@ public class SleighLanguage implements Language {
}
private void xrefRegisters() {
Register[] regs = getRegisterManager().getRegisters();
for (Register register : regs) {
if (register.isProcessorContext()) {
contextcache.registerVariable(register);
}
for (Register register : getRegisterManager().getContextRegisters()) {
contextcache.registerVariable(register);
}
}
@ -1587,7 +1584,7 @@ public class SleighLanguage implements Language {
}
@Override
public Register[] getSortedVectorRegisters() {
public List<Register> getSortedVectorRegisters() {
return registerManager.getSortedVectorRegisters();
}

View file

@ -16,6 +16,7 @@
package ghidra.app.util;
import java.math.BigInteger;
import java.util.List;
import ghidra.program.disassemble.DisassemblerContextImpl;
import ghidra.program.model.address.Address;
@ -56,7 +57,7 @@ public class PseudoDisassemblerContext implements DisassemblerContext {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return disContext.getRegisters();
}

View file

@ -548,7 +548,7 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return procContext.getRegisters();
}

View file

@ -154,7 +154,7 @@ public class EmulateDisassemblerContext implements DisassemblerContext {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
throw new UnsupportedOperationException();
}

View file

@ -17,8 +17,7 @@ package ghidra.program.database.code;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
@ -753,7 +752,7 @@ abstract class CodeUnitDB extends DatabaseObject implements CodeUnit, ProcessorC
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return programContext.getRegisters();
}

View file

@ -17,6 +17,7 @@ package ghidra.program.database.code;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.StringTokenizer;
import db.*;
@ -130,8 +131,9 @@ class PrototypeManager {
RecordIterator it = contextTable.iterator();
while (it.hasNext()) {
monitor.setProgress(++count);
if (monitor.isCancelled())
if (monitor.isCancelled()) {
throw new IOException("Upgrade Cancelled");
}
Record rec = it.next();
String oldValue = rec.getString(0);
rec.setString(0, convertString(oldValue));
@ -143,8 +145,9 @@ class PrototypeManager {
it = tempTable.iterator();
while (it.hasNext()) {
monitor.setProgress(++count);
if (monitor.isCancelled())
if (monitor.isCancelled()) {
throw new IOException("Upgrade Cancelled");
}
Record rec = it.next();
contextTable.putRecord(rec);
}
@ -187,8 +190,9 @@ class PrototypeManager {
RecordIterator it = protoAdapter.getRecords();
while (it.hasNext()) {
monitor.setProgress(++count);
if (monitor.isCancelled())
if (monitor.isCancelled()) {
throw new IOException("Upgrade Cancelled");
}
Record rec = it.next();
tempAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
@ -201,8 +205,9 @@ class PrototypeManager {
it = tempAdapter.getRecords();
while (it.hasNext()) {
monitor.setProgress(++count);
if (monitor.isCancelled())
if (monitor.isCancelled()) {
throw new IOException("Upgrade Cancelled");
}
Record rec = it.next();
protoAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
@ -287,19 +292,10 @@ class PrototypeManager {
return 0;
}
// private boolean shouldSave(BigInteger value, BigInteger defaultValue) {
// if (value == null) {
// return false;
// }
// if (defaultValue == null) {
// return true;
// }
// return !value.equals(defaultValue);
//
// }
/**
* Get the prototype with the given ID.
* @param protoID prototype ID
* @return instruction prototype or null if not found
*/
InstructionPrototype getPrototype(int protoID) {
if (protoID < 0) {
@ -449,25 +445,16 @@ class PrototypeManager {
this.address = address;
}
/**
* @see ghidra.program.model.lang.ProcessorContext#getRegister(java.lang.String)
*/
@Override
public Register getRegister(String name) {
return programContext.getRegister(name);
}
/**
* @see ghidra.program.model.lang.ProcessorContext#getRegisters()
*/
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return programContext.getRegisters();
}
/**
* @see ghidra.program.model.lang.ProcessorContext#hasValue(ghidra.program.model.lang.Register)
*/
@Override
public boolean hasValue(Register register) {
return false;

View file

@ -49,16 +49,14 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
private DBHandle dbHandle;
private ErrorHandler errHandler;
private Register[] registers;
private Language language;
private AddressMap addrMap;
private int registerSpaceSize;
private Lock lock;
/**
* maintain values stored in registers for specified addresses and
* address ranges using the PropertyMap utilities.
*/
private HashMap<String, Register> registersMap;
private Map<Integer, AddressRangeMapDB> valueMaps;
private Register baseContextRegister;
protected Map<Register, RegisterValueStore> defaultRegisterValueMap;
@ -82,28 +80,12 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
this.errHandler = errHandler;
this.lock = lock;
this.addrMap = addrMap.getOldAddressMap();
this.registers = language.getRegisters();
this.language = language;
defaultRegisterValueMap = new HashMap<Register, RegisterValueStore>();
registersMap = new HashMap<String, Register>();
valueMaps = new HashMap<>();
registerSpaceSize = 0;
for (Register register : registers) {
String registerName = register.getName();
registersMap.put(registerName.toUpperCase(), register);
int offset = (register.getOffset() & 0xffff);
if (offset + register.getMinimumByteSize() > registerSpaceSize) {
registerSpaceSize = offset + register.getMinimumByteSize();
}
}
for (Register register : registers) {
if (register.isProcessorContext()) {
baseContextRegister = register.getBaseRegister();
break;
}
}
baseContextRegister = language.getContextBaseRegister();
if (baseContextRegister == null) {
baseContextRegister =
new Register("DEFAULT_CONTEXT", "DEFAULT_CONTEXT",
@ -186,28 +168,18 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
}
@Override
public Register[] getProcessorStateRegisters() {
List<Register> list = new ArrayList<Register>();
for (Register register : registers) {
if (register.isProcessorContext()) {
list.add(register);
}
}
return list.toArray(new Register[list.size()]);
public List<Register> getContextRegisters() {
return language.getContextRegisters();
}
@Override
public Register getRegister(String name) {
return registersMap.get(name.toUpperCase());
return language.getRegister(name);
}
@Override
public String[] getRegisterNames() {
List<String> list = new ArrayList<String>();
for (Register register : registers) {
list.add(register.getName());
}
return list.toArray(new String[list.size()]);
public List<String> getRegisterNames() {
return language.getRegisterNames();
}
@Override
@ -273,8 +245,8 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
}
@Override
public Register[] getRegisters() {
return registers;
public List<Register> getRegisters() {
return language.getRegisters();
}
public long getSigned(Address addr, Register reg) throws UnsupportedOperationException {
@ -446,7 +418,7 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
public Register[] getRegistersWithValues() {
if (registersWithValues == null) {
List<Register> tmp = new ArrayList<Register>();
for (Register register : registers) {
for (Register register : getRegisters()) {
AddressRangeIterator it = getRegisterValueAddressRanges(register);
if (it.hasNext()) {
tmp.add(register);

View file

@ -17,8 +17,7 @@ package ghidra.program.database.register;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.*;
import db.*;
import db.util.ErrorHandler;
@ -326,8 +325,8 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
// Sort the registers by size so that largest come first.
// This prevents the remove call below from incorrectly clearing
// smaller registers that are part of a larger register.
Register[] registers = language.getRegisters().clone();
Arrays.sort(registers, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
List<Register> registers = new ArrayList<Register>(language.getRegisters());
Collections.sort(registers, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
// Map all register stores to new registers
for (Register register : registers) {

View file

@ -1727,7 +1727,7 @@ public class Disassembler implements DisassemblerConflictHandler {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return langauge.getRegisters();
}

View file

@ -566,7 +566,7 @@ public class DisassemblerContextImpl implements DisassemblerContext {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return programContext.getRegisters();
}

View file

@ -206,21 +206,21 @@ public interface Language {
public Register getRegister(AddressSpace addrspc, long offset, int size);
/**
* Get the unsorted array of Register objects that this language supports
* Get an unsorted unmodifiable list of Register objects that this language defines
* (including context registers).
*
* @return the array of processor registers.
* @return unmodifiable list of processor registers.
*/
public Register[] getRegisters();
public List<Register> getRegisters();
/**
* Get the unsorted array of register names that this language supports
* Get an alphabetical sorted unmodifiable list of original register names
* (including context registers). Names correspond to orignal register
* name and not aliases which may be defined.
*
* @return the array of processor register names.
* @return alphabetical sorted unmodifiable list of original register names.
*/
public String[] getRegisterNames();
public List<String> getRegisterNames();
/**
* Get a register given the name of the register
@ -252,19 +252,19 @@ public interface Language {
public Register getProgramCounter();
/**
* Returns context base register or null if one has not been defined by the
* Returns processor context base register or null if one has not been defined by the
* language.
* @return base context register or null if not defined
*/
public Register getContextBaseRegister();
/**
* Get the unsorted array of Context Register objects that this language defines
* Get an unsorted unmodifiable list of processor context registers that this language defines
* (includes context base register and its context field registers).
*
* @return the array of processor registers.
* @return unmodifiable list of processor registers.
*/
public Register[] getContextRegisters();
public List<Register> getContextRegisters();
/**
* Returns the default memory blocks for this language.
@ -412,9 +412,9 @@ public interface Language {
public Exception getManualException();
/**
* Returns the array of vector registers, sorted first by size and then by name.
* @return sorted array of vector registers.
* Returns an unmodifiable list of vector registers, sorted first by size and then by name.
* @return unmodifiable list of vector registers.
*/
public Register[] getSortedVectorRegisters();
public List<Register> getSortedVectorRegisters();
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,8 +16,7 @@
package ghidra.program.model.lang;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* An implementation of processor context which contains the state of all
@ -29,47 +27,41 @@ import java.util.Map;
*/
public final class ProcessorContextImpl implements ProcessorContext {
Map<Register, byte[]> values = new HashMap<Register, byte[]>();
Register[] registers;
Register baseContextRegister;
Language language;
public ProcessorContextImpl(ProcessorContext context) {
this(context.getRegisters());
for (Register register : registers) {
if (!register.isBaseRegister()) {
continue;
}
if (register.isProcessorContext()) {
baseContextRegister = register;
}
RegisterValue value = context.getRegisterValue(register);
if (value != null) {
setRegisterValue(value);
}
}
}
// public ProcessorContextImpl(ProcessorContext context) {
// this(context.getRegisters());
// for (Register register : registers) {
// if (!register.isBaseRegister()) {
// continue;
// }
// if (register.isProcessorContext()) {
// baseContextRegister = register;
// }
// RegisterValue value = context.getRegisterValue(register);
// if (value != null) {
// setRegisterValue(value);
// }
// }
// }
public ProcessorContextImpl(Register[] registers) {
this.registers = registers;
public ProcessorContextImpl(Language language) {
this.language = language;
}
@Override
public Register getBaseContextRegister() {
return baseContextRegister;
return language.getContextBaseRegister();
}
@Override
public Register getRegister(String name) {
for (Register register : registers) {
if (register.getName().equals(name)) {
return register;
}
}
return null;
return language.getRegister(name);
}
@Override
public Register[] getRegisters() {
return registers;
public List<Register> getRegisters() {
return language.getRegisters();
}
@Override

View file

@ -16,6 +16,7 @@
package ghidra.program.model.lang;
import java.math.BigInteger;
import java.util.List;
/**
* Defines the interface for an object containing the state
@ -30,10 +31,10 @@ public interface ProcessorContextView {
public Register getBaseContextRegister();
/**
* Returns all the Registers for the processor
* Returns all the Registers for the processor as an unmodifiable list
* @return all the Registers for the processor
*/
public Register[] getRegisters();
public List<Register> getRegisters();
/**
* Get a Register given the name of a register

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,12 +15,13 @@
*/
package ghidra.program.model.lang;
import java.math.BigInteger;
import java.util.List;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.ContextChangeException;
import ghidra.program.model.listing.ProgramContext;
import java.math.BigInteger;
/**
* Implementation for the program processor context interface
*/
@ -45,17 +45,11 @@ public class ProgramProcessorContext implements ProcessorContext {
return context.getBaseContextRegister();
}
/**
* @see ghidra.program.model.lang.ProcessorContext#getRegisters()
*/
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return context.getRegisters();
}
/**
* @see ghidra.program.model.lang.ProcessorContext#getRegister(java.lang.String)
*/
@Override
public Register getRegister(String name) {
return context.getRegister(name);
@ -71,10 +65,6 @@ public class ProgramProcessorContext implements ProcessorContext {
return context.getRegisterValue(register, addr);
}
/**
* @throws ContextChangeException
* @see ghidra.program.model.lang.ProcessorContext#setValue(ghidra.program.model.lang.Register, java.math.BigInteger)
*/
@Override
public void setValue(Register register, BigInteger value) throws ContextChangeException {
context.setValue(register, addr, addr, value);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,6 +21,7 @@ package ghidra.program.model.lang;
*/
import java.math.BigInteger;
import java.util.List;
public class ReadOnlyProcessorContext implements ProcessorContext {
@ -42,7 +42,7 @@ public class ReadOnlyProcessorContext implements ProcessorContext {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return context.getRegisters();
}

View file

@ -89,11 +89,15 @@ public class RegisterBuilder {
return contextAddress;
}
/**
* Compute current register collection and instantiate a {@link RegisterManager}
* @return new register manager instance
*/
public RegisterManager getRegisterManager() {
return new RegisterManager(computeRegisters(), Collections.unmodifiableMap(registerMap));
return new RegisterManager(computeRegisters(), registerMap);
}
private Register[] computeRegisters() {
private List<Register> computeRegisters() {
List<Register> regList = new LinkedList<>();
List<Register> unprocessed = new LinkedList<>(registerList);
@ -115,8 +119,7 @@ public class RegisterBuilder {
}
bitSize = nextLargerSize;
}
return registerList.toArray(new Register[registerList.size()]);
return registerList;
}
private Register[] getChildren(Register parent, List<Register> regList) {

View file

@ -22,18 +22,19 @@ import ghidra.program.model.address.OldGenericNamespaceAddress;
public class RegisterManager {
Register[] registers;
Map<String, Register> registerNameMap = new HashMap<String, Register>(); // include aliases and case-variations
private List<Register> registers;
private Map<String, Register> registerNameMap = new HashMap<String, Register>(); // include aliases and case-variations
String[] registerNames; // excludes aliases
Register[] contextRegisters;
Register contextBaseRegister;
private List<String> registerNames; // alphabetical sorted list, excludes aliases
private List<Register> contextRegisters;
private Register contextBaseRegister;
Map<RegisterSizeKey, Register> sizeMap = new HashMap<RegisterSizeKey, Register>();
Map<Address, List<Register>> registerAddressMap = new HashMap<Address, List<Register>>();
private Map<RegisterSizeKey, Register> sizeMap = new HashMap<RegisterSizeKey, Register>();
private Map<Address, List<Register>> registerAddressMap =
new HashMap<Address, List<Register>>();
/**Collection of vector registers, sorted first by size and then by offset**/
private TreeSet<Register> sortedVectorRegisters;
/**List of vector registers, sorted first by size and then by offset**/
private List<Register> sortedVectorRegisters;
class RegisterSizeKey {
Address address;
@ -85,16 +86,16 @@ public class RegisterManager {
* @param registerNameMap a complete name-to-register map including all register aliases
* and alternate spellings (e.g., case-variations)
*/
RegisterManager(Register[] cookedRegisters, Map<String, Register> registerNameMap) {
registers = cookedRegisters;
this.registerNameMap = registerNameMap;
RegisterManager(List<Register> cookedRegisters, Map<String, Register> registerNameMap) {
this.registers = Collections.unmodifiableList(cookedRegisters);
this.registerNameMap = Collections.unmodifiableMap(registerNameMap);
initialize();
}
private void initialize() {
List<String> registerNameList = new ArrayList<String>();
List<Register> contextRegisterList = new ArrayList<Register>();
List<Register> registerList = new ArrayList<Register>(Arrays.asList(registers));
ArrayList<Register> registerList = new ArrayList<>(registers); // copy for sorting
Collections.sort(registerList, registerSizeComparator);
for (Register reg : registerList) {
String regName = reg.getName();
@ -129,8 +130,9 @@ public class RegisterManager {
for (Register register : registerList) {
sizeMap.put(new RegisterSizeKey(register.getAddress(), 0), register);
}
contextRegisters = contextRegisterList.toArray(new Register[contextRegisterList.size()]);
registerNames = registerNameList.toArray(new String[registerNameList.size()]);
contextRegisters = Collections.unmodifiableList(contextRegisterList);
Collections.sort(registerNameList);
registerNames = Collections.unmodifiableList(registerNameList);
}
private void populateSizeMapBigEndian(Register reg) {
@ -157,18 +159,21 @@ public class RegisterManager {
}
/**
* Get unsorted array of all processor context registers (include base context register and children)
* Get unsorted unmodifiable list of all processor context registers (include base context register and children)
* @return all processor context registers
*/
public Register[] getContextRegisters() {
public List<Register> getContextRegisters() {
return contextRegisters;
}
/**
* Get unsorted array of all original register names (exludes aliases)
* @return all register names
* Get an alphabetical sorted unmodifiable list of original register names
* (including context registers). Names correspond to orignal register
* name and not aliases which may be defined.
*
* @return alphabetical sorted unmodifiable list of original register names.
*/
public String[] getRegisterNames() {
public List<String> getRegisterNames() {
return registerNames;
}
@ -234,29 +239,30 @@ public class RegisterManager {
}
/**
* Get all registers. Array returned is not protected and must not be modified
* by caller.
* @return array of all registers defined
* Get all registers as an unsorted unmodifiable list.
* @return unmodifiable list of all registers defined
*/
public Register[] getRegisters() {
public List<Register> getRegisters() {
return registers;
}
/**
* Get all vector registers indentified by processor specification
* in sorted order based upon address and size.
* @return all vector registers
* Get an unmodifiable list of all vector registers indentified by the processor specification
* in sorted order based upon address and size.
* @return all vector registers as unmodifiable list
*/
public Register[] getSortedVectorRegisters() {
public List<Register> getSortedVectorRegisters() {
if (sortedVectorRegisters == null) {
sortedVectorRegisters = new TreeSet<Register>(RegisterManager::compareVectorRegisters);
for (Register reg : getRegisters()) {
ArrayList<Register> list = new ArrayList<Register>();
for (Register reg : registers) {
if (reg.isVectorRegister()) {
sortedVectorRegisters.add(reg);
list.add(reg);
}
}
Collections.sort(list, RegisterManager::compareVectorRegisters);
sortedVectorRegisters = Collections.unmodifiableList(list);
}
return sortedVectorRegisters.toArray(new Register[0]);
return sortedVectorRegisters;
}
/**

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,36 +15,33 @@
*/
package ghidra.program.model.lang;
import ghidra.program.model.address.Address;
import java.util.*;
import ghidra.program.model.address.Address;
public class RegisterTranslator {
private static Comparator<Register> registerSizeComparator = new Comparator<Register>() {
@Override
public int compare(Register r1, Register r2) {
// Used for sorting largest to smallest
return r2.getBitLength() - r1.getBitLength();
}
};
private Register[] oldRegs;
private Register[] newRegs;
private Language oldLang;
private Language newLang;
private HashMap<Integer, List<Register>> oldRegisterMap;
private HashMap<Integer, List<Register>> newRegisterMap;
private HashMap<String, Register> oldRegisterNameMap;
private HashMap<String, Register> newRegisterNameMap;
public RegisterTranslator(Language oldLang, Language newLang) {
oldRegs = oldLang.getRegisters();
newRegs = newLang.getRegisters();
this.oldRegisterMap = buildOffsetMap(oldRegs);
this.newRegisterMap = buildOffsetMap(newRegs);
oldRegisterNameMap = buildNameMap(oldRegs);
newRegisterNameMap = buildNameMap(newRegs);
this.oldLang = oldLang;
this.newLang = newLang;
this.oldRegisterMap = buildOffsetMap(oldLang.getRegisters());
this.newRegisterMap = buildOffsetMap(newLang.getRegisters());
}
private HashMap<Integer, List<Register>> buildOffsetMap(Register[] registers) {
private HashMap<Integer, List<Register>> buildOffsetMap(List<Register> registers) {
HashMap<Integer, List<Register>> offsetMap = new HashMap<Integer, List<Register>>();
for (Register register : registers) {
Address addr = register.getAddress();
@ -69,14 +65,6 @@ public class RegisterTranslator {
return offsetMap;
}
private HashMap<String, Register> buildNameMap(Register[] regs) {
HashMap<String, Register> map = new HashMap<String, Register>();
for (Register r : regs) {
map.put(r.getName().toUpperCase(), r);
}
return map;
}
public Register getOldRegister(int offset, int size) {
List<Register> list = oldRegisterMap.get(offset);
if (list != null) {
@ -110,15 +98,15 @@ public class RegisterTranslator {
}
public Register getNewRegister(Register oldReg) {
return newRegisterNameMap.get(oldReg.getName().toUpperCase());
return newLang.getRegister(oldReg.getName());
}
public Register getOldRegister(Register newReg) {
return oldRegisterNameMap.get(newReg.getName().toUpperCase());
return oldLang.getRegister(newReg.getName());
}
public Register[] getNewRegisters() {
return newRegs;
public List<Register> getNewRegisters() {
return newLang.getRegisters();
}
}

View file

@ -340,7 +340,7 @@ public class InstructionStub implements Instruction {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
throw new UnsupportedOperationException();
}

View file

@ -15,12 +15,13 @@
*/
package ghidra.program.model.listing;
import java.math.BigInteger;
import java.util.List;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import java.math.BigInteger;
/**
* Interface to define a processor register context over the address space.
*/
@ -34,14 +35,14 @@ public interface ProgramContext {
/**
* Modify register value to eliminate non-flowing bits
* @param value
* @param value register value to be modified
* @return value suitable for flowing
*/
public RegisterValue getFlowValue(RegisterValue value);
/**
* Modify register value to only include non-flowing bits
* @param value
* @param value register value to be modified
* @return new value or null
*/
public RegisterValue getNonFlowValue(RegisterValue value);
@ -57,9 +58,9 @@ public interface ProgramContext {
/**
* Get all the register descriptions defined for this program context.
*
* @return array of defined register descriptions
* @return unmodifiable list of defined register descriptions
*/
public Register[] getRegisters();
public List<Register> getRegisters();
/**
* Returns an array of all registers that at least one value associated with an address.
@ -92,6 +93,8 @@ public interface ProgramContext {
* @param start the start address to set values
* @param end the end address to set values
* @param value the actual values to store at address
* @throws ContextChangeException if failed to modifiy context across specified range
* (e.g., instruction exists).
*/
public void setRegisterValue(Address start, Address end, RegisterValue value)
throws ContextChangeException;
@ -112,6 +115,8 @@ public interface ProgramContext {
* @param start the start address.
* @param end the end address (inclusive).
* @param value the value to assign. A value of null will effective clear any existing values.
* @throws ContextChangeException if failed to modifiy context across specified range
* (e.g., instruction exists).
*/
public void setValue(Register register, Address start, Address end, BigInteger value)
throws ContextChangeException;
@ -130,6 +135,8 @@ public interface ProgramContext {
* given range for the given register. Each range returned will have the same value
* associated with the register for all addresses in that range.
* @param register the register for which to get set value ranges.
* @param start start of address range to search
* @param end end of address range to search
* @return An AddressRangeIterator over all address within the given range that have values
* for the given register.
*/
@ -139,8 +146,8 @@ public interface ProgramContext {
/**
* Returns the bounding address-range containing addr and the the same RegisterValue throughout.
* The range returned may be limited by other value changes associated with register's base-register.
* @param register
* @param addr
* @param register program register
* @param addr program address
* @return single register-value address-range containing addr
*/
public AddressRange getRegisterValueRangeContaining(Register register, Address addr);
@ -159,6 +166,8 @@ public interface ProgramContext {
* given range for the given register. Each range returned will have the same default value
* associated with the register for all addresses in that range.
* @param register the register for which to get default value ranges.
* @param start start of address range to search
* @param end end of address range to search
* @return An AddressRangeIterator over all address within the given range that have default values
* for the given register.
*/
@ -169,20 +178,26 @@ public interface ProgramContext {
* Gets the registers for this context that are used for processor context states.
* @return all processor context registers
*/
public Register[] getProcessorStateRegisters();
public List<Register> getContextRegisters();
/**
* Remove (unset) the register values for a given address range.
* @param start starting address.
* @param end ending adddress.
* @param register handle to the register to be set.
* @throws ContextChangeException thrown if context change not permitted over specified
* range (e.g., instructions exist)
*/
public void remove(Address start, Address end, Register register) throws ContextChangeException;
/**
* Returns the list of register names
* Get an alphabetical sorted unmodifiable list of original register names
* (including context registers). Names correspond to orignal register
* name and not aliases which may be defined.
*
* @return alphabetical sorted unmodifiable list of original register names.
*/
public String[] getRegisterNames();
public List<String> getRegisterNames();
/**
* Returns true if the given register has the value over the addressSet
@ -224,7 +239,7 @@ public interface ProgramContext {
* from the default disassembly context and the context register value stored
* at the specified address. Those bits specified by the stored context value
* take precedence.
* @param address
* @param address program address
* @return disassembly context register value
*/
public RegisterValue getDisassemblyContext(Address address);

View file

@ -20,6 +20,8 @@
*/
package ghidra.program.model.pcode;
import java.util.List;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.Program;
@ -50,8 +52,9 @@ public class VarnodeTranslator {
* @return Register or null if node is not a register
*/
public Register getRegister(Varnode node) {
if (node == null)
if (node == null) {
return null;
}
return language.getRegister(node.getAddress(), node.getSize());
}
@ -72,9 +75,9 @@ public class VarnodeTranslator {
* Get all defined registers for the program this translator was created
* with.
*
* @return all defined registers
* @return all defined registers as unmodifiable list
*/
public Register[] getRegisters() {
public List<Register> getRegisters() {
return language.getRegisters();
}
}

View file

@ -16,6 +16,7 @@
package ghidra.program.util;
import java.util.Arrays;
import java.util.List;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.*;
@ -128,7 +129,7 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
}
@Override
public final Register[] getProcessorStateRegisters() {
public final List<Register> getContextRegisters() {
return language.getContextRegisters();
}
@ -138,12 +139,12 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
}
@Override
public final String[] getRegisterNames() {
public final List<String> getRegisterNames() {
return language.getRegisterNames();
}
@Override
public final Register[] getRegisters() {
public final List<Register> getRegisters() {
return language.getRegisters();
}

View file

@ -120,7 +120,7 @@ class OldLanguage implements Language {
}
@Override
public Register[] getContextRegisters() {
public List<Register> getContextRegisters() {
return registerMgr.getContextRegisters();
}
@ -140,12 +140,12 @@ class OldLanguage implements Language {
}
@Override
public Register[] getRegisters() {
public List<Register> getRegisters() {
return registerMgr.getRegisters();
}
@Override
public String[] getRegisterNames() {
public List<String> getRegisterNames() {
return registerMgr.getRegisterNames();
}
@ -747,7 +747,7 @@ class OldLanguage implements Language {
}
@Override
public Register[] getSortedVectorRegisters() {
public List<Register> getSortedVectorRegisters() {
throw new UnsupportedOperationException(
"Language for upgrade use only (getSortedVectorRegisters)");
}

View file

@ -270,7 +270,6 @@ public class OldLanguageFactory {
private static Element getRegistersElement(Language lang) {
Register[] registers = lang.getRegisters();
Register contextReg = lang.getContextBaseRegister();
Element registersElement = new Element("registers");
if (contextReg != null) {
@ -292,7 +291,7 @@ public class OldLanguageFactory {
}
registersElement.addContent(ctxElement);
}
for (Register reg : registers) {
for (Register reg : lang.getRegisters()) {
if (!reg.getBaseRegister().isProcessorContext()) {
Element regElement = getRegisterElement(reg);
registersElement.addContent(regElement);