mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-38 Refactored language/context related APIs to return unmodifiable
lists instead of arrays for some register related methods
This commit is contained in:
parent
0386895578
commit
e39b2e9ea9
43 changed files with 346 additions and 389 deletions
|
@ -219,8 +219,7 @@ public class BuildResultState extends GhidraScript {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
Register[] regs = currentProgram.getLanguage().getRegisters();
|
List<Register> registers = currentProgram.getLanguage().getRegisters();
|
||||||
List<Register> registers = Arrays.asList(regs);
|
|
||||||
try {
|
try {
|
||||||
Register reg = askChoice("Results Query", "Select Register:", registers, null);
|
Register reg = askChoice("Results Query", "Select Register:", registers, null);
|
||||||
while (reg != null) {
|
while (reg != null) {
|
||||||
|
|
|
@ -31,7 +31,6 @@ import ghidra.program.util.SymbolicPropogator.Value;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CallDepthChangeInfo.java
|
* CallDepthChangeInfo.java
|
||||||
|
@ -89,7 +88,7 @@ public class CallDepthChangeInfo {
|
||||||
this.program = func.getProgram();
|
this.program = func.getProgram();
|
||||||
frameReg = program.getCompilerSpec().getStackPointer();
|
frameReg = program.getCompilerSpec().getStackPointer();
|
||||||
try {
|
try {
|
||||||
initialize(func, func.getBody(), frameReg, TaskMonitorAdapter.DUMMY_MONITOR);
|
initialize(func, func.getBody(), frameReg, TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
throw new RuntimeException("Unexpected Exception", e);
|
throw new RuntimeException("Unexpected Exception", e);
|
||||||
|
@ -532,7 +531,7 @@ public class CallDepthChangeInfo {
|
||||||
st.push(func.getEntryPoint());
|
st.push(func.getEntryPoint());
|
||||||
st.push(new Integer(0));
|
st.push(new Integer(0));
|
||||||
st.push(Boolean.TRUE);
|
st.push(Boolean.TRUE);
|
||||||
ProcessorContextImpl procContext = new ProcessorContextImpl(trans.getRegisters());
|
ProcessorContextImpl procContext = new ProcessorContextImpl(program.getLanguage());
|
||||||
|
|
||||||
AddressSet undone = new AddressSet(func.getBody());
|
AddressSet undone = new AddressSet(func.getBody());
|
||||||
AddressSet badStackSet = new AddressSet(undone);
|
AddressSet badStackSet = new AddressSet(undone);
|
||||||
|
@ -903,9 +902,9 @@ public class CallDepthChangeInfo {
|
||||||
|
|
||||||
Stack<Object> st = new Stack<Object>();
|
Stack<Object> st = new Stack<Object>();
|
||||||
st.push(func.getEntryPoint());
|
st.push(func.getEntryPoint());
|
||||||
st.push(new Integer(0));
|
st.push(Integer.valueOf(0));
|
||||||
st.push(Boolean.TRUE);
|
st.push(Boolean.TRUE);
|
||||||
ProcessorContextImpl procContext = new ProcessorContextImpl(trans.getRegisters());
|
ProcessorContextImpl procContext = new ProcessorContextImpl(program.getLanguage());
|
||||||
|
|
||||||
AddressSet undone = new AddressSet(func.getBody());
|
AddressSet undone = new AddressSet(func.getBody());
|
||||||
AddressSet badStackSet = new AddressSet(undone);
|
AddressSet badStackSet = new AddressSet(undone);
|
||||||
|
@ -955,7 +954,7 @@ public class CallDepthChangeInfo {
|
||||||
Address[] flows = instr.getFlows();
|
Address[] flows = instr.getFlows();
|
||||||
for (Address flow2 : flows) {
|
for (Address flow2 : flows) {
|
||||||
st.push(flow2);
|
st.push(flow2);
|
||||||
st.push(new Integer(stackPointerDepth));
|
st.push(Integer.valueOf(stackPointerDepth));
|
||||||
st.push(stackOK);
|
st.push(stackOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -16,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.merge.listing;
|
package ghidra.app.merge.listing;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.merge.MergeResolver;
|
import ghidra.app.merge.MergeResolver;
|
||||||
import ghidra.app.merge.ProgramMultiUserMergeManager;
|
import ghidra.app.merge.ProgramMultiUserMergeManager;
|
||||||
import ghidra.app.merge.tool.ListingMergePanel;
|
import ghidra.app.merge.tool.ListingMergePanel;
|
||||||
|
@ -27,9 +28,6 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>ProgramContextMergeManager</code> merges register value changes
|
* <code>ProgramContextMergeManager</code> merges register value changes
|
||||||
* for multi-user program versions. It merges changes for each named register
|
* for multi-user program versions. It merges changes for each named register
|
||||||
|
@ -70,7 +68,7 @@ public class ProgramContextMergeManager implements MergeResolver, ListingMergeCo
|
||||||
ProgramContext latestContext;
|
ProgramContext latestContext;
|
||||||
ProgramContext myContext;
|
ProgramContext myContext;
|
||||||
ProgramContext resultContext;
|
ProgramContext resultContext;
|
||||||
Register[] registers;
|
List<Register> registers;
|
||||||
|
|
||||||
/** Used to determine differences between the original program and latest program. */
|
/** Used to determine differences between the original program and latest program. */
|
||||||
ProgramDiff diffOriginalLatest;
|
ProgramDiff diffOriginalLatest;
|
||||||
|
@ -187,21 +185,19 @@ public class ProgramContextMergeManager implements MergeResolver, ListingMergeCo
|
||||||
mergePanel.setTopComponent(conflictInfoPanel);
|
mergePanel.setTopComponent(conflictInfoPanel);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String[] latestNames = latestContext.getRegisterNames();
|
List<String> latestNames = latestContext.getRegisterNames();
|
||||||
String[] myNames = myContext.getRegisterNames();
|
List<String> myNames = myContext.getRegisterNames();
|
||||||
Arrays.sort(latestNames);
|
if (!latestNames.equals(myNames)) {
|
||||||
Arrays.sort(myNames);
|
|
||||||
if (!Arrays.equals(latestNames, myNames)) {
|
|
||||||
mergeManager.setStatusText("Program Context Registers don't match between the programs.");
|
mergeManager.setStatusText("Program Context Registers don't match between the programs.");
|
||||||
cancel();
|
cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Register[] regs = latestContext.getRegisters();
|
ArrayList<Register> regs = new ArrayList<>(latestContext.getRegisters());
|
||||||
// Sort the registers by size so that largest come first.
|
// Sort the registers by size so that largest come first.
|
||||||
// This prevents the remove call below from incorrectly clearing
|
// This prevents the remove call below from incorrectly clearing
|
||||||
// smaller registers that are part of a larger register.
|
// smaller registers that are part of a larger register.
|
||||||
Arrays.sort(regs, new Comparator<Register>() {
|
Collections.sort(regs, new Comparator<Register>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(Register r1, Register r2) {
|
public int compare(Register r1, Register r2) {
|
||||||
return r2.getBitLength() - r1.getBitLength();
|
return r2.getBitLength() - r1.getBitLength();
|
||||||
|
@ -211,15 +207,16 @@ public class ProgramContextMergeManager implements MergeResolver, ListingMergeCo
|
||||||
int transactionID = resultPgm.startTransaction(getDescription());
|
int transactionID = resultPgm.startTransaction(getDescription());
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
try {
|
try {
|
||||||
int numRegs = regs.length;
|
int numRegs = regs.size();
|
||||||
monitor.initialize(numRegs);
|
monitor.initialize(numRegs);
|
||||||
|
|
||||||
// Get the conflicts for each register
|
// Get the conflicts for each register
|
||||||
for (int i = 0; i < numRegs; i++) {
|
for (int i = 0; i < numRegs; i++) {
|
||||||
if (regs[i].isProcessorContext()) {
|
Register reg = regs.get(i);
|
||||||
|
if (reg.isProcessorContext()) {
|
||||||
continue; // context register handle by code unit merge
|
continue; // context register handle by code unit merge
|
||||||
}
|
}
|
||||||
String regName = regs[i].getName();
|
String regName = reg.getName();
|
||||||
int currentProgressPercentage = (int) (((float) 100 / numRegs) * i);
|
int currentProgressPercentage = (int) (((float) 100 / numRegs) * i);
|
||||||
mergeManager.updateProgress(currentProgressPercentage,
|
mergeManager.updateProgress(currentProgressPercentage,
|
||||||
"Merging register values for " + regName);
|
"Merging register values for " + regName);
|
||||||
|
|
|
@ -47,9 +47,9 @@ public class ProcessorStateDialog extends DialogComponentProvider {
|
||||||
public ProcessorStateDialog(ProgramContext programContext) {
|
public ProcessorStateDialog(ProgramContext programContext) {
|
||||||
super(TITLE, true, false, true, false);
|
super(TITLE, true, false, true, false);
|
||||||
this.programContext = programContext;
|
this.programContext = programContext;
|
||||||
Register[] contextRegisters = programContext.getProcessorStateRegisters();
|
|
||||||
registerList = new ArrayList<>();
|
registerList = new ArrayList<>();
|
||||||
for (Register register : contextRegisters) {
|
for (Register register : programContext.getContextRegisters()) {
|
||||||
if (!register.isBaseRegister()) {
|
if (!register.isBaseRegister()) {
|
||||||
registerList.add(register);
|
registerList.add(register);
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,8 +172,8 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE
|
||||||
|
|
||||||
private Component createRegisterCombo(VarnodeInfo varnode) {
|
private Component createRegisterCombo(VarnodeInfo varnode) {
|
||||||
ProgramContext programContext = program.getProgramContext();
|
ProgramContext programContext = program.getProgramContext();
|
||||||
Register[] contextRegisters = programContext.getRegisters();
|
|
||||||
List<Register> validItems = new ArrayList<>(Arrays.asList(contextRegisters));
|
List<Register> validItems = new ArrayList<>(programContext.getRegisters());
|
||||||
|
|
||||||
for (Iterator<Register> iter = validItems.iterator(); iter.hasNext();) {
|
for (Iterator<Register> iter = validItems.iterator(); iter.hasNext();) {
|
||||||
Register register = iter.next();
|
Register register = iter.next();
|
||||||
|
|
|
@ -186,7 +186,7 @@ public class RegisterFieldFactory extends FieldFactory {
|
||||||
private List<Register> getSetRegisters(Function function) {
|
private List<Register> getSetRegisters(Function function) {
|
||||||
Program program = function.getProgram();
|
Program program = function.getProgram();
|
||||||
ProgramContext programContext = program.getProgramContext();
|
ProgramContext programContext = program.getProgramContext();
|
||||||
Register[] registers = programContext.getRegisters();
|
Register[] registers = programContext.getRegistersWithValues();
|
||||||
Address address = function.getEntryPoint();
|
Address address = function.getEntryPoint();
|
||||||
List<Register> setRegisters = new ArrayList<>();
|
List<Register> setRegisters = new ArrayList<>();
|
||||||
for (Register register : registers) {
|
for (Register register : registers) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -16,21 +15,23 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.xml;
|
package ghidra.app.util.xml;
|
||||||
|
|
||||||
import ghidra.app.util.importer.*;
|
import java.io.IOException;
|
||||||
import ghidra.program.model.address.*;
|
import java.math.BigInteger;
|
||||||
import ghidra.program.model.lang.*;
|
|
||||||
import ghidra.program.model.listing.*;
|
|
||||||
import ghidra.util.*;
|
|
||||||
import ghidra.util.exception.*;
|
|
||||||
import ghidra.util.task.*;
|
|
||||||
import ghidra.util.xml.*;
|
|
||||||
import ghidra.xml.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.xml.sax.*;
|
import org.xml.sax.SAXParseException;
|
||||||
|
|
||||||
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.listing.ProgramContext;
|
||||||
|
import ghidra.util.XmlProgramUtilities;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
import ghidra.util.xml.*;
|
||||||
|
import ghidra.xml.XmlElement;
|
||||||
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML manager for register values.
|
* XML manager for register values.
|
||||||
|
@ -87,10 +88,11 @@ class RegisterValuesXmlMgr {
|
||||||
* Returns list of unique registers which do not overlap any smaller
|
* Returns list of unique registers which do not overlap any smaller
|
||||||
* registers.
|
* registers.
|
||||||
*/
|
*/
|
||||||
private Register[] getUniqueRegisters() {
|
private List<Register> getUniqueRegisters() {
|
||||||
|
|
||||||
Register[] regs = context.getRegisters();
|
ArrayList<Register> regs = new ArrayList<>(context.getRegisters());
|
||||||
Arrays.sort(regs, new Comparator<Register>() {
|
Collections.sort(regs, new Comparator<Register>() {
|
||||||
|
@Override
|
||||||
public int compare(Register r1, Register r2) {
|
public int compare(Register r1, Register r2) {
|
||||||
int size1 = r1.getMinimumByteSize();
|
int size1 = r1.getMinimumByteSize();
|
||||||
int size2 = r2.getMinimumByteSize();
|
int size2 = r2.getMinimumByteSize();
|
||||||
|
@ -140,7 +142,7 @@ class RegisterValuesXmlMgr {
|
||||||
|
|
||||||
writer.startElement("REGISTER_VALUES");
|
writer.startElement("REGISTER_VALUES");
|
||||||
|
|
||||||
Register[] regs = getUniqueRegisters();
|
List<Register> regs = getUniqueRegisters();
|
||||||
|
|
||||||
//for (int i = 0; i < regs.length; i++) {
|
//for (int i = 0; i < regs.length; i++) {
|
||||||
//Register reg = regs[i];
|
//Register reg = regs[i];
|
||||||
|
@ -156,8 +158,7 @@ class RegisterValuesXmlMgr {
|
||||||
|
|
||||||
AddressRange range = rangeIter.next();
|
AddressRange range = rangeIter.next();
|
||||||
|
|
||||||
for (int i = 0; i < regs.length; i++) {
|
for (Register reg : regs) {
|
||||||
Register reg = regs[i];
|
|
||||||
AddressRangeIterator it = context.getRegisterValueAddressRanges(reg, range.getMinAddress(), range.getMaxAddress());
|
AddressRangeIterator it = context.getRegisterValueAddressRanges(reg, range.getMinAddress(), range.getMaxAddress());
|
||||||
while(it.hasNext()) {
|
while(it.hasNext()) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
|
|
|
@ -1156,13 +1156,8 @@ public class ProgramDiff {
|
||||||
private AddressSet getProgramContextDifferences(AddressSetView addressSet, TaskMonitor monitor)
|
private AddressSet getProgramContextDifferences(AddressSetView addressSet, TaskMonitor monitor)
|
||||||
throws ProgramConflictException, CancelledException {
|
throws ProgramConflictException, CancelledException {
|
||||||
AddressSet differences = new AddressSet();
|
AddressSet differences = new AddressSet();
|
||||||
ProgramContext pc1 = program1.getProgramContext();
|
|
||||||
ProgramContext pc2 = program2.getProgramContext();
|
if (!ProgramMemoryComparator.sameProgramContextRegisterNames(program1, program2)) {
|
||||||
String[] names1 = pc1.getRegisterNames();
|
|
||||||
String[] names2 = pc2.getRegisterNames();
|
|
||||||
Arrays.sort(names1);
|
|
||||||
Arrays.sort(names2);
|
|
||||||
if (!Arrays.equals(names1, names2)) {
|
|
||||||
throw new ProgramConflictException(
|
throw new ProgramConflictException(
|
||||||
"Program Context Registers don't match between the programs.");
|
"Program Context Registers don't match between the programs.");
|
||||||
}
|
}
|
||||||
|
@ -1171,7 +1166,10 @@ public class ProgramDiff {
|
||||||
AddressSet inCommon = pgmMemComp.getAddressesInCommon();
|
AddressSet inCommon = pgmMemComp.getAddressesInCommon();
|
||||||
addressSet = (addressSet != null) ? inCommon.intersect(addressSet) : inCommon;
|
addressSet = (addressSet != null) ? inCommon.intersect(addressSet) : inCommon;
|
||||||
|
|
||||||
for (String element : names1) {
|
ProgramContext pc1 = program1.getProgramContext();
|
||||||
|
ProgramContext pc2 = program2.getProgramContext();
|
||||||
|
|
||||||
|
for (String element : pc1.getRegisterNames()) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
Register rb1 = pc1.getRegister(element);
|
Register rb1 = pc1.getRegister(element);
|
||||||
Register rb2 = pc2.getRegister(element);
|
Register rb2 = pc2.getRegister(element);
|
||||||
|
|
|
@ -383,9 +383,8 @@ public class ProgramDiffDetails {
|
||||||
l1 = p1.getListing();
|
l1 = p1.getListing();
|
||||||
l2 = p2.getListing();
|
l2 = p2.getListing();
|
||||||
|
|
||||||
Register[] descs1 = p1.getProgramContext().getRegisters();
|
|
||||||
maxRegisterName = "Register".length(); // default name length.
|
maxRegisterName = "Register".length(); // default name length.
|
||||||
for (Register element : descs1) {
|
for (Register element : p1.getProgramContext().getRegisters()) {
|
||||||
maxRegisterName = Math.max(maxRegisterName, element.getName().length());
|
maxRegisterName = Math.max(maxRegisterName, element.getName().length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1285,13 +1284,8 @@ public class ProgramDiffDetails {
|
||||||
* @throws ConcurrentModificationException if analysis is modifying the program context.
|
* @throws ConcurrentModificationException if analysis is modifying the program context.
|
||||||
*/
|
*/
|
||||||
private void addProgramContextDetails() throws ConcurrentModificationException {
|
private void addProgramContextDetails() throws ConcurrentModificationException {
|
||||||
ProgramContext pc1 = p1.getProgramContext();
|
|
||||||
ProgramContext pc2 = p2.getProgramContext();
|
if (!ProgramMemoryComparator.sameProgramContextRegisterNames(p1, p2)) {
|
||||||
String[] names1 = pc1.getRegisterNames();
|
|
||||||
String[] names2 = pc2.getRegisterNames();
|
|
||||||
Arrays.sort(names1);
|
|
||||||
Arrays.sort(names2);
|
|
||||||
if (!Arrays.equals(names1, names2)) {
|
|
||||||
addDiffHeader("Program Context");
|
addDiffHeader("Program Context");
|
||||||
addText(
|
addText(
|
||||||
indent1 + "Program Context Registers don't match between the programs." + newLine);
|
indent1 + "Program Context Registers don't match between the programs." + newLine);
|
||||||
|
@ -1299,8 +1293,9 @@ public class ProgramDiffDetails {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all the register's values and output any differences.
|
// Check all the register's values and output any differences.
|
||||||
Register[] descs1 = pc1.getRegisters();
|
ProgramContext pc1 = p1.getProgramContext();
|
||||||
for (Register reg1 : descs1) {
|
ProgramContext pc2 = p2.getProgramContext();
|
||||||
|
for (Register reg1 : pc1.getRegisters()) {
|
||||||
addRegisterDiffDetails(pc1, pc2, reg1);
|
addRegisterDiffDetails(pc1, pc2, reg1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.util;
|
package ghidra.program.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.listing.ProgramContext;
|
import ghidra.program.model.listing.ProgramContext;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <CODE>ProgramMemoryComparator</CODE> is a class for comparing two programs and
|
* <CODE>ProgramMemoryComparator</CODE> is a class for comparing two programs and
|
||||||
* determining the address differences between them.
|
* determining the address differences between them.
|
||||||
|
@ -120,15 +121,17 @@ public class ProgramMemoryComparator {
|
||||||
* @return true if the programs are alike (their language name or address spaces are the same).
|
* @return true if the programs are alike (their language name or address spaces are the same).
|
||||||
*/
|
*/
|
||||||
public static boolean similarPrograms(Program p1, Program p2) {
|
public static boolean similarPrograms(Program p1, Program p2) {
|
||||||
if (p1 == null || p2 == null)
|
if (p1 == null || p2 == null) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (p1.getLanguageID().equals(p2.getLanguageID())) {
|
if (p1.getLanguageID().equals(p2.getLanguageID())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
AddressSpace[] spaces1 = p1.getLanguage().getAddressFactory().getAddressSpaces();
|
AddressSpace[] spaces1 = p1.getLanguage().getAddressFactory().getAddressSpaces();
|
||||||
AddressSpace[] spaces2 = p2.getLanguage().getAddressFactory().getAddressSpaces();
|
AddressSpace[] spaces2 = p2.getLanguage().getAddressFactory().getAddressSpaces();
|
||||||
if (spaces1.length != spaces2.length)
|
if (spaces1.length != spaces2.length) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
Arrays.sort(spaces1);
|
Arrays.sort(spaces1);
|
||||||
Arrays.sort(spaces2);
|
Arrays.sort(spaces2);
|
||||||
for (int i=0; i<spaces1.length; i++) {
|
for (int i=0; i<spaces1.length; i++) {
|
||||||
|
@ -279,14 +282,9 @@ public class ProgramMemoryComparator {
|
||||||
static public boolean sameProgramContextRegisterNames(Program program1, Program program2) {
|
static public boolean sameProgramContextRegisterNames(Program program1, Program program2) {
|
||||||
ProgramContext pc1 = program1.getProgramContext();
|
ProgramContext pc1 = program1.getProgramContext();
|
||||||
ProgramContext pc2 = program2.getProgramContext();
|
ProgramContext pc2 = program2.getProgramContext();
|
||||||
String[] names1 = pc1.getRegisterNames();
|
List<String> names1 = pc1.getRegisterNames();
|
||||||
String[] names2 = pc2.getRegisterNames();
|
List<String> names2 = pc2.getRegisterNames();
|
||||||
Arrays.sort(names1);
|
return names1.equals(names2);
|
||||||
Arrays.sort(names2);
|
|
||||||
if (!Arrays.equals(names1, names2)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,11 +239,11 @@ public class ProgramMerge implements PropertyVisitor {
|
||||||
|
|
||||||
ProgramContext resultContext = resultProgram.getProgramContext();
|
ProgramContext resultContext = resultProgram.getProgramContext();
|
||||||
ProgramContext originContext = originProgram.getProgramContext();
|
ProgramContext originContext = originProgram.getProgramContext();
|
||||||
Register[] originRegs = originContext.getRegisters();
|
ArrayList<Register> originRegs = new ArrayList<>(originContext.getRegisters());
|
||||||
// Sort the registers by size so that largest come first.
|
// Sort the registers by size so that largest come first.
|
||||||
// This prevents the remove call below from incorrectly clearing
|
// This prevents the remove call below from incorrectly clearing
|
||||||
// smaller registers that are part of a larger register.
|
// smaller registers that are part of a larger register.
|
||||||
Arrays.sort(originRegs, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
|
Collections.sort(originRegs, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
|
||||||
AddressRangeIterator originRangeIter = originAddressSet.getAddressRanges();
|
AddressRangeIterator originRangeIter = originAddressSet.getAddressRanges();
|
||||||
while (originRangeIter.hasNext() && !monitor.isCancelled()) {
|
while (originRangeIter.hasNext() && !monitor.isCancelled()) {
|
||||||
AddressRange originRange = originRangeIter.next();
|
AddressRange originRange = originRangeIter.next();
|
||||||
|
|
|
@ -1389,7 +1389,7 @@ public class VarnodeContext implements ProcessorContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return offsetContext.getRegisters();
|
return offsetContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.viewer.field;
|
package ghidra.app.util.viewer.field;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -106,11 +105,10 @@ public class RegisterFieldFactoryTest extends AbstractGhidraHeadedIntegrationTes
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Register> getNonContextRegisters(ProgramContext pc) {
|
private List<Register> getNonContextRegisters(ProgramContext pc) {
|
||||||
Register[] regs = pc.getRegisters();
|
|
||||||
List<Register> nonContextRegs = new ArrayList<Register>();
|
List<Register> nonContextRegs = new ArrayList<Register>();
|
||||||
for (int i = 0; i < regs.length; i++) {
|
for (Register reg : pc.getRegisters()) {
|
||||||
if (!regs[i].isProcessorContext()) {
|
if (!reg.isProcessorContext()) {
|
||||||
nonContextRegs.add(regs[i]);
|
nonContextRegs.add(reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nonContextRegs;
|
return nonContextRegs;
|
||||||
|
|
|
@ -58,6 +58,21 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
mem = program.getMemory();
|
mem = program.getMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterNameLookup() {
|
||||||
|
ProgramContext programContext = program.getProgramContext();
|
||||||
|
boolean didSomething = false;
|
||||||
|
for (String regName : programContext.getRegisterNames()) {
|
||||||
|
Register reg = programContext.getRegister(regName);
|
||||||
|
assertNotNull(reg);
|
||||||
|
assertEquals(regName, reg.getName());
|
||||||
|
assertTrue(reg == programContext.getRegister(regName.toLowerCase()));
|
||||||
|
assertTrue(reg == programContext.getRegister(regName.toUpperCase()));
|
||||||
|
didSomething = true;
|
||||||
|
}
|
||||||
|
assertTrue(didSomething);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAll() {
|
public void testAll() {
|
||||||
int id = program.startTransaction("Test");
|
int id = program.startTransaction("Test");
|
||||||
|
@ -73,10 +88,7 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramContext programContext = program.getProgramContext();
|
ProgramContext programContext = program.getProgramContext();
|
||||||
Register[] registers = null;
|
boolean didSomething = false;
|
||||||
if (programContext != null) {
|
|
||||||
registers = programContext.getRegisters();
|
|
||||||
}
|
|
||||||
|
|
||||||
Address startAddress = start;
|
Address startAddress = start;
|
||||||
Address endAddress = getAddress(0x30);
|
Address endAddress = getAddress(0x30);
|
||||||
|
@ -84,7 +96,7 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
// stick a value into each one!
|
// stick a value into each one!
|
||||||
BigInteger value = BigInteger.valueOf(255);
|
BigInteger value = BigInteger.valueOf(255);
|
||||||
|
|
||||||
for (Register register : registers) {
|
for (Register register : programContext.getRegisters()) {
|
||||||
Register reg = register;
|
Register reg = register;
|
||||||
if (!reg.isBaseRegister() && reg.isProcessorContext()) {
|
if (!reg.isBaseRegister() && reg.isProcessorContext()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -136,7 +148,9 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
endAddress.getAddressSpace().getMaxAddress()),
|
endAddress.getAddressSpace().getMaxAddress()),
|
||||||
programContext.getRegisterValueRangeContaining(reg, badAddress));
|
programContext.getRegisterValueRangeContaining(reg, badAddress));
|
||||||
|
|
||||||
|
didSomething = true;
|
||||||
}
|
}
|
||||||
|
assertTrue(didSomething);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(id, false);
|
program.endTransaction(id, false);
|
||||||
|
|
|
@ -839,16 +839,13 @@ public class DecompileCallback {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ProgramContext context = program.getProgramContext();
|
ProgramContext context = program.getProgramContext();
|
||||||
Register[] regs = context.getRegisters();
|
|
||||||
if (regs == null || regs.length == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
StringBuilder stringBuf = new StringBuilder();
|
StringBuilder stringBuf = new StringBuilder();
|
||||||
|
|
||||||
stringBuf.append("<tracked_pointset");
|
stringBuf.append("<tracked_pointset");
|
||||||
Varnode.appendSpaceOffset(stringBuf, addr);
|
Varnode.appendSpaceOffset(stringBuf, addr);
|
||||||
stringBuf.append(">\n");
|
stringBuf.append(">\n");
|
||||||
for (Register reg : regs) {
|
for (Register reg : context.getRegisters()) {
|
||||||
if (reg.isProcessorContext()) {
|
if (reg.isProcessorContext()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/address/package.html||GHIDRA||||END|
|
||||||
src/main/java/ghidra/program/model/block/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/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/lang/package.html||GHIDRA||||END|
|
||||||
src/main/java/ghidra/program/model/listing/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|
|
src/main/java/ghidra/program/model/mem/package.html||GHIDRA||||END|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.app.plugin.assembler.sleigh.sem;
|
package ghidra.app.plugin.assembler.sleigh.sem;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.plugin.assembler.sleigh.util.DbgTimer;
|
import ghidra.app.plugin.assembler.sleigh.util.DbgTimer;
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
|
@ -117,7 +118,7 @@ public class AssemblyDefaultContext implements DisassemblerContext, DefaultProgr
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return lang.getRegisters();
|
return lang.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1276,7 +1276,7 @@ public class SleighDebugLogger {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
if (originalContext != null) {
|
if (originalContext != null) {
|
||||||
return originalContext.getRegisters();
|
return originalContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,7 +266,7 @@ public class SleighLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getContextRegisters() {
|
public List<Register> getContextRegisters() {
|
||||||
return getRegisterManager().getContextRegisters();
|
return getRegisterManager().getContextRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,12 +336,12 @@ public class SleighLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return getRegisterManager().getRegisters();
|
return getRegisterManager().getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getRegisterNames() {
|
public List<String> getRegisterNames() {
|
||||||
return getRegisterManager().getRegisterNames();
|
return getRegisterManager().getRegisterNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1080,11 +1080,8 @@ public class SleighLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void xrefRegisters() {
|
private void xrefRegisters() {
|
||||||
Register[] regs = getRegisterManager().getRegisters();
|
for (Register register : getRegisterManager().getContextRegisters()) {
|
||||||
for (Register register : regs) {
|
contextcache.registerVariable(register);
|
||||||
if (register.isProcessorContext()) {
|
|
||||||
contextcache.registerVariable(register);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,7 +1584,7 @@ public class SleighLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getSortedVectorRegisters() {
|
public List<Register> getSortedVectorRegisters() {
|
||||||
return registerManager.getSortedVectorRegisters();
|
return registerManager.getSortedVectorRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.app.util;
|
package ghidra.app.util;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
@ -56,7 +57,7 @@ public class PseudoDisassemblerContext implements DisassemblerContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return disContext.getRegisters();
|
return disContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -548,7 +548,7 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return procContext.getRegisters();
|
return procContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ public class EmulateDisassemblerContext implements DisassemblerContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,7 @@ package ghidra.program.database.code;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
@ -753,7 +752,7 @@ abstract class CodeUnitDB extends DatabaseObject implements CodeUnit, ProcessorC
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return programContext.getRegisters();
|
return programContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.program.database.code;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import db.*;
|
import db.*;
|
||||||
|
@ -130,8 +131,9 @@ class PrototypeManager {
|
||||||
RecordIterator it = contextTable.iterator();
|
RecordIterator it = contextTable.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
monitor.setProgress(++count);
|
monitor.setProgress(++count);
|
||||||
if (monitor.isCancelled())
|
if (monitor.isCancelled()) {
|
||||||
throw new IOException("Upgrade Cancelled");
|
throw new IOException("Upgrade Cancelled");
|
||||||
|
}
|
||||||
Record rec = it.next();
|
Record rec = it.next();
|
||||||
String oldValue = rec.getString(0);
|
String oldValue = rec.getString(0);
|
||||||
rec.setString(0, convertString(oldValue));
|
rec.setString(0, convertString(oldValue));
|
||||||
|
@ -143,8 +145,9 @@ class PrototypeManager {
|
||||||
it = tempTable.iterator();
|
it = tempTable.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
monitor.setProgress(++count);
|
monitor.setProgress(++count);
|
||||||
if (monitor.isCancelled())
|
if (monitor.isCancelled()) {
|
||||||
throw new IOException("Upgrade Cancelled");
|
throw new IOException("Upgrade Cancelled");
|
||||||
|
}
|
||||||
Record rec = it.next();
|
Record rec = it.next();
|
||||||
contextTable.putRecord(rec);
|
contextTable.putRecord(rec);
|
||||||
}
|
}
|
||||||
|
@ -187,8 +190,9 @@ class PrototypeManager {
|
||||||
RecordIterator it = protoAdapter.getRecords();
|
RecordIterator it = protoAdapter.getRecords();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
monitor.setProgress(++count);
|
monitor.setProgress(++count);
|
||||||
if (monitor.isCancelled())
|
if (monitor.isCancelled()) {
|
||||||
throw new IOException("Upgrade Cancelled");
|
throw new IOException("Upgrade Cancelled");
|
||||||
|
}
|
||||||
Record rec = it.next();
|
Record rec = it.next();
|
||||||
tempAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
|
tempAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
|
||||||
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
|
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
|
||||||
|
@ -201,8 +205,9 @@ class PrototypeManager {
|
||||||
it = tempAdapter.getRecords();
|
it = tempAdapter.getRecords();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
monitor.setProgress(++count);
|
monitor.setProgress(++count);
|
||||||
if (monitor.isCancelled())
|
if (monitor.isCancelled()) {
|
||||||
throw new IOException("Upgrade Cancelled");
|
throw new IOException("Upgrade Cancelled");
|
||||||
|
}
|
||||||
Record rec = it.next();
|
Record rec = it.next();
|
||||||
protoAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
|
protoAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
|
||||||
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
|
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
|
||||||
|
@ -287,19 +292,10 @@ class PrototypeManager {
|
||||||
return 0;
|
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.
|
* Get the prototype with the given ID.
|
||||||
|
* @param protoID prototype ID
|
||||||
|
* @return instruction prototype or null if not found
|
||||||
*/
|
*/
|
||||||
InstructionPrototype getPrototype(int protoID) {
|
InstructionPrototype getPrototype(int protoID) {
|
||||||
if (protoID < 0) {
|
if (protoID < 0) {
|
||||||
|
@ -449,25 +445,16 @@ class PrototypeManager {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.lang.ProcessorContext#getRegister(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Register getRegister(String name) {
|
public Register getRegister(String name) {
|
||||||
return programContext.getRegister(name);
|
return programContext.getRegister(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.lang.ProcessorContext#getRegisters()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return programContext.getRegisters();
|
return programContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.lang.ProcessorContext#hasValue(ghidra.program.model.lang.Register)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasValue(Register register) {
|
public boolean hasValue(Register register) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -49,16 +49,14 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||||
|
|
||||||
private DBHandle dbHandle;
|
private DBHandle dbHandle;
|
||||||
private ErrorHandler errHandler;
|
private ErrorHandler errHandler;
|
||||||
private Register[] registers;
|
private Language language;
|
||||||
private AddressMap addrMap;
|
private AddressMap addrMap;
|
||||||
private int registerSpaceSize;
|
|
||||||
private Lock lock;
|
private Lock lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* maintain values stored in registers for specified addresses and
|
* maintain values stored in registers for specified addresses and
|
||||||
* address ranges using the PropertyMap utilities.
|
* address ranges using the PropertyMap utilities.
|
||||||
*/
|
*/
|
||||||
private HashMap<String, Register> registersMap;
|
|
||||||
private Map<Integer, AddressRangeMapDB> valueMaps;
|
private Map<Integer, AddressRangeMapDB> valueMaps;
|
||||||
private Register baseContextRegister;
|
private Register baseContextRegister;
|
||||||
protected Map<Register, RegisterValueStore> defaultRegisterValueMap;
|
protected Map<Register, RegisterValueStore> defaultRegisterValueMap;
|
||||||
|
@ -82,28 +80,12 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||||
this.errHandler = errHandler;
|
this.errHandler = errHandler;
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
this.addrMap = addrMap.getOldAddressMap();
|
this.addrMap = addrMap.getOldAddressMap();
|
||||||
this.registers = language.getRegisters();
|
this.language = language;
|
||||||
|
|
||||||
defaultRegisterValueMap = new HashMap<Register, RegisterValueStore>();
|
defaultRegisterValueMap = new HashMap<Register, RegisterValueStore>();
|
||||||
|
|
||||||
registersMap = new HashMap<String, Register>();
|
|
||||||
valueMaps = new HashMap<>();
|
valueMaps = new HashMap<>();
|
||||||
registerSpaceSize = 0;
|
|
||||||
|
|
||||||
for (Register register : registers) {
|
baseContextRegister = language.getContextBaseRegister();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (baseContextRegister == null) {
|
if (baseContextRegister == null) {
|
||||||
baseContextRegister =
|
baseContextRegister =
|
||||||
new Register("DEFAULT_CONTEXT", "DEFAULT_CONTEXT",
|
new Register("DEFAULT_CONTEXT", "DEFAULT_CONTEXT",
|
||||||
|
@ -186,28 +168,18 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getProcessorStateRegisters() {
|
public List<Register> getContextRegisters() {
|
||||||
List<Register> list = new ArrayList<Register>();
|
return language.getContextRegisters();
|
||||||
for (Register register : registers) {
|
|
||||||
if (register.isProcessorContext()) {
|
|
||||||
list.add(register);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list.toArray(new Register[list.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register getRegister(String name) {
|
public Register getRegister(String name) {
|
||||||
return registersMap.get(name.toUpperCase());
|
return language.getRegister(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getRegisterNames() {
|
public List<String> getRegisterNames() {
|
||||||
List<String> list = new ArrayList<String>();
|
return language.getRegisterNames();
|
||||||
for (Register register : registers) {
|
|
||||||
list.add(register.getName());
|
|
||||||
}
|
|
||||||
return list.toArray(new String[list.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -273,8 +245,8 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return registers;
|
return language.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSigned(Address addr, Register reg) throws UnsupportedOperationException {
|
public long getSigned(Address addr, Register reg) throws UnsupportedOperationException {
|
||||||
|
@ -446,7 +418,7 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||||
public Register[] getRegistersWithValues() {
|
public Register[] getRegistersWithValues() {
|
||||||
if (registersWithValues == null) {
|
if (registersWithValues == null) {
|
||||||
List<Register> tmp = new ArrayList<Register>();
|
List<Register> tmp = new ArrayList<Register>();
|
||||||
for (Register register : registers) {
|
for (Register register : getRegisters()) {
|
||||||
AddressRangeIterator it = getRegisterValueAddressRanges(register);
|
AddressRangeIterator it = getRegisterValueAddressRanges(register);
|
||||||
if (it.hasNext()) {
|
if (it.hasNext()) {
|
||||||
tmp.add(register);
|
tmp.add(register);
|
||||||
|
|
|
@ -17,8 +17,7 @@ package ghidra.program.database.register;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import db.*;
|
import db.*;
|
||||||
import db.util.ErrorHandler;
|
import db.util.ErrorHandler;
|
||||||
|
@ -326,8 +325,8 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||||
// Sort the registers by size so that largest come first.
|
// Sort the registers by size so that largest come first.
|
||||||
// This prevents the remove call below from incorrectly clearing
|
// This prevents the remove call below from incorrectly clearing
|
||||||
// smaller registers that are part of a larger register.
|
// smaller registers that are part of a larger register.
|
||||||
Register[] registers = language.getRegisters().clone();
|
List<Register> registers = new ArrayList<Register>(language.getRegisters());
|
||||||
Arrays.sort(registers, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
|
Collections.sort(registers, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
|
||||||
|
|
||||||
// Map all register stores to new registers
|
// Map all register stores to new registers
|
||||||
for (Register register : registers) {
|
for (Register register : registers) {
|
||||||
|
|
|
@ -1727,7 +1727,7 @@ public class Disassembler implements DisassemblerConflictHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return langauge.getRegisters();
|
return langauge.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -566,7 +566,7 @@ public class DisassemblerContextImpl implements DisassemblerContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return programContext.getRegisters();
|
return programContext.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,21 +206,21 @@ public interface Language {
|
||||||
public Register getRegister(AddressSpace addrspc, long offset, int size);
|
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).
|
* (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
|
* (including context registers). Names correspond to orignal register
|
||||||
* name and not aliases which may be defined.
|
* 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
|
* Get a register given the name of the register
|
||||||
|
@ -252,19 +252,19 @@ public interface Language {
|
||||||
public Register getProgramCounter();
|
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.
|
* language.
|
||||||
* @return base context register or null if not defined
|
* @return base context register or null if not defined
|
||||||
*/
|
*/
|
||||||
public Register getContextBaseRegister();
|
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).
|
* (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.
|
* Returns the default memory blocks for this language.
|
||||||
|
@ -412,9 +412,9 @@ public interface Language {
|
||||||
public Exception getManualException();
|
public Exception getManualException();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the array of vector registers, sorted first by size and then by name.
|
* Returns an unmodifiable list of vector registers, sorted first by size and then by name.
|
||||||
* @return sorted array of vector registers.
|
* @return unmodifiable list of vector registers.
|
||||||
*/
|
*/
|
||||||
public Register[] getSortedVectorRegisters();
|
public List<Register> getSortedVectorRegisters();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -17,8 +16,7 @@
|
||||||
package ghidra.program.model.lang;
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of processor context which contains the state of all
|
* 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 {
|
public final class ProcessorContextImpl implements ProcessorContext {
|
||||||
Map<Register, byte[]> values = new HashMap<Register, byte[]>();
|
Map<Register, byte[]> values = new HashMap<Register, byte[]>();
|
||||||
Register[] registers;
|
Language language;
|
||||||
Register baseContextRegister;
|
|
||||||
|
|
||||||
public ProcessorContextImpl(ProcessorContext context) {
|
// public ProcessorContextImpl(ProcessorContext context) {
|
||||||
this(context.getRegisters());
|
// this(context.getRegisters());
|
||||||
for (Register register : registers) {
|
// for (Register register : registers) {
|
||||||
if (!register.isBaseRegister()) {
|
// if (!register.isBaseRegister()) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
if (register.isProcessorContext()) {
|
// if (register.isProcessorContext()) {
|
||||||
baseContextRegister = register;
|
// baseContextRegister = register;
|
||||||
}
|
// }
|
||||||
RegisterValue value = context.getRegisterValue(register);
|
// RegisterValue value = context.getRegisterValue(register);
|
||||||
if (value != null) {
|
// if (value != null) {
|
||||||
setRegisterValue(value);
|
// setRegisterValue(value);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public ProcessorContextImpl(Register[] registers) {
|
public ProcessorContextImpl(Language language) {
|
||||||
this.registers = registers;
|
this.language = language;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register getBaseContextRegister() {
|
public Register getBaseContextRegister() {
|
||||||
return baseContextRegister;
|
return language.getContextBaseRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register getRegister(String name) {
|
public Register getRegister(String name) {
|
||||||
for (Register register : registers) {
|
return language.getRegister(name);
|
||||||
if (register.getName().equals(name)) {
|
|
||||||
return register;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return registers;
|
return language.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.program.model.lang;
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the interface for an object containing the state
|
* Defines the interface for an object containing the state
|
||||||
|
@ -30,10 +31,10 @@ public interface ProcessorContextView {
|
||||||
public Register getBaseContextRegister();
|
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
|
* @return all the Registers for the processor
|
||||||
*/
|
*/
|
||||||
public Register[] getRegisters();
|
public List<Register> getRegisters();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a Register given the name of a register
|
* Get a Register given the name of a register
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -16,12 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.lang;
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.ContextChangeException;
|
import ghidra.program.model.listing.ContextChangeException;
|
||||||
import ghidra.program.model.listing.ProgramContext;
|
import ghidra.program.model.listing.ProgramContext;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for the program processor context interface
|
* Implementation for the program processor context interface
|
||||||
*/
|
*/
|
||||||
|
@ -45,17 +45,11 @@ public class ProgramProcessorContext implements ProcessorContext {
|
||||||
return context.getBaseContextRegister();
|
return context.getBaseContextRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.lang.ProcessorContext#getRegisters()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return context.getRegisters();
|
return context.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.lang.ProcessorContext#getRegister(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Register getRegister(String name) {
|
public Register getRegister(String name) {
|
||||||
return context.getRegister(name);
|
return context.getRegister(name);
|
||||||
|
@ -71,10 +65,6 @@ public class ProgramProcessorContext implements ProcessorContext {
|
||||||
return context.getRegisterValue(register, addr);
|
return context.getRegisterValue(register, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws ContextChangeException
|
|
||||||
* @see ghidra.program.model.lang.ProcessorContext#setValue(ghidra.program.model.lang.Register, java.math.BigInteger)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(Register register, BigInteger value) throws ContextChangeException {
|
public void setValue(Register register, BigInteger value) throws ContextChangeException {
|
||||||
context.setValue(register, addr, addr, value);
|
context.setValue(register, addr, addr, value);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -22,6 +21,7 @@ package ghidra.program.model.lang;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class ReadOnlyProcessorContext implements ProcessorContext {
|
public class ReadOnlyProcessorContext implements ProcessorContext {
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class ReadOnlyProcessorContext implements ProcessorContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return context.getRegisters();
|
return context.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,11 +89,15 @@ public class RegisterBuilder {
|
||||||
return contextAddress;
|
return contextAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute current register collection and instantiate a {@link RegisterManager}
|
||||||
|
* @return new register manager instance
|
||||||
|
*/
|
||||||
public RegisterManager getRegisterManager() {
|
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> regList = new LinkedList<>();
|
||||||
List<Register> unprocessed = new LinkedList<>(registerList);
|
List<Register> unprocessed = new LinkedList<>(registerList);
|
||||||
|
|
||||||
|
@ -115,8 +119,7 @@ public class RegisterBuilder {
|
||||||
}
|
}
|
||||||
bitSize = nextLargerSize;
|
bitSize = nextLargerSize;
|
||||||
}
|
}
|
||||||
|
return registerList;
|
||||||
return registerList.toArray(new Register[registerList.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Register[] getChildren(Register parent, List<Register> regList) {
|
private Register[] getChildren(Register parent, List<Register> regList) {
|
||||||
|
|
|
@ -22,18 +22,19 @@ import ghidra.program.model.address.OldGenericNamespaceAddress;
|
||||||
|
|
||||||
public class RegisterManager {
|
public class RegisterManager {
|
||||||
|
|
||||||
Register[] registers;
|
private List<Register> registers;
|
||||||
Map<String, Register> registerNameMap = new HashMap<String, Register>(); // include aliases and case-variations
|
private Map<String, Register> registerNameMap = new HashMap<String, Register>(); // include aliases and case-variations
|
||||||
|
|
||||||
String[] registerNames; // excludes aliases
|
private List<String> registerNames; // alphabetical sorted list, excludes aliases
|
||||||
Register[] contextRegisters;
|
private List<Register> contextRegisters;
|
||||||
Register contextBaseRegister;
|
private Register contextBaseRegister;
|
||||||
|
|
||||||
Map<RegisterSizeKey, Register> sizeMap = new HashMap<RegisterSizeKey, Register>();
|
private Map<RegisterSizeKey, Register> sizeMap = new HashMap<RegisterSizeKey, Register>();
|
||||||
Map<Address, List<Register>> registerAddressMap = new HashMap<Address, List<Register>>();
|
private Map<Address, List<Register>> registerAddressMap =
|
||||||
|
new HashMap<Address, List<Register>>();
|
||||||
|
|
||||||
/**Collection of vector registers, sorted first by size and then by offset**/
|
/**List of vector registers, sorted first by size and then by offset**/
|
||||||
private TreeSet<Register> sortedVectorRegisters;
|
private List<Register> sortedVectorRegisters;
|
||||||
|
|
||||||
class RegisterSizeKey {
|
class RegisterSizeKey {
|
||||||
Address address;
|
Address address;
|
||||||
|
@ -85,16 +86,16 @@ public class RegisterManager {
|
||||||
* @param registerNameMap a complete name-to-register map including all register aliases
|
* @param registerNameMap a complete name-to-register map including all register aliases
|
||||||
* and alternate spellings (e.g., case-variations)
|
* and alternate spellings (e.g., case-variations)
|
||||||
*/
|
*/
|
||||||
RegisterManager(Register[] cookedRegisters, Map<String, Register> registerNameMap) {
|
RegisterManager(List<Register> cookedRegisters, Map<String, Register> registerNameMap) {
|
||||||
registers = cookedRegisters;
|
this.registers = Collections.unmodifiableList(cookedRegisters);
|
||||||
this.registerNameMap = registerNameMap;
|
this.registerNameMap = Collections.unmodifiableMap(registerNameMap);
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
List<String> registerNameList = new ArrayList<String>();
|
List<String> registerNameList = new ArrayList<String>();
|
||||||
List<Register> contextRegisterList = new ArrayList<Register>();
|
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);
|
Collections.sort(registerList, registerSizeComparator);
|
||||||
for (Register reg : registerList) {
|
for (Register reg : registerList) {
|
||||||
String regName = reg.getName();
|
String regName = reg.getName();
|
||||||
|
@ -129,8 +130,9 @@ public class RegisterManager {
|
||||||
for (Register register : registerList) {
|
for (Register register : registerList) {
|
||||||
sizeMap.put(new RegisterSizeKey(register.getAddress(), 0), register);
|
sizeMap.put(new RegisterSizeKey(register.getAddress(), 0), register);
|
||||||
}
|
}
|
||||||
contextRegisters = contextRegisterList.toArray(new Register[contextRegisterList.size()]);
|
contextRegisters = Collections.unmodifiableList(contextRegisterList);
|
||||||
registerNames = registerNameList.toArray(new String[registerNameList.size()]);
|
Collections.sort(registerNameList);
|
||||||
|
registerNames = Collections.unmodifiableList(registerNameList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void populateSizeMapBigEndian(Register reg) {
|
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
|
* @return all processor context registers
|
||||||
*/
|
*/
|
||||||
public Register[] getContextRegisters() {
|
public List<Register> getContextRegisters() {
|
||||||
return contextRegisters;
|
return contextRegisters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get unsorted array of all original register names (exludes aliases)
|
* Get an alphabetical sorted unmodifiable list of original register names
|
||||||
* @return all 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;
|
return registerNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,29 +239,30 @@ public class RegisterManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all registers. Array returned is not protected and must not be modified
|
* Get all registers as an unsorted unmodifiable list.
|
||||||
* by caller.
|
* @return unmodifiable list of all registers defined
|
||||||
* @return array of all registers defined
|
|
||||||
*/
|
*/
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return registers;
|
return registers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all vector registers indentified by processor specification
|
* Get an unmodifiable list of all vector registers indentified by the processor specification
|
||||||
* in sorted order based upon address and size.
|
* in sorted order based upon address and size.
|
||||||
* @return all vector registers
|
* @return all vector registers as unmodifiable list
|
||||||
*/
|
*/
|
||||||
public Register[] getSortedVectorRegisters() {
|
public List<Register> getSortedVectorRegisters() {
|
||||||
if (sortedVectorRegisters == null) {
|
if (sortedVectorRegisters == null) {
|
||||||
sortedVectorRegisters = new TreeSet<Register>(RegisterManager::compareVectorRegisters);
|
ArrayList<Register> list = new ArrayList<Register>();
|
||||||
for (Register reg : getRegisters()) {
|
for (Register reg : registers) {
|
||||||
if (reg.isVectorRegister()) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -16,36 +15,33 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.lang;
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
|
||||||
public class RegisterTranslator {
|
public class RegisterTranslator {
|
||||||
private static Comparator<Register> registerSizeComparator = new Comparator<Register>() {
|
private static Comparator<Register> registerSizeComparator = new Comparator<Register>() {
|
||||||
|
@Override
|
||||||
public int compare(Register r1, Register r2) {
|
public int compare(Register r1, Register r2) {
|
||||||
// Used for sorting largest to smallest
|
// Used for sorting largest to smallest
|
||||||
return r2.getBitLength() - r1.getBitLength();
|
return r2.getBitLength() - r1.getBitLength();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private Register[] oldRegs;
|
private Language oldLang;
|
||||||
private Register[] newRegs;
|
private Language newLang;
|
||||||
|
|
||||||
private HashMap<Integer, List<Register>> oldRegisterMap;
|
private HashMap<Integer, List<Register>> oldRegisterMap;
|
||||||
private HashMap<Integer, List<Register>> newRegisterMap;
|
private HashMap<Integer, List<Register>> newRegisterMap;
|
||||||
private HashMap<String, Register> oldRegisterNameMap;
|
|
||||||
private HashMap<String, Register> newRegisterNameMap;
|
|
||||||
|
|
||||||
public RegisterTranslator(Language oldLang, Language newLang) {
|
public RegisterTranslator(Language oldLang, Language newLang) {
|
||||||
oldRegs = oldLang.getRegisters();
|
this.oldLang = oldLang;
|
||||||
newRegs = newLang.getRegisters();
|
this.newLang = newLang;
|
||||||
this.oldRegisterMap = buildOffsetMap(oldRegs);
|
this.oldRegisterMap = buildOffsetMap(oldLang.getRegisters());
|
||||||
this.newRegisterMap = buildOffsetMap(newRegs);
|
this.newRegisterMap = buildOffsetMap(newLang.getRegisters());
|
||||||
oldRegisterNameMap = buildNameMap(oldRegs);
|
|
||||||
newRegisterNameMap = buildNameMap(newRegs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>>();
|
HashMap<Integer, List<Register>> offsetMap = new HashMap<Integer, List<Register>>();
|
||||||
for (Register register : registers) {
|
for (Register register : registers) {
|
||||||
Address addr = register.getAddress();
|
Address addr = register.getAddress();
|
||||||
|
@ -69,14 +65,6 @@ public class RegisterTranslator {
|
||||||
return offsetMap;
|
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) {
|
public Register getOldRegister(int offset, int size) {
|
||||||
List<Register> list = oldRegisterMap.get(offset);
|
List<Register> list = oldRegisterMap.get(offset);
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
|
@ -110,15 +98,15 @@ public class RegisterTranslator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register getNewRegister(Register oldReg) {
|
public Register getNewRegister(Register oldReg) {
|
||||||
return newRegisterNameMap.get(oldReg.getName().toUpperCase());
|
return newLang.getRegister(oldReg.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register getOldRegister(Register newReg) {
|
public Register getOldRegister(Register newReg) {
|
||||||
return oldRegisterNameMap.get(newReg.getName().toUpperCase());
|
return oldLang.getRegister(newReg.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register[] getNewRegisters() {
|
public List<Register> getNewRegisters() {
|
||||||
return newRegs;
|
return newLang.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,7 +340,7 @@ public class InstructionStub implements Instruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.listing;
|
package ghidra.program.model.listing;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to define a processor register context over the address space.
|
* 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
|
* Modify register value to eliminate non-flowing bits
|
||||||
* @param value
|
* @param value register value to be modified
|
||||||
* @return value suitable for flowing
|
* @return value suitable for flowing
|
||||||
*/
|
*/
|
||||||
public RegisterValue getFlowValue(RegisterValue value);
|
public RegisterValue getFlowValue(RegisterValue value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modify register value to only include non-flowing bits
|
* Modify register value to only include non-flowing bits
|
||||||
* @param value
|
* @param value register value to be modified
|
||||||
* @return new value or null
|
* @return new value or null
|
||||||
*/
|
*/
|
||||||
public RegisterValue getNonFlowValue(RegisterValue value);
|
public RegisterValue getNonFlowValue(RegisterValue value);
|
||||||
|
@ -57,9 +58,9 @@ public interface ProgramContext {
|
||||||
/**
|
/**
|
||||||
* Get all the register descriptions defined for this program context.
|
* 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.
|
* 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 start the start address to set values
|
||||||
* @param end the end address to set values
|
* @param end the end address to set values
|
||||||
* @param value the actual values to store at address
|
* @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)
|
public void setRegisterValue(Address start, Address end, RegisterValue value)
|
||||||
throws ContextChangeException;
|
throws ContextChangeException;
|
||||||
|
@ -112,6 +115,8 @@ public interface ProgramContext {
|
||||||
* @param start the start address.
|
* @param start the start address.
|
||||||
* @param end the end address (inclusive).
|
* @param end the end address (inclusive).
|
||||||
* @param value the value to assign. A value of null will effective clear any existing values.
|
* @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)
|
public void setValue(Register register, Address start, Address end, BigInteger value)
|
||||||
throws ContextChangeException;
|
throws ContextChangeException;
|
||||||
|
@ -130,6 +135,8 @@ public interface ProgramContext {
|
||||||
* given range for the given register. Each range returned will have the same value
|
* given range for the given register. Each range returned will have the same value
|
||||||
* associated with the register for all addresses in that range.
|
* associated with the register for all addresses in that range.
|
||||||
* @param register the register for which to get set value ranges.
|
* @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
|
* @return An AddressRangeIterator over all address within the given range that have values
|
||||||
* for the given register.
|
* for the given register.
|
||||||
*/
|
*/
|
||||||
|
@ -139,8 +146,8 @@ public interface ProgramContext {
|
||||||
/**
|
/**
|
||||||
* Returns the bounding address-range containing addr and the the same RegisterValue throughout.
|
* 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.
|
* The range returned may be limited by other value changes associated with register's base-register.
|
||||||
* @param register
|
* @param register program register
|
||||||
* @param addr
|
* @param addr program address
|
||||||
* @return single register-value address-range containing addr
|
* @return single register-value address-range containing addr
|
||||||
*/
|
*/
|
||||||
public AddressRange getRegisterValueRangeContaining(Register register, Address 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
|
* 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.
|
* associated with the register for all addresses in that range.
|
||||||
* @param register the register for which to get default value ranges.
|
* @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
|
* @return An AddressRangeIterator over all address within the given range that have default values
|
||||||
* for the given register.
|
* for the given register.
|
||||||
*/
|
*/
|
||||||
|
@ -169,20 +178,26 @@ public interface ProgramContext {
|
||||||
* Gets the registers for this context that are used for processor context states.
|
* Gets the registers for this context that are used for processor context states.
|
||||||
* @return all processor context registers
|
* @return all processor context registers
|
||||||
*/
|
*/
|
||||||
public Register[] getProcessorStateRegisters();
|
public List<Register> getContextRegisters();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove (unset) the register values for a given address range.
|
* Remove (unset) the register values for a given address range.
|
||||||
* @param start starting address.
|
* @param start starting address.
|
||||||
* @param end ending adddress.
|
* @param end ending adddress.
|
||||||
* @param register handle to the register to be set.
|
* @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;
|
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
|
* 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
|
* from the default disassembly context and the context register value stored
|
||||||
* at the specified address. Those bits specified by the stored context value
|
* at the specified address. Those bits specified by the stored context value
|
||||||
* take precedence.
|
* take precedence.
|
||||||
* @param address
|
* @param address program address
|
||||||
* @return disassembly context register value
|
* @return disassembly context register value
|
||||||
*/
|
*/
|
||||||
public RegisterValue getDisassemblyContext(Address address);
|
public RegisterValue getDisassemblyContext(Address address);
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.pcode;
|
package ghidra.program.model.pcode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -50,8 +52,9 @@ public class VarnodeTranslator {
|
||||||
* @return Register or null if node is not a register
|
* @return Register or null if node is not a register
|
||||||
*/
|
*/
|
||||||
public Register getRegister(Varnode node) {
|
public Register getRegister(Varnode node) {
|
||||||
if (node == null)
|
if (node == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return language.getRegister(node.getAddress(), node.getSize());
|
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
|
* Get all defined registers for the program this translator was created
|
||||||
* with.
|
* with.
|
||||||
*
|
*
|
||||||
* @return all defined registers
|
* @return all defined registers as unmodifiable list
|
||||||
*/
|
*/
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return language.getRegisters();
|
return language.getRegisters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.program.util;
|
package ghidra.program.util;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
|
@ -128,7 +129,7 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Register[] getProcessorStateRegisters() {
|
public final List<Register> getContextRegisters() {
|
||||||
return language.getContextRegisters();
|
return language.getContextRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,12 +139,12 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String[] getRegisterNames() {
|
public final List<String> getRegisterNames() {
|
||||||
return language.getRegisterNames();
|
return language.getRegisterNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Register[] getRegisters() {
|
public final List<Register> getRegisters() {
|
||||||
return language.getRegisters();
|
return language.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ class OldLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getContextRegisters() {
|
public List<Register> getContextRegisters() {
|
||||||
return registerMgr.getContextRegisters();
|
return registerMgr.getContextRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,12 +140,12 @@ class OldLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getRegisters() {
|
public List<Register> getRegisters() {
|
||||||
return registerMgr.getRegisters();
|
return registerMgr.getRegisters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getRegisterNames() {
|
public List<String> getRegisterNames() {
|
||||||
return registerMgr.getRegisterNames();
|
return registerMgr.getRegisterNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,7 +747,7 @@ class OldLanguage implements Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getSortedVectorRegisters() {
|
public List<Register> getSortedVectorRegisters() {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
"Language for upgrade use only (getSortedVectorRegisters)");
|
"Language for upgrade use only (getSortedVectorRegisters)");
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,6 @@ public class OldLanguageFactory {
|
||||||
|
|
||||||
private static Element getRegistersElement(Language lang) {
|
private static Element getRegistersElement(Language lang) {
|
||||||
|
|
||||||
Register[] registers = lang.getRegisters();
|
|
||||||
Register contextReg = lang.getContextBaseRegister();
|
Register contextReg = lang.getContextBaseRegister();
|
||||||
Element registersElement = new Element("registers");
|
Element registersElement = new Element("registers");
|
||||||
if (contextReg != null) {
|
if (contextReg != null) {
|
||||||
|
@ -292,7 +291,7 @@ public class OldLanguageFactory {
|
||||||
}
|
}
|
||||||
registersElement.addContent(ctxElement);
|
registersElement.addContent(ctxElement);
|
||||||
}
|
}
|
||||||
for (Register reg : registers) {
|
for (Register reg : lang.getRegisters()) {
|
||||||
if (!reg.getBaseRegister().isProcessorContext()) {
|
if (!reg.getBaseRegister().isProcessorContext()) {
|
||||||
Element regElement = getRegisterElement(reg);
|
Element regElement = getRegisterElement(reg);
|
||||||
registersElement.addContent(regElement);
|
registersElement.addContent(regElement);
|
||||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.framework.main;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
|
@ -44,19 +46,20 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
public void testPspecParsing_x64() throws Exception {
|
public void testPspecParsing_x64() throws Exception {
|
||||||
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._X64);
|
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._X64);
|
||||||
testProgram = pBuilder.getProgram();
|
testProgram = pBuilder.getProgram();
|
||||||
Register[] vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
List<Register> vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
||||||
String[] intelVectorRegisterNames = getIntelVectorRegisterNames();
|
String[] intelVectorRegisterNames = getIntelVectorRegisterNames();
|
||||||
assertEquals(intelVectorRegisterNames.length, vectorRegs.length);
|
assertEquals(intelVectorRegisterNames.length, vectorRegs.size());
|
||||||
for (int i = 0; i < intelVectorRegisterNames.length; i++) {
|
for (int i = 0; i < intelVectorRegisterNames.length; i++) {
|
||||||
assertTrue(vectorRegs[i].isVectorRegister());
|
Register vectorReg = vectorRegs.get(i);
|
||||||
assertEquals(intelVectorRegisterNames[i], vectorRegs[i].getName());
|
assertTrue(vectorRegs.get(i).isVectorRegister());
|
||||||
if (vectorRegs[i].getName().startsWith("Y")) {
|
assertEquals(intelVectorRegisterNames[i], vectorReg.getName());
|
||||||
assertEquals(YMM_BIT_SIZE, vectorRegs[i].getBitLength());
|
if (vectorReg.getName().startsWith("Y")) {
|
||||||
|
assertEquals(YMM_BIT_SIZE, vectorReg.getBitLength());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(XMM_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(XMM_BIT_SIZE, vectorReg.getBitLength());
|
||||||
}
|
}
|
||||||
int[] lanes = vectorRegs[i].getLaneSizes();
|
int[] lanes = vectorReg.getLaneSizes();
|
||||||
assertEquals(4, lanes.length);
|
assertEquals(4, lanes.length);
|
||||||
//test lane sizes: should be 1,2,4,8
|
//test lane sizes: should be 1,2,4,8
|
||||||
int laneSize = 1;
|
int laneSize = 1;
|
||||||
|
@ -64,7 +67,7 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
assertEquals(laneSize, lane);
|
assertEquals(laneSize, lane);
|
||||||
laneSize *= 2;
|
laneSize *= 2;
|
||||||
}
|
}
|
||||||
assertFalse(vectorRegs[i].isValidLaneSize(3));
|
assertFalse(vectorReg.isValidLaneSize(3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,19 +75,20 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
public void testPspecParsing_x86() throws Exception {
|
public void testPspecParsing_x86() throws Exception {
|
||||||
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._X86);
|
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._X86);
|
||||||
testProgram = pBuilder.getProgram();
|
testProgram = pBuilder.getProgram();
|
||||||
Register[] vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
List<Register> vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
||||||
String[] intelVectorRegisterNames = getIntelVectorRegisterNames();
|
String[] intelVectorRegisterNames = getIntelVectorRegisterNames();
|
||||||
assertEquals(intelVectorRegisterNames.length, vectorRegs.length);
|
assertEquals(intelVectorRegisterNames.length, vectorRegs.size());
|
||||||
for (int i = 0; i < intelVectorRegisterNames.length; i++) {
|
for (int i = 0; i < intelVectorRegisterNames.length; i++) {
|
||||||
assertTrue(vectorRegs[i].isVectorRegister());
|
Register vectorReg = vectorRegs.get(i);
|
||||||
assertEquals(intelVectorRegisterNames[i], vectorRegs[i].getName());
|
assertTrue(vectorReg.isVectorRegister());
|
||||||
if (vectorRegs[i].getName().startsWith("Y")) {
|
assertEquals(intelVectorRegisterNames[i], vectorReg.getName());
|
||||||
assertEquals(YMM_BIT_SIZE, vectorRegs[i].getBitLength());
|
if (vectorReg.getName().startsWith("Y")) {
|
||||||
|
assertEquals(YMM_BIT_SIZE, vectorReg.getBitLength());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(XMM_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(XMM_BIT_SIZE, vectorReg.getBitLength());
|
||||||
}
|
}
|
||||||
int[] lanes = vectorRegs[i].getLaneSizes();
|
int[] lanes = vectorReg.getLaneSizes();
|
||||||
assertEquals(4, lanes.length);
|
assertEquals(4, lanes.length);
|
||||||
//test lane sizes: should be 1,2,4,8
|
//test lane sizes: should be 1,2,4,8
|
||||||
int laneSize = 1;
|
int laneSize = 1;
|
||||||
|
@ -92,7 +96,7 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
assertEquals(laneSize, lane);
|
assertEquals(laneSize, lane);
|
||||||
laneSize *= 2;
|
laneSize *= 2;
|
||||||
}
|
}
|
||||||
assertFalse(vectorRegs[i].isValidLaneSize(3));
|
assertFalse(vectorReg.isValidLaneSize(3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,14 +104,15 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
public void testPspecParsing_PPC_32() throws Exception {
|
public void testPspecParsing_PPC_32() throws Exception {
|
||||||
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._PPC_32);
|
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._PPC_32);
|
||||||
testProgram = pBuilder.getProgram();
|
testProgram = pBuilder.getProgram();
|
||||||
Register[] vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
List<Register> vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
||||||
String[] powerPcVectorRegisterNames = getPowerPCVectorRegisterNames();
|
String[] powerPcVectorRegisterNames = getPowerPCVectorRegisterNames();
|
||||||
assertEquals(powerPcVectorRegisterNames.length, vectorRegs.length);
|
assertEquals(powerPcVectorRegisterNames.length, vectorRegs.size());
|
||||||
for (int i = 0; i < vectorRegs.length; i++) {
|
for (int i = 0; i < powerPcVectorRegisterNames.length; i++) {
|
||||||
assertTrue(vectorRegs[i].isVectorRegister());
|
Register vectorReg = vectorRegs.get(i);
|
||||||
assertEquals(powerPcVectorRegisterNames[i], vectorRegs[i].getName());
|
assertTrue(vectorReg.isVectorRegister());
|
||||||
assertEquals(VSX_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(powerPcVectorRegisterNames[i], vectorReg.getName());
|
||||||
int[] lanes = vectorRegs[i].getLaneSizes();
|
assertEquals(VSX_BIT_SIZE, vectorReg.getBitLength());
|
||||||
|
int[] lanes = vectorReg.getLaneSizes();
|
||||||
assertEquals(3, lanes.length);
|
assertEquals(3, lanes.length);
|
||||||
//lane sizes should be 1, 2, 4
|
//lane sizes should be 1, 2, 4
|
||||||
int size = 1;
|
int size = 1;
|
||||||
|
@ -115,7 +120,7 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
assertEquals(size, lane);
|
assertEquals(size, lane);
|
||||||
size *= 2;
|
size *= 2;
|
||||||
}
|
}
|
||||||
assertFalse(vectorRegs[i].isValidLaneSize(5));
|
assertFalse(vectorReg.isValidLaneSize(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,14 +128,15 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
public void testPspecParsing_PPC_6432() throws Exception {
|
public void testPspecParsing_PPC_6432() throws Exception {
|
||||||
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._PPC_6432);
|
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._PPC_6432);
|
||||||
testProgram = pBuilder.getProgram();
|
testProgram = pBuilder.getProgram();
|
||||||
Register[] vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
List<Register> vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
||||||
String[] powerPcVectorRegisterNames = getPowerPCVectorRegisterNames();
|
String[] powerPcVectorRegisterNames = getPowerPCVectorRegisterNames();
|
||||||
assertEquals(powerPcVectorRegisterNames.length, vectorRegs.length);
|
assertEquals(powerPcVectorRegisterNames.length, vectorRegs.size());
|
||||||
for (int i = 0; i < vectorRegs.length; i++) {
|
for (int i = 0; i < powerPcVectorRegisterNames.length; i++) {
|
||||||
assertTrue(vectorRegs[i].isVectorRegister());
|
Register vectorReg = vectorRegs.get(i);
|
||||||
assertEquals(powerPcVectorRegisterNames[i], vectorRegs[i].getName());
|
assertTrue(vectorReg.isVectorRegister());
|
||||||
assertEquals(VSX_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(powerPcVectorRegisterNames[i], vectorReg.getName());
|
||||||
int[] lanes = vectorRegs[i].getLaneSizes();
|
assertEquals(VSX_BIT_SIZE, vectorReg.getBitLength());
|
||||||
|
int[] lanes = vectorReg.getLaneSizes();
|
||||||
assertEquals(3, lanes.length);
|
assertEquals(3, lanes.length);
|
||||||
//lane sizes should be 1, 2, 4
|
//lane sizes should be 1, 2, 4
|
||||||
int size = 1;
|
int size = 1;
|
||||||
|
@ -138,7 +144,7 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
assertEquals(size, lane);
|
assertEquals(size, lane);
|
||||||
size *= 2;
|
size *= 2;
|
||||||
}
|
}
|
||||||
assertFalse(vectorRegs[i].isValidLaneSize(5));
|
assertFalse(vectorReg.isValidLaneSize(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,14 +152,15 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
public void testPspecParsing_ARM() throws Exception {
|
public void testPspecParsing_ARM() throws Exception {
|
||||||
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._ARM);
|
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._ARM);
|
||||||
testProgram = pBuilder.getProgram();
|
testProgram = pBuilder.getProgram();
|
||||||
Register[] vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
List<Register> vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
||||||
String[] armVectorRegisterNames = getArmVectorRegisterNames();
|
String[] armVectorRegisterNames = getArmVectorRegisterNames();
|
||||||
assertEquals(armVectorRegisterNames.length, vectorRegs.length);
|
assertEquals(armVectorRegisterNames.length, vectorRegs.size());
|
||||||
for (int i = 0; i < vectorRegs.length; i++) {
|
for (int i = 0; i < armVectorRegisterNames.length; i++) {
|
||||||
assertTrue(vectorRegs[i].isVectorRegister());
|
Register vectorReg = vectorRegs.get(i);
|
||||||
assertEquals(armVectorRegisterNames[i], vectorRegs[i].getName());
|
assertTrue(vectorReg.isVectorRegister());
|
||||||
assertEquals(NEON_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(armVectorRegisterNames[i], vectorReg.getName());
|
||||||
int[] laneSizes = vectorRegs[i].getLaneSizes();
|
assertEquals(NEON_BIT_SIZE, vectorReg.getBitLength());
|
||||||
|
int[] laneSizes = vectorReg.getLaneSizes();
|
||||||
assertEquals(3, laneSizes.length);
|
assertEquals(3, laneSizes.length);
|
||||||
//lane sizes should be 1, 2, 4
|
//lane sizes should be 1, 2, 4
|
||||||
int size = 1;
|
int size = 1;
|
||||||
|
@ -161,7 +168,7 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
assertEquals(size, laneSize);
|
assertEquals(size, laneSize);
|
||||||
size *= 2;
|
size *= 2;
|
||||||
}
|
}
|
||||||
assertFalse(vectorRegs[i].isValidLaneSize(5));
|
assertFalse(vectorReg.isValidLaneSize(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,24 +176,25 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
public void testPspecParsing_AARCH64() throws Exception {
|
public void testPspecParsing_AARCH64() throws Exception {
|
||||||
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._AARCH64);
|
ProgramBuilder pBuilder = new ProgramBuilder("test", ProgramBuilder._AARCH64);
|
||||||
testProgram = pBuilder.getProgram();
|
testProgram = pBuilder.getProgram();
|
||||||
Register[] vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
List<Register> vectorRegs = testProgram.getLanguage().getSortedVectorRegisters();
|
||||||
String[] aarch64VectorRegisterNames = getAarch64VectorRegisterNames();
|
String[] aarch64VectorRegisterNames = getAarch64VectorRegisterNames();
|
||||||
assertEquals(aarch64VectorRegisterNames.length, vectorRegs.length);
|
assertEquals(aarch64VectorRegisterNames.length, vectorRegs.size());
|
||||||
for (int i = 0; i < vectorRegs.length; i++) {
|
for (int i = 0; i < aarch64VectorRegisterNames.length; i++) {
|
||||||
assertTrue(vectorRegs[i].isVectorRegister());
|
Register vectorReg = vectorRegs.get(i);
|
||||||
assertEquals(aarch64VectorRegisterNames[i], vectorRegs[i].getName());
|
assertTrue(vectorReg.isVectorRegister());
|
||||||
switch (vectorRegs[i].getName().substring(0, 1)) {
|
assertEquals(aarch64VectorRegisterNames[i], vectorReg.getName());
|
||||||
|
switch (vectorReg.getName().substring(0, 1)) {
|
||||||
case "z":
|
case "z":
|
||||||
assertEquals(SVE_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(SVE_BIT_SIZE, vectorReg.getBitLength());
|
||||||
break;
|
break;
|
||||||
case "q":
|
case "q":
|
||||||
assertEquals(NEON_BIT_SIZE, vectorRegs[i].getBitLength());
|
assertEquals(NEON_BIT_SIZE, vectorReg.getBitLength());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"bad vector register name: " + vectorRegs[i].getName());
|
"bad vector register name: " + vectorReg.getName());
|
||||||
}
|
}
|
||||||
int[] laneSizes = vectorRegs[i].getLaneSizes();
|
int[] laneSizes = vectorReg.getLaneSizes();
|
||||||
assertEquals(4, laneSizes.length);
|
assertEquals(4, laneSizes.length);
|
||||||
//sizes should be 1,2,4,8
|
//sizes should be 1,2,4,8
|
||||||
int size = 1;
|
int size = 1;
|
||||||
|
@ -194,7 +202,7 @@ public class VectorRegisterPspecTest extends AbstractGenericTest {
|
||||||
assertEquals(size, laneSize);
|
assertEquals(size, laneSize);
|
||||||
size *= 2;
|
size *= 2;
|
||||||
}
|
}
|
||||||
assertFalse(vectorRegs[i].isValidLaneSize(3));
|
assertFalse(vectorReg.isValidLaneSize(3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue