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

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

View file

@ -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) {

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1389,7 +1389,7 @@ public class VarnodeContext implements ProcessorContext {
} }
@Override @Override
public Register[] getRegisters() { public List<Register> getRegisters() {
return offsetContext.getRegisters(); return offsetContext.getRegisters();
} }

View file

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

View file

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

View file

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

View file

@ -29,7 +29,6 @@ src/main/java/ghidra/program/database/package.html||GHIDRA||||END|
src/main/java/ghidra/program/model/address/package.html||GHIDRA||||END| src/main/java/ghidra/program/model/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|

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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