mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-24 23:10:47 +08:00
Merge remote-tracking branch 'origin/GP-38_ghidra1_CaseInsensitiveRegisterLookup'
This commit is contained in:
@@ -219,8 +219,7 @@ public class BuildResultState extends GhidraScript {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
Register[] regs = currentProgram.getLanguage().getRegisters();
|
||||
List<Register> registers = Arrays.asList(regs);
|
||||
List<Register> registers = currentProgram.getLanguage().getRegisters();
|
||||
try {
|
||||
Register reg = askChoice("Results Query", "Select Register:", registers, null);
|
||||
while (reg != null) {
|
||||
|
||||
+1
-2
@@ -309,8 +309,7 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
||||
|
||||
Program program = function.getProgram();
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
SymbolUtilities.validateName(name, entryPoint, SymbolType.FUNCTION,
|
||||
program.getAddressMap().getAddressFactory());
|
||||
SymbolUtilities.validateName(name);
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol sym = symbolTable.getPrimarySymbol(entryPoint);
|
||||
|
||||
@@ -31,7 +31,6 @@ import ghidra.program.util.SymbolicPropogator.Value;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
/**
|
||||
* CallDepthChangeInfo.java
|
||||
@@ -89,7 +88,7 @@ public class CallDepthChangeInfo {
|
||||
this.program = func.getProgram();
|
||||
frameReg = program.getCompilerSpec().getStackPointer();
|
||||
try {
|
||||
initialize(func, func.getBody(), frameReg, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
initialize(func, func.getBody(), frameReg, TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
throw new RuntimeException("Unexpected Exception", e);
|
||||
@@ -532,7 +531,7 @@ public class CallDepthChangeInfo {
|
||||
st.push(func.getEntryPoint());
|
||||
st.push(new Integer(0));
|
||||
st.push(Boolean.TRUE);
|
||||
ProcessorContextImpl procContext = new ProcessorContextImpl(trans.getRegisters());
|
||||
ProcessorContextImpl procContext = new ProcessorContextImpl(program.getLanguage());
|
||||
|
||||
AddressSet undone = new AddressSet(func.getBody());
|
||||
AddressSet badStackSet = new AddressSet(undone);
|
||||
@@ -903,9 +902,9 @@ public class CallDepthChangeInfo {
|
||||
|
||||
Stack<Object> st = new Stack<Object>();
|
||||
st.push(func.getEntryPoint());
|
||||
st.push(new Integer(0));
|
||||
st.push(Integer.valueOf(0));
|
||||
st.push(Boolean.TRUE);
|
||||
ProcessorContextImpl procContext = new ProcessorContextImpl(trans.getRegisters());
|
||||
ProcessorContextImpl procContext = new ProcessorContextImpl(program.getLanguage());
|
||||
|
||||
AddressSet undone = new AddressSet(func.getBody());
|
||||
AddressSet badStackSet = new AddressSet(undone);
|
||||
@@ -955,7 +954,7 @@ public class CallDepthChangeInfo {
|
||||
Address[] flows = instr.getFlows();
|
||||
for (Address flow2 : flows) {
|
||||
st.push(flow2);
|
||||
st.push(new Integer(stackPointerDepth));
|
||||
st.push(Integer.valueOf(stackPointerDepth));
|
||||
st.push(stackOK);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-15
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +15,8 @@
|
||||
*/
|
||||
package ghidra.app.merge.listing;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.merge.MergeResolver;
|
||||
import ghidra.app.merge.ProgramMultiUserMergeManager;
|
||||
import ghidra.app.merge.tool.ListingMergePanel;
|
||||
@@ -27,9 +28,6 @@ import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* <code>ProgramContextMergeManager</code> merges register value changes
|
||||
* 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 myContext;
|
||||
ProgramContext resultContext;
|
||||
Register[] registers;
|
||||
List<Register> registers;
|
||||
|
||||
/** Used to determine differences between the original program and latest program. */
|
||||
ProgramDiff diffOriginalLatest;
|
||||
@@ -187,21 +185,19 @@ public class ProgramContextMergeManager implements MergeResolver, ListingMergeCo
|
||||
mergePanel.setTopComponent(conflictInfoPanel);
|
||||
}
|
||||
try {
|
||||
String[] latestNames = latestContext.getRegisterNames();
|
||||
String[] myNames = myContext.getRegisterNames();
|
||||
Arrays.sort(latestNames);
|
||||
Arrays.sort(myNames);
|
||||
if (!Arrays.equals(latestNames, myNames)) {
|
||||
List<String> latestNames = latestContext.getRegisterNames();
|
||||
List<String> myNames = myContext.getRegisterNames();
|
||||
if (!latestNames.equals(myNames)) {
|
||||
mergeManager.setStatusText("Program Context Registers don't match between the programs.");
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
Register[] regs = latestContext.getRegisters();
|
||||
ArrayList<Register> regs = new ArrayList<>(latestContext.getRegisters());
|
||||
// Sort the registers by size so that largest come first.
|
||||
// This prevents the remove call below from incorrectly clearing
|
||||
// smaller registers that are part of a larger register.
|
||||
Arrays.sort(regs, new Comparator<Register>() {
|
||||
Collections.sort(regs, new Comparator<Register>() {
|
||||
@Override
|
||||
public int compare(Register r1, Register r2) {
|
||||
return r2.getBitLength() - r1.getBitLength();
|
||||
@@ -211,15 +207,16 @@ public class ProgramContextMergeManager implements MergeResolver, ListingMergeCo
|
||||
int transactionID = resultPgm.startTransaction(getDescription());
|
||||
boolean commit = false;
|
||||
try {
|
||||
int numRegs = regs.length;
|
||||
int numRegs = regs.size();
|
||||
monitor.initialize(numRegs);
|
||||
|
||||
// Get the conflicts for each register
|
||||
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
|
||||
}
|
||||
String regName = regs[i].getName();
|
||||
String regName = reg.getName();
|
||||
int currentProgressPercentage = (int) (((float) 100 / numRegs) * i);
|
||||
mergeManager.updateProgress(currentProgressPercentage,
|
||||
"Merging register values for " + regName);
|
||||
|
||||
+4
-18
@@ -301,25 +301,11 @@ public class DisassemblerPlugin extends Plugin {
|
||||
return currentProgram.getMemory().contains(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.plugin.contrib.disassembler.DisassemblyTaskListener#disassembleMessageReported(String)
|
||||
*/
|
||||
public void disassembleMessageReported(String msg) {
|
||||
tool.setStatusInfo(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.plugin.contrib.disassembler.DisassemblyTaskListener#disassemblyDone(DisassemblyTask)
|
||||
*/
|
||||
public void disassemblyDone(Disassembler task) {
|
||||
}
|
||||
|
||||
public void setDefaultContext(ListingActionContext context) {
|
||||
|
||||
Program contextProgram = context.getProgram();
|
||||
ProgramContext programContext = contextProgram.getProgramContext();
|
||||
Register[] registers = programContext.getProcessorStateRegisters();
|
||||
if (registers.length == 0) {
|
||||
Register baseContextReg = contextProgram.getLanguage().getContextBaseRegister();
|
||||
if (baseContextReg != null && baseContextReg.hasChildren()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -328,8 +314,8 @@ public class DisassemblerPlugin extends Plugin {
|
||||
}
|
||||
|
||||
public boolean hasContextRegisters(Program currentProgram) {
|
||||
Register[] registers = currentProgram.getProgramContext().getProcessorStateRegisters();
|
||||
return registers.length > 0;
|
||||
Register baseContextReg = currentProgram.getLanguage().getContextBaseRegister();
|
||||
return baseContextReg != null && baseContextReg.hasChildren();
|
||||
}
|
||||
|
||||
public void disassembleArmCallback(ListingActionContext context, boolean thumbMode) {
|
||||
|
||||
+2
-2
@@ -47,9 +47,9 @@ public class ProcessorStateDialog extends DialogComponentProvider {
|
||||
public ProcessorStateDialog(ProgramContext programContext) {
|
||||
super(TITLE, true, false, true, false);
|
||||
this.programContext = programContext;
|
||||
Register[] contextRegisters = programContext.getProcessorStateRegisters();
|
||||
|
||||
registerList = new ArrayList<>();
|
||||
for (Register register : contextRegisters) {
|
||||
for (Register register : programContext.getContextRegisters()) {
|
||||
if (!register.isBaseRegister()) {
|
||||
registerList.add(register);
|
||||
}
|
||||
|
||||
+2
-2
@@ -172,8 +172,8 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE
|
||||
|
||||
private Component createRegisterCombo(VarnodeInfo varnode) {
|
||||
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();) {
|
||||
Register register = iter.next();
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ public class RegisterFieldFactory extends FieldFactory {
|
||||
private List<Register> getSetRegisters(Function function) {
|
||||
Program program = function.getProgram();
|
||||
ProgramContext programContext = program.getProgramContext();
|
||||
Register[] registers = programContext.getRegisters();
|
||||
Register[] registers = programContext.getRegistersWithValues();
|
||||
Address address = function.getEntryPoint();
|
||||
List<Register> setRegisters = new ArrayList<>();
|
||||
for (Register register : registers) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,21 +15,23 @@
|
||||
*/
|
||||
package ghidra.app.util.xml;
|
||||
|
||||
import ghidra.app.util.importer.*;
|
||||
import ghidra.program.model.address.*;
|
||||
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.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
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.
|
||||
@@ -87,10 +88,11 @@ class RegisterValuesXmlMgr {
|
||||
* Returns list of unique registers which do not overlap any smaller
|
||||
* registers.
|
||||
*/
|
||||
private Register[] getUniqueRegisters() {
|
||||
private List<Register> getUniqueRegisters() {
|
||||
|
||||
Register[] regs = context.getRegisters();
|
||||
Arrays.sort(regs, new Comparator<Register>() {
|
||||
ArrayList<Register> regs = new ArrayList<>(context.getRegisters());
|
||||
Collections.sort(regs, new Comparator<Register>() {
|
||||
@Override
|
||||
public int compare(Register r1, Register r2) {
|
||||
int size1 = r1.getMinimumByteSize();
|
||||
int size2 = r2.getMinimumByteSize();
|
||||
@@ -101,30 +103,6 @@ class RegisterValuesXmlMgr {
|
||||
}
|
||||
});
|
||||
|
||||
// ArrayList list = new ArrayList();
|
||||
// for (int i = 0; i < regs.length; i++) {
|
||||
//
|
||||
// Register reg = regs[i];
|
||||
// int minOffset = reg.getOffset();
|
||||
// int maxOffset = minOffset + reg.getSize() - 1;
|
||||
//
|
||||
// // Skip if reg is broken into smaller registers
|
||||
// boolean overlap = false;
|
||||
// for (int n = 0; n < i; n++) {
|
||||
// int off = regs[n].getOffset();
|
||||
// if (off >= minOffset && off <= maxOffset) {
|
||||
// overlap = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!overlap) {
|
||||
// list.add(reg);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// regs = new Register[list.size()];
|
||||
// list.toArray(regs);
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
||||
@@ -140,11 +118,7 @@ class RegisterValuesXmlMgr {
|
||||
|
||||
writer.startElement("REGISTER_VALUES");
|
||||
|
||||
Register[] regs = getUniqueRegisters();
|
||||
|
||||
//for (int i = 0; i < regs.length; i++) {
|
||||
//Register reg = regs[i];
|
||||
//}
|
||||
List<Register> regs = getUniqueRegisters();
|
||||
if (set == null) {
|
||||
set = program.getMemory();
|
||||
}
|
||||
@@ -156,8 +130,7 @@ class RegisterValuesXmlMgr {
|
||||
|
||||
AddressRange range = rangeIter.next();
|
||||
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
Register reg = regs[i];
|
||||
for (Register reg : regs) {
|
||||
AddressRangeIterator it = context.getRegisterValueAddressRanges(reg, range.getMinAddress(), range.getMaxAddress());
|
||||
while(it.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
@@ -1156,13 +1156,8 @@ public class ProgramDiff {
|
||||
private AddressSet getProgramContextDifferences(AddressSetView addressSet, TaskMonitor monitor)
|
||||
throws ProgramConflictException, CancelledException {
|
||||
AddressSet differences = new AddressSet();
|
||||
ProgramContext pc1 = program1.getProgramContext();
|
||||
ProgramContext pc2 = program2.getProgramContext();
|
||||
String[] names1 = pc1.getRegisterNames();
|
||||
String[] names2 = pc2.getRegisterNames();
|
||||
Arrays.sort(names1);
|
||||
Arrays.sort(names2);
|
||||
if (!Arrays.equals(names1, names2)) {
|
||||
|
||||
if (!ProgramMemoryComparator.sameProgramContextRegisterNames(program1, program2)) {
|
||||
throw new ProgramConflictException(
|
||||
"Program Context Registers don't match between the programs.");
|
||||
}
|
||||
@@ -1171,7 +1166,10 @@ public class ProgramDiff {
|
||||
AddressSet inCommon = pgmMemComp.getAddressesInCommon();
|
||||
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();
|
||||
Register rb1 = pc1.getRegister(element);
|
||||
Register rb2 = pc2.getRegister(element);
|
||||
|
||||
@@ -383,9 +383,8 @@ public class ProgramDiffDetails {
|
||||
l1 = p1.getListing();
|
||||
l2 = p2.getListing();
|
||||
|
||||
Register[] descs1 = p1.getProgramContext().getRegisters();
|
||||
maxRegisterName = "Register".length(); // default name length.
|
||||
for (Register element : descs1) {
|
||||
for (Register element : p1.getProgramContext().getRegisters()) {
|
||||
maxRegisterName = Math.max(maxRegisterName, element.getName().length());
|
||||
}
|
||||
}
|
||||
@@ -1285,13 +1284,8 @@ public class ProgramDiffDetails {
|
||||
* @throws ConcurrentModificationException if analysis is modifying the program context.
|
||||
*/
|
||||
private void addProgramContextDetails() throws ConcurrentModificationException {
|
||||
ProgramContext pc1 = p1.getProgramContext();
|
||||
ProgramContext pc2 = p2.getProgramContext();
|
||||
String[] names1 = pc1.getRegisterNames();
|
||||
String[] names2 = pc2.getRegisterNames();
|
||||
Arrays.sort(names1);
|
||||
Arrays.sort(names2);
|
||||
if (!Arrays.equals(names1, names2)) {
|
||||
|
||||
if (!ProgramMemoryComparator.sameProgramContextRegisterNames(p1, p2)) {
|
||||
addDiffHeader("Program Context");
|
||||
addText(
|
||||
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.
|
||||
Register[] descs1 = pc1.getRegisters();
|
||||
for (Register reg1 : descs1) {
|
||||
ProgramContext pc1 = p1.getProgramContext();
|
||||
ProgramContext pc2 = p2.getProgramContext();
|
||||
for (Register reg1 : pc1.getRegisters()) {
|
||||
addRegisterDiffDetails(pc1, pc2, reg1);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-12
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package ghidra.program.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.ProgramContext;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* <CODE>ProgramMemoryComparator</CODE> is a class for comparing two programs and
|
||||
* 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).
|
||||
*/
|
||||
public static boolean similarPrograms(Program p1, Program p2) {
|
||||
if (p1 == null || p2 == null)
|
||||
if (p1 == null || p2 == null) {
|
||||
return false;
|
||||
}
|
||||
if (p1.getLanguageID().equals(p2.getLanguageID())) {
|
||||
return true;
|
||||
}
|
||||
AddressSpace[] spaces1 = p1.getLanguage().getAddressFactory().getAddressSpaces();
|
||||
AddressSpace[] spaces2 = p2.getLanguage().getAddressFactory().getAddressSpaces();
|
||||
if (spaces1.length != spaces2.length)
|
||||
if (spaces1.length != spaces2.length) {
|
||||
return false;
|
||||
}
|
||||
Arrays.sort(spaces1);
|
||||
Arrays.sort(spaces2);
|
||||
for (int i=0; i<spaces1.length; i++) {
|
||||
@@ -279,14 +282,9 @@ public class ProgramMemoryComparator {
|
||||
static public boolean sameProgramContextRegisterNames(Program program1, Program program2) {
|
||||
ProgramContext pc1 = program1.getProgramContext();
|
||||
ProgramContext pc2 = program2.getProgramContext();
|
||||
String[] names1 = pc1.getRegisterNames();
|
||||
String[] names2 = pc2.getRegisterNames();
|
||||
Arrays.sort(names1);
|
||||
Arrays.sort(names2);
|
||||
if (!Arrays.equals(names1, names2)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
List<String> names1 = pc1.getRegisterNames();
|
||||
List<String> names2 = pc2.getRegisterNames();
|
||||
return names1.equals(names2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -239,11 +239,11 @@ public class ProgramMerge implements PropertyVisitor {
|
||||
|
||||
ProgramContext resultContext = resultProgram.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.
|
||||
// This prevents the remove call below from incorrectly clearing
|
||||
// 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();
|
||||
while (originRangeIter.hasNext() && !monitor.isCancelled()) {
|
||||
AddressRange originRange = originRangeIter.next();
|
||||
|
||||
@@ -81,9 +81,9 @@ public class SymbolicPropogator {
|
||||
public SymbolicPropogator(Program program) {
|
||||
this.program = program;
|
||||
|
||||
Register regs[] = program.getLanguage().getRegisters();
|
||||
programContext = new ProgramContextImpl(regs);
|
||||
spaceContext = new ProgramContextImpl(regs);
|
||||
Language language = program.getLanguage();
|
||||
programContext = new ProgramContextImpl(language);
|
||||
spaceContext = new ProgramContextImpl(language);
|
||||
|
||||
setPointerMask(program);
|
||||
setExternalRange(program);
|
||||
@@ -208,8 +208,9 @@ public class SymbolicPropogator {
|
||||
* @return
|
||||
*/
|
||||
protected VarnodeContext saveOffCurrentContext(Address startAddr) {
|
||||
ProgramContext newValueContext = new ProgramContextImpl(programContext.getRegisters());
|
||||
ProgramContext newSpaceContext = new ProgramContextImpl(programContext.getRegisters());
|
||||
Language language = program.getLanguage();
|
||||
ProgramContext newValueContext = new ProgramContextImpl(language);
|
||||
ProgramContext newSpaceContext = new ProgramContextImpl(language);
|
||||
VarnodeContext newContext = new VarnodeContext(program, newValueContext, newSpaceContext);
|
||||
newContext.setDebug(debug);
|
||||
int constantSpaceID = program.getAddressFactory().getConstantSpace().getSpaceID();
|
||||
|
||||
@@ -1389,7 +1389,7 @@ public class VarnodeContext implements ProcessorContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return offsetContext.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -15,8 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.cmd.disassemble;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
@@ -338,8 +337,7 @@ public class DisassembleContextTest extends AbstractGhidraHeadedIntegrationTest
|
||||
public void testFlowWithNoSaveIntoContextImpl() {
|
||||
|
||||
// Simple context does not contain default values
|
||||
ProgramContext retainedContext =
|
||||
new ProgramContextImpl(program.getLanguage().getRegisters());
|
||||
ProgramContext retainedContext = new ProgramContextImpl(program.getLanguage());
|
||||
|
||||
Address addr = space.getAddress(0x0);
|
||||
|
||||
|
||||
+4
-6
@@ -15,8 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.util.viewer.field;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
@@ -106,11 +105,10 @@ public class RegisterFieldFactoryTest extends AbstractGhidraHeadedIntegrationTes
|
||||
}
|
||||
|
||||
private List<Register> getNonContextRegisters(ProgramContext pc) {
|
||||
Register[] regs = pc.getRegisters();
|
||||
List<Register> nonContextRegs = new ArrayList<Register>();
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
if (!regs[i].isProcessorContext()) {
|
||||
nonContextRegs.add(regs[i]);
|
||||
for (Register reg : pc.getRegisters()) {
|
||||
if (!reg.isProcessorContext()) {
|
||||
nonContextRegs.add(reg);
|
||||
}
|
||||
}
|
||||
return nonContextRegs;
|
||||
|
||||
+19
-5
@@ -58,6 +58,21 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
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
|
||||
public void testAll() {
|
||||
int id = program.startTransaction("Test");
|
||||
@@ -73,10 +88,7 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
ProgramContext programContext = program.getProgramContext();
|
||||
Register[] registers = null;
|
||||
if (programContext != null) {
|
||||
registers = programContext.getRegisters();
|
||||
}
|
||||
boolean didSomething = false;
|
||||
|
||||
Address startAddress = start;
|
||||
Address endAddress = getAddress(0x30);
|
||||
@@ -84,7 +96,7 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
// stick a value into each one!
|
||||
BigInteger value = BigInteger.valueOf(255);
|
||||
|
||||
for (Register register : registers) {
|
||||
for (Register register : programContext.getRegisters()) {
|
||||
Register reg = register;
|
||||
if (!reg.isBaseRegister() && reg.isProcessorContext()) {
|
||||
continue;
|
||||
@@ -136,7 +148,9 @@ public class ProgramContextTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
endAddress.getAddressSpace().getMaxAddress()),
|
||||
programContext.getRegisterValueRangeContaining(reg, badAddress));
|
||||
|
||||
didSomething = true;
|
||||
}
|
||||
assertTrue(didSomething);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(id, false);
|
||||
|
||||
@@ -132,7 +132,7 @@ public class ContextStateTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
@Test
|
||||
public void testStoreConstantWithEntryContext() {
|
||||
|
||||
ProgramContextImpl ctx = new ProgramContextImpl(lang.getRegisters());
|
||||
ProgramContextImpl ctx = new ProgramContextImpl(lang);
|
||||
ctx.setDefaultValue(
|
||||
new RegisterValue(lang.getRegister("EAX"), new BigInteger("fedcba98", 16)), addr(1000),
|
||||
addr(1000));
|
||||
|
||||
+2
-5
@@ -839,16 +839,13 @@ public class DecompileCallback {
|
||||
return null;
|
||||
}
|
||||
ProgramContext context = program.getProgramContext();
|
||||
Register[] regs = context.getRegisters();
|
||||
if (regs == null || regs.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder stringBuf = new StringBuilder();
|
||||
|
||||
stringBuf.append("<tracked_pointset");
|
||||
Varnode.appendSpaceOffset(stringBuf, addr);
|
||||
stringBuf.append(">\n");
|
||||
for (Register reg : regs) {
|
||||
for (Register reg : context.getRegisters()) {
|
||||
if (reg.isProcessorContext()) {
|
||||
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/block/package.html||GHIDRA||||END|
|
||||
src/main/java/ghidra/program/model/data/package.html||GHIDRA||||END|
|
||||
src/main/java/ghidra/program/model/graph/package.html||GHIDRA||||END|
|
||||
src/main/java/ghidra/program/model/lang/package.html||GHIDRA||||END|
|
||||
src/main/java/ghidra/program/model/listing/package.html||GHIDRA||||END|
|
||||
src/main/java/ghidra/program/model/mem/package.html||GHIDRA||||END|
|
||||
|
||||
@@ -99,11 +99,6 @@
|
||||
<ref name="boolean_type"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="unused">
|
||||
<ref name="boolean_type"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="vector_lane_sizes"/>
|
||||
</optional>
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
package ghidra.app.plugin.assembler.sleigh.sem;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.plugin.assembler.sleigh.util.DbgTimer;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
@@ -117,7 +118,7 @@ public class AssemblyDefaultContext implements DisassemblerContext, DefaultProgr
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return lang.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1276,7 +1276,7 @@ public class SleighDebugLogger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
if (originalContext != null) {
|
||||
return originalContext.getRegisters();
|
||||
}
|
||||
|
||||
+16
-13
@@ -140,7 +140,6 @@ public class SleighLanguage implements Language {
|
||||
loadRegisters(registerBuilder);
|
||||
readRemainingSpecification();
|
||||
|
||||
// registerManager = registerBuilder.getRegisterManager();
|
||||
xrefRegisters();
|
||||
|
||||
instructProtoMap = new LinkedHashMap<>();
|
||||
@@ -265,6 +264,11 @@ public class SleighLanguage implements Language {
|
||||
return getRegisterManager().getContextBaseRegister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Register> getContextRegisters() {
|
||||
return getRegisterManager().getContextRegisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlockDefinition[] getDefaultMemoryBlocks() {
|
||||
return defaultMemoryBlocks;
|
||||
@@ -331,10 +335,15 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return getRegisterManager().getRegisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRegisterNames() {
|
||||
return getRegisterManager().getRegisterNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSegmentedSpace() {
|
||||
return segmentedspace;
|
||||
@@ -743,11 +752,7 @@ public class SleighLanguage implements Language {
|
||||
String registerRename = reg.getAttribute("rename");
|
||||
String groupName = reg.getAttribute("group");
|
||||
boolean isHidden = SpecXmlUtils.decodeBoolean(reg.getAttribute("hidden"));
|
||||
boolean isUnused = SpecXmlUtils.decodeBoolean(reg.getAttribute("unused"));
|
||||
if (isUnused) {
|
||||
registerBuilder.removeRegister(registerName);
|
||||
}
|
||||
else if (registerRename != null) {
|
||||
if (registerRename != null) {
|
||||
if (!registerBuilder.renameRegister(registerName, registerRename)) {
|
||||
throw new SleighException(
|
||||
"error renaming " + registerName + " to " + registerRename);
|
||||
@@ -1074,11 +1079,8 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
|
||||
private void xrefRegisters() {
|
||||
Register[] regs = getRegisterManager().getRegisters();
|
||||
for (Register register : regs) {
|
||||
if (register.isProcessorContext()) {
|
||||
contextcache.registerVariable(register);
|
||||
}
|
||||
for (Register register : getRegisterManager().getContextRegisters()) {
|
||||
contextcache.registerVariable(register);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1581,7 +1583,8 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getSortedVectorRegisters() {
|
||||
public List<Register> getSortedVectorRegisters() {
|
||||
return registerManager.getSortedVectorRegisters();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
package ghidra.app.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -56,7 +57,7 @@ public class PseudoDisassemblerContext implements DisassemblerContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return disContext.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -548,7 +548,7 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return procContext.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+5
-8
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,14 +15,12 @@
|
||||
*/
|
||||
package ghidra.pcode.emulate;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.util.ProgramContextImpl;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.util.ProgramContextImpl;
|
||||
|
||||
public class EmulateDisassemblerContext implements DisassemblerContext {
|
||||
|
||||
@@ -72,7 +69,7 @@ public class EmulateDisassemblerContext implements DisassemblerContext {
|
||||
contextRegValue = null;
|
||||
}
|
||||
if (contextRegValue == null) {
|
||||
ProgramContextImpl defaultContext = new ProgramContextImpl(language.getRegisters());
|
||||
ProgramContextImpl defaultContext = new ProgramContextImpl(language);
|
||||
language.applyContextSettings(defaultContext);
|
||||
contextRegValue = defaultContext.getDefaultValue(contextReg, addr);
|
||||
if (contextRegValue == null) {
|
||||
@@ -157,7 +154,7 @@ public class EmulateDisassemblerContext implements DisassemblerContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -17,8 +17,7 @@ package ghidra.program.database.code;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -753,7 +752,7 @@ abstract class CodeUnitDB extends DatabaseObject implements CodeUnit, ProcessorC
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return programContext.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+12
-25
@@ -17,6 +17,7 @@ package ghidra.program.database.code;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import db.*;
|
||||
@@ -130,8 +131,9 @@ class PrototypeManager {
|
||||
RecordIterator it = contextTable.iterator();
|
||||
while (it.hasNext()) {
|
||||
monitor.setProgress(++count);
|
||||
if (monitor.isCancelled())
|
||||
if (monitor.isCancelled()) {
|
||||
throw new IOException("Upgrade Cancelled");
|
||||
}
|
||||
Record rec = it.next();
|
||||
String oldValue = rec.getString(0);
|
||||
rec.setString(0, convertString(oldValue));
|
||||
@@ -143,8 +145,9 @@ class PrototypeManager {
|
||||
it = tempTable.iterator();
|
||||
while (it.hasNext()) {
|
||||
monitor.setProgress(++count);
|
||||
if (monitor.isCancelled())
|
||||
if (monitor.isCancelled()) {
|
||||
throw new IOException("Upgrade Cancelled");
|
||||
}
|
||||
Record rec = it.next();
|
||||
contextTable.putRecord(rec);
|
||||
}
|
||||
@@ -187,8 +190,9 @@ class PrototypeManager {
|
||||
RecordIterator it = protoAdapter.getRecords();
|
||||
while (it.hasNext()) {
|
||||
monitor.setProgress(++count);
|
||||
if (monitor.isCancelled())
|
||||
if (monitor.isCancelled()) {
|
||||
throw new IOException("Upgrade Cancelled");
|
||||
}
|
||||
Record rec = it.next();
|
||||
tempAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
|
||||
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
|
||||
@@ -201,8 +205,9 @@ class PrototypeManager {
|
||||
it = tempAdapter.getRecords();
|
||||
while (it.hasNext()) {
|
||||
monitor.setProgress(++count);
|
||||
if (monitor.isCancelled())
|
||||
if (monitor.isCancelled()) {
|
||||
throw new IOException("Upgrade Cancelled");
|
||||
}
|
||||
Record rec = it.next();
|
||||
protoAdapter.createRecord((int) rec.getKey(), rec.getLongValue(ADDR_COL),
|
||||
rec.getBinaryData(BYTES_COL), rec.getBooleanValue(DELAY_COL));
|
||||
@@ -287,19 +292,10 @@ class PrototypeManager {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// private boolean shouldSave(BigInteger value, BigInteger defaultValue) {
|
||||
// if (value == null) {
|
||||
// return false;
|
||||
// }
|
||||
// if (defaultValue == null) {
|
||||
// return true;
|
||||
// }
|
||||
// return !value.equals(defaultValue);
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the prototype with the given ID.
|
||||
* @param protoID prototype ID
|
||||
* @return instruction prototype or null if not found
|
||||
*/
|
||||
InstructionPrototype getPrototype(int protoID) {
|
||||
if (protoID < 0) {
|
||||
@@ -449,25 +445,16 @@ class PrototypeManager {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.lang.ProcessorContext#getRegister(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Register getRegister(String name) {
|
||||
return programContext.getRegister(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.lang.ProcessorContext#getRegisters()
|
||||
*/
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return programContext.getRegisters();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.lang.ProcessorContext#hasValue(ghidra.program.model.lang.Register)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasValue(Register register) {
|
||||
return false;
|
||||
|
||||
+12
-40
@@ -49,16 +49,14 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||
|
||||
private DBHandle dbHandle;
|
||||
private ErrorHandler errHandler;
|
||||
private Register[] registers;
|
||||
private Language language;
|
||||
private AddressMap addrMap;
|
||||
private int registerSpaceSize;
|
||||
private Lock lock;
|
||||
|
||||
/**
|
||||
* maintain values stored in registers for specified addresses and
|
||||
* address ranges using the PropertyMap utilities.
|
||||
*/
|
||||
private HashMap<String, Register> registersMap;
|
||||
private Map<Integer, AddressRangeMapDB> valueMaps;
|
||||
private Register baseContextRegister;
|
||||
protected Map<Register, RegisterValueStore> defaultRegisterValueMap;
|
||||
@@ -82,28 +80,12 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||
this.errHandler = errHandler;
|
||||
this.lock = lock;
|
||||
this.addrMap = addrMap.getOldAddressMap();
|
||||
this.registers = language.getRegisters();
|
||||
this.language = language;
|
||||
|
||||
defaultRegisterValueMap = new HashMap<Register, RegisterValueStore>();
|
||||
|
||||
registersMap = new HashMap<String, Register>();
|
||||
valueMaps = new HashMap<>();
|
||||
registerSpaceSize = 0;
|
||||
|
||||
for (Register register : registers) {
|
||||
String registerName = register.getName();
|
||||
registersMap.put(registerName.toUpperCase(), register);
|
||||
|
||||
int offset = (register.getOffset() & 0xffff);
|
||||
if (offset + register.getMinimumByteSize() > registerSpaceSize) {
|
||||
registerSpaceSize = offset + register.getMinimumByteSize();
|
||||
}
|
||||
}
|
||||
for (Register register : registers) {
|
||||
if (register.isProcessorContext()) {
|
||||
baseContextRegister = register.getBaseRegister();
|
||||
break;
|
||||
}
|
||||
}
|
||||
baseContextRegister = language.getContextBaseRegister();
|
||||
if (baseContextRegister == null) {
|
||||
baseContextRegister =
|
||||
new Register("DEFAULT_CONTEXT", "DEFAULT_CONTEXT",
|
||||
@@ -186,28 +168,18 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getProcessorStateRegisters() {
|
||||
List<Register> list = new ArrayList<Register>();
|
||||
for (Register register : registers) {
|
||||
if (register.isProcessorContext()) {
|
||||
list.add(register);
|
||||
}
|
||||
}
|
||||
return list.toArray(new Register[list.size()]);
|
||||
public List<Register> getContextRegisters() {
|
||||
return language.getContextRegisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register getRegister(String name) {
|
||||
return registersMap.get(name.toUpperCase());
|
||||
return language.getRegister(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRegisterNames() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (Register register : registers) {
|
||||
list.add(register.getName());
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
public List<String> getRegisterNames() {
|
||||
return language.getRegisterNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -273,8 +245,8 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
return registers;
|
||||
public List<Register> getRegisters() {
|
||||
return language.getRegisters();
|
||||
}
|
||||
|
||||
public long getSigned(Address addr, Register reg) throws UnsupportedOperationException {
|
||||
@@ -446,7 +418,7 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex
|
||||
public Register[] getRegistersWithValues() {
|
||||
if (registersWithValues == null) {
|
||||
List<Register> tmp = new ArrayList<Register>();
|
||||
for (Register register : registers) {
|
||||
for (Register register : getRegisters()) {
|
||||
AddressRangeIterator it = getRegisterValueAddressRanges(register);
|
||||
if (it.hasNext()) {
|
||||
tmp.add(register);
|
||||
|
||||
+12
-15
@@ -17,8 +17,7 @@ package ghidra.program.database.register;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.*;
|
||||
|
||||
import db.*;
|
||||
import db.util.ErrorHandler;
|
||||
@@ -49,8 +48,7 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||
public ProgramRegisterContextDB(DBHandle dbHandle, ErrorHandler errHandler, Language lang,
|
||||
CompilerSpec compilerSpec, AddressMap addrMap, Lock lock, int openMode,
|
||||
CodeManager codeMgr, TaskMonitor monitor) throws VersionException, CancelledException {
|
||||
|
||||
super(lang.getRegisters());
|
||||
super(lang);
|
||||
this.addrMap = addrMap;
|
||||
this.dbHandle = dbHandle;
|
||||
this.errorHandler = errHandler;
|
||||
@@ -68,7 +66,7 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||
initializedCurrentValues();
|
||||
|
||||
if (upgrade) {
|
||||
upgrade(addrMap, lang, monitor);
|
||||
upgrade(addrMap, monitor);
|
||||
}
|
||||
|
||||
if (openMode == DBConstants.UPGRADE && oldContextDataExists) {
|
||||
@@ -90,13 +88,13 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||
return false;
|
||||
}
|
||||
|
||||
private void upgrade(AddressMap addressMapExt, Language language, TaskMonitor monitor)
|
||||
private void upgrade(AddressMap addressMapExt, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
|
||||
OldProgramContextDB oldContext =
|
||||
new OldProgramContextDB(dbHandle, errorHandler, language, addressMapExt, lock);
|
||||
|
||||
for (Register register : registers) {
|
||||
for (Register register : language.getRegisters()) {
|
||||
if (register.getBaseRegister() != register) {
|
||||
continue;
|
||||
}
|
||||
@@ -306,16 +304,16 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||
AddressSetView programMemory, TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
if (translator == null) {
|
||||
Language lang = program.getLanguage();
|
||||
// Language instance unchanged
|
||||
boolean clearContext = Boolean.valueOf(
|
||||
lang.getProperty(GhidraLanguagePropertyKeys.RESET_CONTEXT_ON_UPGRADE));
|
||||
language.getProperty(GhidraLanguagePropertyKeys.RESET_CONTEXT_ON_UPGRADE));
|
||||
if (clearContext) {
|
||||
RegisterValueStore store = registerValueMap.get(baseContextRegister);
|
||||
if (store != null) {
|
||||
store.clearAll();
|
||||
}
|
||||
}
|
||||
initializeDefaultValues(lang, newCompilerSpec);
|
||||
initializeDefaultValues(language, newCompilerSpec);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -324,7 +322,8 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||
// Sort the registers by size so that largest come first.
|
||||
// This prevents the remove call below from incorrectly clearing
|
||||
// smaller registers that are part of a larger register.
|
||||
Arrays.sort(registers, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
|
||||
List<Register> registers = new ArrayList<Register>(language.getRegisters());
|
||||
Collections.sort(registers, (r1, r2) -> r2.getBitLength() - r1.getBitLength());
|
||||
|
||||
// Map all register stores to new registers
|
||||
for (Register register : registers) {
|
||||
@@ -350,11 +349,9 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
|
||||
registerValueMap.remove(register);
|
||||
}
|
||||
|
||||
initializeDefaultValues(newLanguage, newCompilerSpec);
|
||||
init(newLanguage);
|
||||
|
||||
registers = newLanguage.getRegisters();
|
||||
baseContextRegister = newLanguage.getContextBaseRegister();
|
||||
init();
|
||||
initializeDefaultValues(newLanguage, newCompilerSpec);
|
||||
|
||||
registerValueMap.clear();
|
||||
initializedCurrentValues();
|
||||
|
||||
+1
-2
@@ -558,8 +558,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
||||
newName = "";
|
||||
}
|
||||
else {
|
||||
SymbolUtilities.validateName(newName, address, getSymbolType(),
|
||||
symbolMgr.getAddressMap().getAddressFactory());
|
||||
SymbolUtilities.validateName(newName);
|
||||
nameChange = !oldName.equals(newName);
|
||||
if (!namespaceChange && !nameChange) {
|
||||
return;
|
||||
|
||||
+5
-5
@@ -2305,7 +2305,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
try {
|
||||
parent = validateNamespace(parent, addr, symbolType);
|
||||
source = validateSource(source, name, addr, symbolType);
|
||||
name = validateName(name, addr, symbolType, source);
|
||||
name = validateName(name, source);
|
||||
checkDuplicateSymbolName(addr, name, parent, symbolType);
|
||||
|
||||
return doCreateSymbol(name, addr, parent, symbolType, data1, data2, data3, source);
|
||||
@@ -2356,7 +2356,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
try {
|
||||
namespace = validateNamespace(namespace, addr, SymbolType.LABEL);
|
||||
source = validateSource(source, name, addr, SymbolType.LABEL);
|
||||
name = validateName(name, addr, SymbolType.LABEL, source);
|
||||
name = validateName(name, source);
|
||||
|
||||
Symbol symbol = getSymbol(name, addr, namespace);
|
||||
if (symbol != null) {
|
||||
@@ -2400,7 +2400,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
|
||||
namespace = validateNamespace(namespace, addr, SymbolType.FUNCTION);
|
||||
source = validateSource(source, name, addr, SymbolType.FUNCTION);
|
||||
name = validateName(name, addr, SymbolType.FUNCTION, source);
|
||||
name = validateName(name, source);
|
||||
|
||||
Symbol[] symbols = getSymbols(addr);
|
||||
|
||||
@@ -2510,12 +2510,12 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String validateName(String name, Address addr, SymbolType type, SourceType source)
|
||||
private String validateName(String name, SourceType source)
|
||||
throws InvalidInputException {
|
||||
if (source == SourceType.DEFAULT) {
|
||||
return "";
|
||||
}
|
||||
SymbolUtilities.validateName(name, addr, type, addrMap.getAddressFactory());
|
||||
SymbolUtilities.validateName(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
+3
-8
@@ -284,7 +284,7 @@ public class Disassembler implements DisassemblerConflictHandler {
|
||||
bmMgr = program.getBookmarkManager();
|
||||
}
|
||||
else {
|
||||
defaultLanguageContext = new ProgramContextImpl(language.getRegisters());
|
||||
defaultLanguageContext = new ProgramContextImpl(language);
|
||||
language.applyContextSettings(defaultLanguageContext);
|
||||
}
|
||||
|
||||
@@ -1496,11 +1496,6 @@ public class Disassembler implements DisassemblerConflictHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static Register[] getContextRegisters(Register baseContextRegister) {
|
||||
return baseContextRegister != null ? new Register[] { baseContextRegister }
|
||||
: new Register[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>DisassemblerProgramContext</code> is used as a proxy program context due to the
|
||||
* delayed nature of laying down instructions and their associated context state.
|
||||
@@ -1517,7 +1512,7 @@ public class Disassembler implements DisassemblerConflictHandler {
|
||||
private InstructionContext instructionContextCache = null;
|
||||
|
||||
DisassemblerProgramContext() {
|
||||
super(getContextRegisters(Disassembler.this.baseContextRegister));
|
||||
super(Disassembler.this.language);
|
||||
if (realProgramContext != null) {
|
||||
setDefaultDisassemblyContext(realProgramContext.getDefaultDisassemblyContext());
|
||||
}
|
||||
@@ -1732,7 +1727,7 @@ public class Disassembler implements DisassemblerConflictHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return langauge.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -566,7 +566,7 @@ public class DisassemblerContextImpl implements DisassemblerContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return programContext.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+40
-12
@@ -121,6 +121,8 @@ public interface Language {
|
||||
|
||||
/**
|
||||
* Return true if the instructions in this language support Pcode.
|
||||
*
|
||||
* @return true if language supports the use of pcode
|
||||
*/
|
||||
public boolean supportsPcode();
|
||||
|
||||
@@ -128,8 +130,8 @@ public interface Language {
|
||||
* Returns true if the language has defined the specified location as
|
||||
* volatile.
|
||||
*
|
||||
* @param addr
|
||||
* location address
|
||||
* @param addr location address
|
||||
* @return true if specified address is within a volatile range
|
||||
*/
|
||||
public boolean isVolatile(Address addr);
|
||||
|
||||
@@ -161,6 +163,8 @@ public interface Language {
|
||||
* Get the total number of user defined pcode names.
|
||||
*
|
||||
* Note: only works for Pcode based languages
|
||||
*
|
||||
* @return number of user defined pcodeops
|
||||
*/
|
||||
public int getNumberOfUserDefinedOpNames();
|
||||
|
||||
@@ -170,6 +174,9 @@ public interface Language {
|
||||
* known.
|
||||
*
|
||||
* Note: only works for Pcode based languages
|
||||
*
|
||||
* @param index user defined pcodeop index
|
||||
* @return pcodeop name or null if not defined
|
||||
*/
|
||||
public String getUserDefinedOpName(int index);
|
||||
|
||||
@@ -199,11 +206,21 @@ public interface Language {
|
||||
public Register getRegister(AddressSpace addrspc, long offset, int size);
|
||||
|
||||
/**
|
||||
* get the array of Register objects that this language supports.
|
||||
* Get an unsorted unmodifiable list of Register objects that this language defines
|
||||
* (including context registers).
|
||||
*
|
||||
* @return the array of processor registers.
|
||||
* @return unmodifiable list of processor registers.
|
||||
*/
|
||||
public Register[] getRegisters();
|
||||
public List<Register> getRegisters();
|
||||
|
||||
/**
|
||||
* Get 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 List<String> getRegisterNames();
|
||||
|
||||
/**
|
||||
* Get a register given the name of the register
|
||||
@@ -235,11 +252,20 @@ public interface Language {
|
||||
public Register getProgramCounter();
|
||||
|
||||
/**
|
||||
* Returns context base register or null if one has not been defined by the
|
||||
* Returns processor context base register or null if one has not been defined by the
|
||||
* language.
|
||||
* @return base context register or null if not defined
|
||||
*/
|
||||
public Register getContextBaseRegister();
|
||||
|
||||
/**
|
||||
* Get an unsorted unmodifiable list of processor context registers that this language defines
|
||||
* (includes context base register and its context field registers).
|
||||
*
|
||||
* @return unmodifiable list of processor registers.
|
||||
*/
|
||||
public List<Register> getContextRegisters();
|
||||
|
||||
/**
|
||||
* Returns the default memory blocks for this language.
|
||||
* @return the default memory blocks for this language
|
||||
@@ -277,16 +303,18 @@ public interface Language {
|
||||
public void applyContextSettings(DefaultProgramContext ctx);
|
||||
|
||||
/**
|
||||
* Refreshes the definition of this language if possible (statically defined
|
||||
* languages can safely do nothing).
|
||||
* Refreshes the definition of this language if possible. Use of this method is
|
||||
* intended for development purpose only since stale references to prior
|
||||
* language resources (e.g., registers) may persist.
|
||||
* @param taskMonitor monitor for progress back to the user
|
||||
* @throws IOException
|
||||
* @throws IOException if error occurs while reloading language spec file(s)
|
||||
*/
|
||||
public void reloadLanguage(TaskMonitor taskMonitor) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a list of all compatible compiler spec descriptions.
|
||||
* The first item in the list is the default.
|
||||
* @return list of all compatible compiler specifications descriptions
|
||||
*/
|
||||
public List<CompilerSpecDescription> getCompatibleCompilerSpecDescriptions();
|
||||
|
||||
@@ -384,9 +412,9 @@ public interface Language {
|
||||
public Exception getManualException();
|
||||
|
||||
/**
|
||||
* Returns the array of vector registers, sorted first by size and then by name.
|
||||
* @return sorted array of vector registers.
|
||||
* Returns an unmodifiable list of vector registers, sorted first by size and then by name.
|
||||
* @return unmodifiable list of vector registers.
|
||||
*/
|
||||
public Register[] getSortedVectorRegisters();
|
||||
public List<Register> getSortedVectorRegisters();
|
||||
|
||||
}
|
||||
|
||||
+23
-31
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +16,7 @@
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An implementation of processor context which contains the state of all
|
||||
@@ -29,47 +27,41 @@ import java.util.Map;
|
||||
*/
|
||||
public final class ProcessorContextImpl implements ProcessorContext {
|
||||
Map<Register, byte[]> values = new HashMap<Register, byte[]>();
|
||||
Register[] registers;
|
||||
Register baseContextRegister;
|
||||
Language language;
|
||||
|
||||
public ProcessorContextImpl(ProcessorContext context) {
|
||||
this(context.getRegisters());
|
||||
for (Register register : registers) {
|
||||
if (!register.isBaseRegister()) {
|
||||
continue;
|
||||
}
|
||||
if (register.isProcessorContext()) {
|
||||
baseContextRegister = register;
|
||||
}
|
||||
RegisterValue value = context.getRegisterValue(register);
|
||||
if (value != null) {
|
||||
setRegisterValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
// public ProcessorContextImpl(ProcessorContext context) {
|
||||
// this(context.getRegisters());
|
||||
// for (Register register : registers) {
|
||||
// if (!register.isBaseRegister()) {
|
||||
// continue;
|
||||
// }
|
||||
// if (register.isProcessorContext()) {
|
||||
// baseContextRegister = register;
|
||||
// }
|
||||
// RegisterValue value = context.getRegisterValue(register);
|
||||
// if (value != null) {
|
||||
// setRegisterValue(value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public ProcessorContextImpl(Register[] registers) {
|
||||
this.registers = registers;
|
||||
public ProcessorContextImpl(Language language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register getBaseContextRegister() {
|
||||
return baseContextRegister;
|
||||
return language.getContextBaseRegister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register getRegister(String name) {
|
||||
for (Register register : registers) {
|
||||
if (register.getName().equals(name)) {
|
||||
return register;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return language.getRegister(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
return registers;
|
||||
public List<Register> getRegisters() {
|
||||
return language.getRegisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -16,6 +16,7 @@
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defines the interface for an object containing the state
|
||||
@@ -30,10 +31,10 @@ public interface ProcessorContextView {
|
||||
public Register getBaseContextRegister();
|
||||
|
||||
/**
|
||||
* Returns all the Registers for the processor
|
||||
* Returns all the Registers for the processor as an unmodifiable list
|
||||
* @return all the Registers for the processor
|
||||
*/
|
||||
public Register[] getRegisters();
|
||||
public List<Register> getRegisters();
|
||||
|
||||
/**
|
||||
* Get a Register given the name of a register
|
||||
|
||||
+4
-14
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +15,13 @@
|
||||
*/
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.ContextChangeException;
|
||||
import ghidra.program.model.listing.ProgramContext;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Implementation for the program processor context interface
|
||||
*/
|
||||
@@ -45,17 +45,11 @@ public class ProgramProcessorContext implements ProcessorContext {
|
||||
return context.getBaseContextRegister();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.lang.ProcessorContext#getRegisters()
|
||||
*/
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return context.getRegisters();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.lang.ProcessorContext#getRegister(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Register getRegister(String name) {
|
||||
return context.getRegister(name);
|
||||
@@ -71,10 +65,6 @@ public class ProgramProcessorContext implements ProcessorContext {
|
||||
return context.getRegisterValue(register, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContextChangeException
|
||||
* @see ghidra.program.model.lang.ProcessorContext#setValue(ghidra.program.model.lang.Register, java.math.BigInteger)
|
||||
*/
|
||||
@Override
|
||||
public void setValue(Register register, BigInteger value) throws ContextChangeException {
|
||||
context.setValue(register, addr, addr, value);
|
||||
|
||||
+2
-2
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +21,7 @@ package ghidra.program.model.lang;
|
||||
*/
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public class ReadOnlyProcessorContext implements ProcessorContext {
|
||||
|
||||
@@ -42,7 +42,7 @@ public class ReadOnlyProcessorContext implements ProcessorContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return context.getRegisters();
|
||||
}
|
||||
|
||||
|
||||
+33
-31
@@ -18,11 +18,12 @@ package ghidra.program.model.lang;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public class RegisterBuilder {
|
||||
|
||||
ArrayList<Register> registerList;
|
||||
HashMap<String, Register> registerMap;
|
||||
Map<String, Register> registerMap; // include aliases and case-variations
|
||||
Address contextAddress;
|
||||
|
||||
public RegisterBuilder() {
|
||||
@@ -44,14 +45,19 @@ public class RegisterBuilder {
|
||||
}
|
||||
|
||||
public void addRegister(Register register) {
|
||||
Register aliasedReg = null;
|
||||
String name = register.getName();
|
||||
if (registerMap.get(name) != null) {
|
||||
Msg.error(this, "Duplicate register name: " + name);
|
||||
// TODO: should we throw exception - hopefully sleigh will prevent this condition
|
||||
}
|
||||
// Use of register alias handles case where context field is defined with different names
|
||||
for (Register reg : registerList) {
|
||||
if (reg.getAddress().equals(register.getAddress()) &&
|
||||
reg.getLeastSignificantBit() == register.getLeastSignificantBit() &&
|
||||
reg.getBitLength() == register.getBitLength()) {
|
||||
// define as register alias
|
||||
reg.addAlias(register.getName());
|
||||
registerMap.put(register.getName(), reg);
|
||||
reg.addAlias(name);
|
||||
addRegisterToNameMap(name, register);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -59,7 +65,19 @@ public class RegisterBuilder {
|
||||
contextAddress = register.getAddress();
|
||||
}
|
||||
registerList.add(register);
|
||||
registerMap.put(register.getName(), register);
|
||||
addRegisterToNameMap(name, register);
|
||||
}
|
||||
|
||||
private void addRegisterToNameMap(String name, Register register) {
|
||||
registerMap.put(name, register);
|
||||
registerMap.put(name.toLowerCase(), register);
|
||||
registerMap.put(name.toUpperCase(), register);
|
||||
}
|
||||
|
||||
private void removeRegisterFromNameMap(String name) {
|
||||
registerMap.remove(name);
|
||||
registerMap.remove(name.toLowerCase());
|
||||
registerMap.remove(name.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,31 +89,15 @@ public class RegisterBuilder {
|
||||
return contextAddress;
|
||||
}
|
||||
|
||||
public void removeRegister(String name) {
|
||||
Register register = registerMap.remove(name);
|
||||
if (register != null) {
|
||||
if (name.equals(register.getName())) {
|
||||
// name is primary - check for alias
|
||||
Iterator<String> iter = register.getAliases().iterator();
|
||||
if (!iter.hasNext()) {
|
||||
// no alias - remove register
|
||||
registerList.remove(register);
|
||||
}
|
||||
else {
|
||||
register.rename(iter.next());
|
||||
}
|
||||
}
|
||||
else {
|
||||
register.removeAlias(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute current register collection and instantiate a {@link RegisterManager}
|
||||
* @return new register manager instance
|
||||
*/
|
||||
public RegisterManager getRegisterManager() {
|
||||
return new RegisterManager(computeRegisters());
|
||||
return new RegisterManager(computeRegisters(), registerMap);
|
||||
}
|
||||
|
||||
private Register[] computeRegisters() {
|
||||
private List<Register> computeRegisters() {
|
||||
List<Register> regList = new LinkedList<>();
|
||||
List<Register> unprocessed = new LinkedList<>(registerList);
|
||||
|
||||
@@ -117,8 +119,7 @@ public class RegisterBuilder {
|
||||
}
|
||||
bitSize = nextLargerSize;
|
||||
}
|
||||
|
||||
return registerList.toArray(new Register[registerList.size()]);
|
||||
return registerList;
|
||||
}
|
||||
|
||||
private Register[] getChildren(Register parent, List<Register> regList) {
|
||||
@@ -159,6 +160,7 @@ public class RegisterBuilder {
|
||||
/**
|
||||
* Returns the register with the given name;
|
||||
* @param name the name of the register to retrieve
|
||||
* @return register or null if not found
|
||||
*/
|
||||
public Register getRegister(String name) {
|
||||
return registerMap.get(name);
|
||||
@@ -180,8 +182,8 @@ public class RegisterBuilder {
|
||||
return false;
|
||||
}
|
||||
register.rename(newName);
|
||||
registerMap.remove(oldName);
|
||||
registerMap.put(newName, register);
|
||||
removeRegisterFromNameMap(oldName);
|
||||
addRegisterToNameMap(newName, register);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+96
-52
@@ -17,19 +17,23 @@ package ghidra.program.model.lang;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.OldGenericNamespaceAddress;
|
||||
import ghidra.program.model.address.*;
|
||||
|
||||
public class RegisterManager {
|
||||
|
||||
Register[] registers;
|
||||
Register contextBaseRegister;
|
||||
Map<String, Register> registerNameMap = new HashMap<String, Register>();
|
||||
Map<RegisterSizeKey, Register> sizeMap = new HashMap<RegisterSizeKey, Register>();
|
||||
Map<Address, List<Register>> registerAddressMap = new HashMap<Address, List<Register>>();
|
||||
private List<Register> registers;
|
||||
private Map<String, Register> registerNameMap = new HashMap<String, Register>(); // include aliases and case-variations
|
||||
|
||||
private List<String> registerNames; // alphabetical sorted list, excludes aliases
|
||||
private List<Register> contextRegisters;
|
||||
private Register contextBaseRegister;
|
||||
|
||||
private Map<RegisterSizeKey, Register> sizeMap = new HashMap<RegisterSizeKey, Register>();
|
||||
private Map<Address, List<Register>> registerAddressMap =
|
||||
new HashMap<Address, List<Register>>();
|
||||
|
||||
/**Collection of vector registers, sorted first by size and then by offset**/
|
||||
private TreeSet<Register> sortedVectorRegisters;
|
||||
/**List of vector registers, sorted first by size and then by offset**/
|
||||
private List<Register> sortedVectorRegisters;
|
||||
|
||||
class RegisterSizeKey {
|
||||
Address address;
|
||||
@@ -74,21 +78,32 @@ public class RegisterManager {
|
||||
}
|
||||
};
|
||||
|
||||
RegisterManager(Register[] cookedRegisters) {
|
||||
registers = cookedRegisters;
|
||||
/**
|
||||
* Construct RegisterManager
|
||||
* @param registers all defined registers with appropriate parent-child relationships
|
||||
* properly established.
|
||||
* @param registerNameMap a complete name-to-register map including all register aliases
|
||||
* and alternate spellings (e.g., case-variations)
|
||||
*/
|
||||
RegisterManager(List<Register> registers, Map<String, Register> registerNameMap) {
|
||||
this.registers = Collections.unmodifiableList(registers);
|
||||
this.registerNameMap = Collections.unmodifiableMap(registerNameMap);
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
List<Register> registerList = new ArrayList<Register>(Arrays.asList(registers));
|
||||
Collections.sort(registerList, registerSizeComparator);
|
||||
for (Register reg : registerList) {
|
||||
registerNameMap.put(reg.getName(), reg);
|
||||
for (String alias : reg.getAliases()) {
|
||||
registerNameMap.put(alias, reg);
|
||||
}
|
||||
if (reg.isProcessorContext() && reg.isBaseRegister()) {
|
||||
contextBaseRegister = reg;
|
||||
List<String> registerNameList = new ArrayList<String>();
|
||||
List<Register> contextRegisterList = new ArrayList<Register>();
|
||||
ArrayList<Register> registerListSortedBySize = new ArrayList<>(registers); // copy for sorting
|
||||
Collections.sort(registerListSortedBySize, registerSizeComparator);
|
||||
for (Register reg : registerListSortedBySize) {
|
||||
String regName = reg.getName();
|
||||
registerNameList.add(regName);
|
||||
if (reg.isProcessorContext()) {
|
||||
contextRegisterList.add(reg);
|
||||
if (reg.isBaseRegister()) {
|
||||
contextBaseRegister = reg;
|
||||
}
|
||||
}
|
||||
|
||||
Address addr = reg.getAddress();
|
||||
@@ -110,10 +125,13 @@ public class RegisterManager {
|
||||
}
|
||||
}
|
||||
// handle the register size 0 case;
|
||||
Collections.reverse(registerList);
|
||||
for (Register register : registerList) {
|
||||
Collections.reverse(registerListSortedBySize);
|
||||
for (Register register : registerListSortedBySize) {
|
||||
sizeMap.put(new RegisterSizeKey(register.getAddress(), 0), register);
|
||||
}
|
||||
contextRegisters = Collections.unmodifiableList(contextRegisterList);
|
||||
Collections.sort(registerNameList);
|
||||
registerNames = Collections.unmodifiableList(registerNameList);
|
||||
}
|
||||
|
||||
private void populateSizeMapBigEndian(Register reg) {
|
||||
@@ -132,33 +150,54 @@ public class RegisterManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns context base register or null if one has not been defined by the language.
|
||||
* Get context base-register
|
||||
* @return context base register or null if one has not been defined by the language.
|
||||
*/
|
||||
public Register getContextBaseRegister() {
|
||||
return contextBaseRegister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest register located at the specified address
|
||||
* Get unsorted unmodifiable list of all processor context registers (include base context register and children)
|
||||
* @return all processor context registers
|
||||
*/
|
||||
public List<Register> getContextRegisters() {
|
||||
return contextRegisters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param addr
|
||||
* @return largest register
|
||||
* @return alphabetical sorted unmodifiable list of original register names.
|
||||
*/
|
||||
public List<String> getRegisterNames() {
|
||||
return registerNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest register located at the specified address
|
||||
* @param addr register address
|
||||
* @return register or null if not found
|
||||
*/
|
||||
public Register getRegister(Address addr) {
|
||||
if (!addr.isRegisterAddress() && !addr.getAddressSpace().hasMappedRegisters()) {
|
||||
return null;
|
||||
AddressSpace space = addr.getAddressSpace();
|
||||
if (space.isRegisterSpace() || space.hasMappedRegisters()) {
|
||||
return sizeMap.get(new RegisterSizeKey(addr, 0));
|
||||
}
|
||||
return sizeMap.get(new RegisterSizeKey(addr, 0));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all registers located at the specified address
|
||||
*
|
||||
* @param addr
|
||||
* @return largest register
|
||||
* @param addr register address
|
||||
* @return array of registers found (may be empty)
|
||||
*/
|
||||
public Register[] getRegisters(Address addr) {
|
||||
if (addr.isRegisterAddress() || addr.getAddressSpace().hasMappedRegisters()) {
|
||||
AddressSpace space = addr.getAddressSpace();
|
||||
if (space.isRegisterSpace() || space.hasMappedRegisters()) {
|
||||
List<Register> list = registerAddressMap.get(getGlobalAddress(addr));
|
||||
if (list != null) {
|
||||
Register[] regs = new Register[list.size()];
|
||||
@@ -177,50 +216,55 @@ public class RegisterManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smallest register at the specified address whose size is
|
||||
* greater than or equal the specified size.
|
||||
* Get register by address and size
|
||||
* @param addr register address
|
||||
* @param size the size of the register (in bytes). A value of 0 will return the
|
||||
* largest register at the specified addr
|
||||
* @return register
|
||||
* @param size register size
|
||||
* @return register or null if not found
|
||||
*/
|
||||
public Register getRegister(Address addr, int size) {
|
||||
if (!addr.isRegisterAddress() && !addr.getAddressSpace().hasMappedRegisters()) {
|
||||
return null;
|
||||
AddressSpace space = addr.getAddressSpace();
|
||||
if (space.isRegisterSpace() || space.hasMappedRegisters()) {
|
||||
return sizeMap.get(new RegisterSizeKey(addr, size));
|
||||
}
|
||||
return sizeMap.get(new RegisterSizeKey(addr, size));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the register with the given name;
|
||||
* @param name the name of the register to retrieve
|
||||
* Get register by name. A semi-case-insensitive lookup is performed.
|
||||
* The specified name must match either the case-sensitive name or
|
||||
* be entirely lowercase or uppercase.
|
||||
* @param name register name
|
||||
* @return register or null if not found
|
||||
*/
|
||||
public Register getRegister(String name) {
|
||||
return registerNameMap.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of all registers.
|
||||
* @return all registers
|
||||
* Get all registers as an unsorted unmodifiable list.
|
||||
* @return unmodifiable list of all registers defined
|
||||
*/
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of vector registers, sorted first by size and then by offset
|
||||
* @return sorted vector registers
|
||||
* Get an unmodifiable list of all vector registers indentified by the processor specification
|
||||
* in sorted order based upon address and size.
|
||||
* @return all vector registers as unmodifiable list
|
||||
*/
|
||||
public Register[] getSortedVectorRegisters() {
|
||||
public List<Register> getSortedVectorRegisters() {
|
||||
if (sortedVectorRegisters == null) {
|
||||
sortedVectorRegisters = new TreeSet<Register>(RegisterManager::compareVectorRegisters);
|
||||
for (Register reg : getRegisters()) {
|
||||
ArrayList<Register> list = new ArrayList<Register>();
|
||||
for (Register reg : registers) {
|
||||
if (reg.isVectorRegister()) {
|
||||
sortedVectorRegisters.add(reg);
|
||||
list.add(reg);
|
||||
}
|
||||
}
|
||||
Collections.sort(list, RegisterManager::compareVectorRegisters);
|
||||
sortedVectorRegisters = Collections.unmodifiableList(list);
|
||||
}
|
||||
return sortedVectorRegisters.toArray(new Register[0]);
|
||||
return sortedVectorRegisters;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+14
-26
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,36 +15,33 @@
|
||||
*/
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
public class RegisterTranslator {
|
||||
private static Comparator<Register> registerSizeComparator = new Comparator<Register>() {
|
||||
@Override
|
||||
public int compare(Register r1, Register r2) {
|
||||
// Used for sorting largest to smallest
|
||||
return r2.getBitLength() - r1.getBitLength();
|
||||
}
|
||||
};
|
||||
|
||||
private Register[] oldRegs;
|
||||
private Register[] newRegs;
|
||||
private Language oldLang;
|
||||
private Language newLang;
|
||||
|
||||
private HashMap<Integer, List<Register>> oldRegisterMap;
|
||||
private HashMap<Integer, List<Register>> newRegisterMap;
|
||||
private HashMap<String, Register> oldRegisterNameMap;
|
||||
private HashMap<String, Register> newRegisterNameMap;
|
||||
|
||||
public RegisterTranslator(Language oldLang, Language newLang) {
|
||||
oldRegs = oldLang.getRegisters();
|
||||
newRegs = newLang.getRegisters();
|
||||
this.oldRegisterMap = buildOffsetMap(oldRegs);
|
||||
this.newRegisterMap = buildOffsetMap(newRegs);
|
||||
oldRegisterNameMap = buildNameMap(oldRegs);
|
||||
newRegisterNameMap = buildNameMap(newRegs);
|
||||
this.oldLang = oldLang;
|
||||
this.newLang = newLang;
|
||||
this.oldRegisterMap = buildOffsetMap(oldLang.getRegisters());
|
||||
this.newRegisterMap = buildOffsetMap(newLang.getRegisters());
|
||||
}
|
||||
|
||||
private HashMap<Integer, List<Register>> buildOffsetMap(Register[] registers) {
|
||||
private HashMap<Integer, List<Register>> buildOffsetMap(List<Register> registers) {
|
||||
HashMap<Integer, List<Register>> offsetMap = new HashMap<Integer, List<Register>>();
|
||||
for (Register register : registers) {
|
||||
Address addr = register.getAddress();
|
||||
@@ -69,14 +65,6 @@ public class RegisterTranslator {
|
||||
return offsetMap;
|
||||
}
|
||||
|
||||
private HashMap<String, Register> buildNameMap(Register[] regs) {
|
||||
HashMap<String, Register> map = new HashMap<String, Register>();
|
||||
for (Register r : regs) {
|
||||
map.put(r.getName().toUpperCase(), r);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public Register getOldRegister(int offset, int size) {
|
||||
List<Register> list = oldRegisterMap.get(offset);
|
||||
if (list != null) {
|
||||
@@ -110,15 +98,15 @@ public class RegisterTranslator {
|
||||
}
|
||||
|
||||
public Register getNewRegister(Register oldReg) {
|
||||
return newRegisterNameMap.get(oldReg.getName().toUpperCase());
|
||||
return newLang.getRegister(oldReg.getName());
|
||||
}
|
||||
|
||||
public Register getOldRegister(Register newReg) {
|
||||
return oldRegisterNameMap.get(newReg.getName().toUpperCase());
|
||||
return oldLang.getRegister(newReg.getName());
|
||||
}
|
||||
|
||||
public Register[] getNewRegisters() {
|
||||
return newRegs;
|
||||
public List<Register> getNewRegisters() {
|
||||
return newLang.getRegisters();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -340,7 +340,7 @@ public class InstructionStub implements Instruction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
+27
-12
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package ghidra.program.model.listing;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Interface to define a processor register context over the address space.
|
||||
*/
|
||||
@@ -34,14 +35,14 @@ public interface ProgramContext {
|
||||
|
||||
/**
|
||||
* Modify register value to eliminate non-flowing bits
|
||||
* @param value
|
||||
* @param value register value to be modified
|
||||
* @return value suitable for flowing
|
||||
*/
|
||||
public RegisterValue getFlowValue(RegisterValue value);
|
||||
|
||||
/**
|
||||
* Modify register value to only include non-flowing bits
|
||||
* @param value
|
||||
* @param value register value to be modified
|
||||
* @return new value or null
|
||||
*/
|
||||
public RegisterValue getNonFlowValue(RegisterValue value);
|
||||
@@ -57,9 +58,9 @@ public interface ProgramContext {
|
||||
/**
|
||||
* Get all the register descriptions defined for this program context.
|
||||
*
|
||||
* @return array of defined register descriptions
|
||||
* @return unmodifiable list of defined register descriptions
|
||||
*/
|
||||
public Register[] getRegisters();
|
||||
public List<Register> getRegisters();
|
||||
|
||||
/**
|
||||
* Returns an array of all registers that at least one value associated with an address.
|
||||
@@ -92,6 +93,8 @@ public interface ProgramContext {
|
||||
* @param start the start address to set values
|
||||
* @param end the end address to set values
|
||||
* @param value the actual values to store at address
|
||||
* @throws ContextChangeException if failed to modifiy context across specified range
|
||||
* (e.g., instruction exists).
|
||||
*/
|
||||
public void setRegisterValue(Address start, Address end, RegisterValue value)
|
||||
throws ContextChangeException;
|
||||
@@ -112,6 +115,8 @@ public interface ProgramContext {
|
||||
* @param start the start address.
|
||||
* @param end the end address (inclusive).
|
||||
* @param value the value to assign. A value of null will effective clear any existing values.
|
||||
* @throws ContextChangeException if failed to modifiy context across specified range
|
||||
* (e.g., instruction exists).
|
||||
*/
|
||||
public void setValue(Register register, Address start, Address end, BigInteger value)
|
||||
throws ContextChangeException;
|
||||
@@ -130,6 +135,8 @@ public interface ProgramContext {
|
||||
* given range for the given register. Each range returned will have the same value
|
||||
* associated with the register for all addresses in that range.
|
||||
* @param register the register for which to get set value ranges.
|
||||
* @param start start of address range to search
|
||||
* @param end end of address range to search
|
||||
* @return An AddressRangeIterator over all address within the given range that have values
|
||||
* for the given register.
|
||||
*/
|
||||
@@ -139,8 +146,8 @@ public interface ProgramContext {
|
||||
/**
|
||||
* Returns the bounding address-range containing addr and the the same RegisterValue throughout.
|
||||
* The range returned may be limited by other value changes associated with register's base-register.
|
||||
* @param register
|
||||
* @param addr
|
||||
* @param register program register
|
||||
* @param addr program address
|
||||
* @return single register-value address-range containing addr
|
||||
*/
|
||||
public AddressRange getRegisterValueRangeContaining(Register register, Address addr);
|
||||
@@ -159,6 +166,8 @@ public interface ProgramContext {
|
||||
* given range for the given register. Each range returned will have the same default value
|
||||
* associated with the register for all addresses in that range.
|
||||
* @param register the register for which to get default value ranges.
|
||||
* @param start start of address range to search
|
||||
* @param end end of address range to search
|
||||
* @return An AddressRangeIterator over all address within the given range that have default values
|
||||
* for the given register.
|
||||
*/
|
||||
@@ -169,20 +178,26 @@ public interface ProgramContext {
|
||||
* Gets the registers for this context that are used for processor context states.
|
||||
* @return all processor context registers
|
||||
*/
|
||||
public Register[] getProcessorStateRegisters();
|
||||
public List<Register> getContextRegisters();
|
||||
|
||||
/**
|
||||
* Remove (unset) the register values for a given address range.
|
||||
* @param start starting address.
|
||||
* @param end ending adddress.
|
||||
* @param register handle to the register to be set.
|
||||
* @throws ContextChangeException thrown if context change not permitted over specified
|
||||
* range (e.g., instructions exist)
|
||||
*/
|
||||
public void remove(Address start, Address end, Register register) throws ContextChangeException;
|
||||
|
||||
/**
|
||||
* Returns the list of register names
|
||||
* Get an alphabetical sorted unmodifiable list of original register names
|
||||
* (including context registers). Names correspond to orignal register
|
||||
* name and not aliases which may be defined.
|
||||
*
|
||||
* @return alphabetical sorted unmodifiable list of original register names.
|
||||
*/
|
||||
public String[] getRegisterNames();
|
||||
public List<String> getRegisterNames();
|
||||
|
||||
/**
|
||||
* Returns true if the given register has the value over the addressSet
|
||||
@@ -224,7 +239,7 @@ public interface ProgramContext {
|
||||
* from the default disassembly context and the context register value stored
|
||||
* at the specified address. Those bits specified by the stored context value
|
||||
* take precedence.
|
||||
* @param address
|
||||
* @param address program address
|
||||
* @return disassembly context register value
|
||||
*/
|
||||
public RegisterValue getDisassemblyContext(Address address);
|
||||
|
||||
+6
-3
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.listing.Program;
|
||||
@@ -50,8 +52,9 @@ public class VarnodeTranslator {
|
||||
* @return Register or null if node is not a register
|
||||
*/
|
||||
public Register getRegister(Varnode node) {
|
||||
if (node == null)
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return language.getRegister(node.getAddress(), node.getSize());
|
||||
}
|
||||
@@ -72,9 +75,9 @@ public class VarnodeTranslator {
|
||||
* Get all defined registers for the program this translator was created
|
||||
* with.
|
||||
*
|
||||
* @return all defined registers
|
||||
* @return all defined registers as unmodifiable list
|
||||
*/
|
||||
public Register[] getRegisters() {
|
||||
public List<Register> getRegisters() {
|
||||
return language.getRegisters();
|
||||
}
|
||||
}
|
||||
|
||||
+26
-6
@@ -219,11 +219,10 @@ public class SymbolUtilities {
|
||||
/**
|
||||
* Validate the given symbol name: cannot be null, cannot be an empty string, cannot contain blank
|
||||
* characters, cannot be a reserved name.
|
||||
* NOTE: This is not infallible since default data labels can start with any data-type name
|
||||
* @param name symbol name to be validated
|
||||
* @throws InvalidInputException invalid or reserved name has been specified
|
||||
*/
|
||||
public static void validateName(String name, Address address, SymbolType symbolType,
|
||||
AddressFactory addrFactory) throws InvalidInputException {
|
||||
public static void validateName(String name) throws InvalidInputException {
|
||||
|
||||
if (name == null) {
|
||||
throw new InvalidInputException("Symbol name can't be null");
|
||||
@@ -243,6 +242,7 @@ public class SymbolUtilities {
|
||||
/**
|
||||
* Returns true if the given name starts with a possible default symbol prefix.
|
||||
* @param name the name string to test.
|
||||
* @return true if name starts with a know dynamic prefix
|
||||
*/
|
||||
public static boolean startsWithDefaultDynamicPrefix(String name) {
|
||||
for (String element : DYNAMIC_PREFIX_ARRAY) {
|
||||
@@ -279,9 +279,11 @@ public class SymbolUtilities {
|
||||
/**
|
||||
* Tests if the given name is a possible dynamic symbol name.
|
||||
* WARNING! This method should be used carefully since it will return true for
|
||||
* any name which ends with an '_' followed by a valid hex value
|
||||
* any name which starts with a known dynamic label prefix or ends with an '_'
|
||||
* followed by a valid hex value.
|
||||
* @param name the name to test
|
||||
* @param caseSensitive true if case matters.
|
||||
* @return true if name is a possible dynamic symbol name, else false
|
||||
*/
|
||||
public static boolean isDynamicSymbolPattern(String name, boolean caseSensitive) {
|
||||
|
||||
@@ -330,6 +332,7 @@ public class SymbolUtilities {
|
||||
* Returns true if the specified char
|
||||
* is not valid for use in a symbol name
|
||||
* @param c the character to be tested as a valid symbol character.
|
||||
* @return return true if c is an invalid char within a symbol name, else false
|
||||
*/
|
||||
public static boolean isInvalidChar(char c) {
|
||||
if (c < ' ') { // non-printable ASCII
|
||||
@@ -354,6 +357,7 @@ public class SymbolUtilities {
|
||||
* @param str the string to have invalid chars converted to underscores or removed.
|
||||
* @param replaceWithUnderscore - true means replace the invalid
|
||||
* chars with underscore. if false, then just drop the invalid chars
|
||||
* @return modified string
|
||||
*/
|
||||
public static String replaceInvalidChars(String str, boolean replaceWithUnderscore) {
|
||||
if (str == null) {
|
||||
@@ -376,8 +380,9 @@ public class SymbolUtilities {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a name for an offcut reference.
|
||||
* Create a dynamic label name for an offcut reference.
|
||||
* @param addr the address at which to create an offcut reference name.
|
||||
* @return dynamic offcut label name
|
||||
*/
|
||||
public static String getDynamicOffcutName(Address addr) {
|
||||
if (addr != null) {
|
||||
@@ -387,9 +392,13 @@ public class SymbolUtilities {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a name for a dynamic symbol
|
||||
* Create a name for a dynamic symbol with a 3-letter prefix based upon reference level
|
||||
* and an address. Acceptable referenceLevel's are:
|
||||
* {@link #UNK_LEVEL}, {@link #DAT_LEVEL}, {@link #LAB_LEVEL}, {@link #SUB_LEVEL},
|
||||
* {@link #EXT_LEVEL}, {@link #FUN_LEVEL}.
|
||||
* @param referenceLevel the type of reference for which to create a dynamic name.
|
||||
* @param addr the address at which to create a dynamic name.
|
||||
* @return dynamic symbol name
|
||||
*/
|
||||
public static String getDynamicName(int referenceLevel, Address addr) {
|
||||
if (addr != null) {
|
||||
@@ -558,9 +567,18 @@ public class SymbolUtilities {
|
||||
|
||||
/**
|
||||
* Parse a dynamic name and return its address or null if unable to parse.
|
||||
* @param factory address factory
|
||||
* @param name the dynamic label name to parse into an address.
|
||||
* @return address corresponding to symbol name if it satisfies possible dynamic naming
|
||||
* or null if unable to parse address fro name
|
||||
*/
|
||||
public static Address parseDynamicName(AddressFactory factory, String name) {
|
||||
|
||||
// assume dynamic names will naver start with an underscore
|
||||
if (name.startsWith(UNDERSCORE)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] pieces = name.split(UNDERSCORE);
|
||||
if (pieces.length < 2) { // if we have less than two pieces, then this is not a dynamic name.
|
||||
return null;
|
||||
@@ -913,6 +931,7 @@ public class SymbolUtilities {
|
||||
* @param program the program to search.
|
||||
* @param symbolName the name of the global label or function symbol to search.
|
||||
* @param errorConsumer the object to use for reporting errors via it's accept() method.
|
||||
* @return symbol if a unique label/function symbol with name is found or null
|
||||
*/
|
||||
public static Symbol getExpectedLabelOrFunctionSymbol(Program program, String symbolName,
|
||||
Consumer<String> errorConsumer) {
|
||||
@@ -938,6 +957,7 @@ public class SymbolUtilities {
|
||||
* @param program the program to search.
|
||||
* @param symbolName the name of the global label or function symbol to search.
|
||||
* @param errorConsumer the object to use for reporting errors via it's accept() method.
|
||||
* @return symbol if a unique label/function symbol with name is found or null
|
||||
*/
|
||||
public static Symbol getLabelOrFunctionSymbol(Program program, String symbolName,
|
||||
Consumer<String> errorConsumer) {
|
||||
|
||||
+36
-60
@@ -15,19 +15,19 @@
|
||||
*/
|
||||
package ghidra.program.util;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.DefaultProgramContext;
|
||||
import ghidra.program.model.listing.ProgramContext;
|
||||
|
||||
abstract public class AbstractProgramContext implements ProgramContext, DefaultProgramContext {
|
||||
|
||||
protected Register[] registers;
|
||||
protected Language language;
|
||||
|
||||
protected Register baseContextRegister;
|
||||
private Map<String, Register> registerNameMap; // lazy initialized only when getRegister(name) called
|
||||
|
||||
private boolean hasNonFlowingContext = false;
|
||||
private byte[] nonFlowingContextRegisterMask;
|
||||
@@ -35,17 +35,16 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
|
||||
|
||||
protected RegisterValue defaultDisassemblyContext;
|
||||
|
||||
protected AbstractProgramContext(Register[] registers) {
|
||||
this.registers = registers;
|
||||
protected AbstractProgramContext(Language language) {
|
||||
init(language);
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
if (baseContextRegister != null) {
|
||||
nonFlowingContextRegisterMask = baseContextRegister.getBaseMask().clone();
|
||||
Arrays.fill(nonFlowingContextRegisterMask, (byte) 0);
|
||||
flowingContextRegisterMask = nonFlowingContextRegisterMask.clone();
|
||||
initContextBitMasks(baseContextRegister);
|
||||
}
|
||||
/**
|
||||
* Get underlying language associated with this context and its registers
|
||||
* @return language
|
||||
*/
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +84,7 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
|
||||
|
||||
/**
|
||||
* Modify register value to eliminate non-flowing bits
|
||||
* @param value
|
||||
* @param value context register value to be modified
|
||||
* @return value suitable for flowing
|
||||
*/
|
||||
@Override
|
||||
@@ -98,8 +97,9 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
|
||||
|
||||
/**
|
||||
* Modify register value to only include non-flowing bits
|
||||
* @param value
|
||||
* @return new value or null
|
||||
* @param value context register value to be modified
|
||||
* @return new value or null if value does not correspond to a context register or
|
||||
* non-flowing context fields have not been defined
|
||||
*/
|
||||
@Override
|
||||
public final RegisterValue getNonFlowValue(RegisterValue value) {
|
||||
@@ -109,67 +109,43 @@ abstract public class AbstractProgramContext implements ProgramContext, DefaultP
|
||||
return value.clearBitValues(flowingContextRegisterMask);
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
registerNameMap = null;
|
||||
baseContextRegister = null;
|
||||
for (Register register : registers) {
|
||||
if (register.isProcessorContext()) {
|
||||
baseContextRegister = register.getBaseRegister();
|
||||
break; // should only be one
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Initialize context for the specified language
|
||||
* @param lang processor language for which this context applies
|
||||
*/
|
||||
protected void init(Language lang) {
|
||||
this.language = lang;
|
||||
baseContextRegister = lang.getContextBaseRegister();
|
||||
if (baseContextRegister == null) {
|
||||
baseContextRegister =
|
||||
new Register("DEFAULT_CONTEXT", "DEFAULT_CONTEXT", Address.NO_ADDRESS, 4, true, 0);
|
||||
}
|
||||
defaultDisassemblyContext = new RegisterValue(baseContextRegister);
|
||||
}
|
||||
|
||||
private Map<String, Register> getRegisterNameMap() {
|
||||
if (registerNameMap != null) {
|
||||
return registerNameMap;
|
||||
}
|
||||
// if register map hasn't been initialized, initialize it
|
||||
registerNameMap = new HashMap<String, Register>();
|
||||
|
||||
// NOTE: if you want upper case names recognized, override this method and add them
|
||||
for (Register register : registers) {
|
||||
registerNameMap.put(register.getName(), register);
|
||||
for (String alias : register.getAliases()) {
|
||||
registerNameMap.put(alias, register);
|
||||
}
|
||||
}
|
||||
return registerNameMap;
|
||||
nonFlowingContextRegisterMask = baseContextRegister.getBaseMask().clone();
|
||||
Arrays.fill(nonFlowingContextRegisterMask, (byte) 0);
|
||||
flowingContextRegisterMask = nonFlowingContextRegisterMask.clone();
|
||||
initContextBitMasks(baseContextRegister);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Register[] getProcessorStateRegisters() {
|
||||
List<Register> list = new ArrayList<Register>();
|
||||
for (Register register : registers) {
|
||||
if (register.isProcessorContext()) {
|
||||
list.add(register);
|
||||
}
|
||||
}
|
||||
return list.toArray(new Register[list.size()]);
|
||||
public final List<Register> getContextRegisters() {
|
||||
return language.getContextRegisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Register getRegister(String name) {
|
||||
return getRegisterNameMap().get(name);
|
||||
return language.getRegister(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String[] getRegisterNames() {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (Register register : registers) {
|
||||
list.add(register.getName());
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
public final List<String> getRegisterNames() {
|
||||
return language.getRegisterNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Register[] getRegisters() {
|
||||
return registers;
|
||||
public final List<Register> getRegisters() {
|
||||
return language.getRegisters();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-5
@@ -20,8 +20,7 @@ import java.util.*;
|
||||
|
||||
import ghidra.program.database.register.InMemoryRangeMapAdapter;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.ContextChangeException;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@@ -34,8 +33,8 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
|
||||
|
||||
private Set<Register> registersWithValues; // cached set, recomputed whenever null
|
||||
|
||||
protected AbstractStoredProgramContext(Register[] registers) {
|
||||
super(registers);
|
||||
protected AbstractStoredProgramContext(Language language) {
|
||||
super(language);
|
||||
registerValueMap = new HashMap<>();
|
||||
defaultRegisterValueMap = new HashMap<>();
|
||||
}
|
||||
@@ -206,7 +205,7 @@ abstract public class AbstractStoredProgramContext extends AbstractProgramContex
|
||||
public Register[] getRegistersWithValues() {
|
||||
if (registersWithValues == null) {
|
||||
registersWithValues = new HashSet<>();
|
||||
for (Register register : registers) {
|
||||
for (Register register : language.getRegisters()) {
|
||||
RegisterValueStore store = registerValueMap.get(register.getBaseRegister());
|
||||
if (store != null && !store.isEmpty()) {
|
||||
registersWithValues.add(register);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user