diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java
index 83c1f6dda7..3bbebfbc22 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java
@@ -150,7 +150,13 @@ public class ConstantPropagationAnalyzer extends AbstractAnalyzer {
// unless there is a good data type at the location
boolean isHarvard = program.getLanguage().getDefaultSpace() != program.getLanguage().getDefaultDataSpace();
checkPointerParamRefsOption = program.getDefaultPointerSize() <= 2 || isHarvard;
+
+ checkStoredRefsOption = program.getDefaultPointerSize() > 2 && !isHarvard;
+ long size = program.getAddressFactory().getDefaultAddressSpace().getSize();
+ minSpeculativeRefAddress = size * 16;
+ maxSpeculativeRefAddress = size * 8;
+
checkParamRefsOption = !(program.getAddressFactory()
.getDefaultAddressSpace() instanceof SegmentedAddressSpace);
@@ -570,12 +576,9 @@ public class ConstantPropagationAnalyzer extends AbstractAnalyzer {
options.registerOption(MIN_KNOWN_REFADDRESS_OPTION_NAME, minStoreLoadRefAddress, null,
MIN_KNOWN_REFADDRESS_OPTION_DESCRIPTION);
- long size = program.getAddressFactory().getDefaultAddressSpace().getSize();
- minSpeculativeRefAddress = size * 16;
options.registerOption(MIN_SPECULATIVE_REFADDRESS_OPTION_NAME, minSpeculativeRefAddress, null,
MIN_SPECULATIVE_REFADDRESS_OPTION_DESCRIPTION);
- maxSpeculativeRefAddress = size * 8;
options.registerOption(MAX_SPECULATIVE_REFADDRESS_OPTION_NAME, maxSpeculativeRefAddress, null,
MAX_SPECULATIVE_REFADDRESS_OPTION_DESCRIPTION);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
index 0dbe506d16..580072b8f4 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -76,6 +76,7 @@ public class VarnodeContext implements ProcessorContext {
private final int BAD_OFFSET_SPACEID; // address space for offsets from an unknown value;
+ static final String SUSPECT_CONST_NAME = "SuspectConst";
private final int SUSPECT_OFFSET_SPACEID; // address space for suspect constant values
public final Address SUSPECT_ZERO_ADDRESS;
@@ -109,7 +110,7 @@ public class VarnodeContext implements ProcessorContext {
/* Suspect constants act like constants, but are in a SuspectConst
* address space instead of the constant space.
*/
- SUSPECT_ZERO_ADDRESS = addrFactory.getAddress(getAddressSpace("SuspectConst"), 0);
+ SUSPECT_ZERO_ADDRESS = addrFactory.getAddress(getAddressSpace(SUSPECT_CONST_NAME), 0);
SUSPECT_OFFSET_SPACEID = SUSPECT_ZERO_ADDRESS.getAddressSpace().getSpaceID();
this.programContext = programContext;
@@ -1754,6 +1755,20 @@ class OffsetAddressFactory extends DefaultAddressFactory {
}
}
}
+ try {
+ // Use JOIN type space for suspect constants, it is used by the decompiler, so can
+ // be repurposed for this algorithm.
+ // Hack for current storage allows suspect constants to fit in a byte. The current
+ // algorithm is sensitive to the space ID value and must be less than 0x7f. Only types that are
+ // between 0-16 will work correctly because of how the spaceID is calculated based on the space type.
+ // The spaceID is computed using the type.
+ AddressSpace suspectConstspc = new GenericAddressSpace(VarnodeContext.SUSPECT_CONST_NAME, 64,
+ AddressSpace.TYPE_JOIN, 0);
+ addAddressSpace(suspectConstspc);
+ }
+ catch (DuplicateNameException e) {
+ throw new AssertException("Duplicate name should not occur.");
+ }
try {
addAddressSpace(AddressSpace.EXTERNAL_SPACE);
}
diff --git a/Ghidra/Processors/PIC/data/languages/pic16.ldefs b/Ghidra/Processors/PIC/data/languages/pic16.ldefs
index af82b20edb..94d988f255 100644
--- a/Ghidra/Processors/PIC/data/languages/pic16.ldefs
+++ b/Ghidra/Processors/PIC/data/languages/pic16.ldefs
@@ -14,7 +14,6 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -40,6 +136,14 @@
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/PIC/data/languages/pic16.sinc b/Ghidra/Processors/PIC/data/languages/pic16.sinc
index d7144dae17..68207af119 100644
--- a/Ghidra/Processors/PIC/data/languages/pic16.sinc
+++ b/Ghidra/Processors/PIC/data/languages/pic16.sinc
@@ -2,28 +2,6 @@
# PIC-16 Main Section
# includes constants, memory space and common register space definitions
#
-
-# STATUS bit definitions
-@define STATUS_IRP_BIT 7
-@define STATUS_RP0_BIT 5
-@define STATUS_Z_BIT 2
-@define STATUS_DC_BIT 1
-@define STATUS_C_BIT 0
-
-# STATUS bit masks used for setting
-@define STATUS_IRP_MASK 0x80
-@define STATUS_RP_MASK 0x60
-@define STATUS_Z_MASK 0x04
-@define STATUS_DC_MASK 0x02
-@define STATUS_C_MASK 0x01
-
-# STATUS bit masks used for clearing
-@define STATUS_IRP_CLEARMASK 0x7F
-@define STATUS_RP_CLEARMASK 0x9F
-@define STATUS_Z_CLEARMASK 0xFB
-@define STATUS_DC_CLEARMASK 0xFD
-@define STATUS_C_CLEARMASK 0xFE
-
define endian=little;
define alignment=2;
@@ -50,18 +28,37 @@ define register offset=0x0002 size=1 [ STKPTR ];
define register offset=0x0003 size=1 [ W SkipNext ];
# Status bit registers (these do not really exist and must get reflected into the STATUS byte register)
-@if PROCESSOR == "PIC_16"
define register offset=0x0007 size=1 [ IRP RP ];
-@elif PROCESSOR == "PIC_16F"
-define register offset=0x0007 size=1 [ IRP RP ];
-@endif
@define C "STATUS[0,1]"
@define DC "STATUS[1,1]"
@define Z "STATUS[2,1]"
@define PD "STATUS[3,1]"
@define TO "STATUS[4,1]"
-@define PA0 "STATUS[5,1]"
+@define RP "STATUS[5,2]"
+@define IRP "STATUS[7,1]"
+
+# STATUS bit definitions
+@define STATUS_IRP_BIT 7
+@define STATUS_RP_BIT 5
+@define STATUS_Z_BIT 2
+@define STATUS_DC_BIT 1
+@define STATUS_C_BIT 0
+
+# STATUS bit masks used for setting
+@define STATUS_IRP_MASK 0x80
+@define STATUS_RP_MASK 0x60
+@define STATUS_Z_MASK 0x04
+@define STATUS_DC_MASK 0x02
+@define STATUS_C_MASK 0x01
+
+# STATUS bit masks used for clearing
+@define STATUS_IRP_CLEARMASK 0x7F
+@define STATUS_RP_CLEARMASK 0x9F
+@define STATUS_Z_CLEARMASK 0xFB
+@define STATUS_DC_CLEARMASK 0xFD
+@define STATUS_C_CLEARMASK 0xFE
+
#
# WARNING! - Reflection of these DATA-based registers with the corresponding register
@@ -80,16 +77,13 @@ define register offset=0x0007 size=1 [ IRP RP ];
#
@if PROCESSOR == "PIC_16"
define DATA offset=0x0000 size=1 [
- INDF TMR0 PCL STATUS FSR PORTA PORTB PORTC PORTD PORTE PCLATH INTCON PIR1 PIR2 TMR1L TMR1H
+ INDF _ PCL STATUS FSR _ _ _ _ _ PCLATH INTCON _ _ _ _
];
-
@elif PROCESSOR == "PIC_16F"
define DATA offset=0x0000 size=1 [
- INDF0 INDF1 PCL STATUS FSR0L FSR0H FSR1L FSR1H BSR WREG PCLATH INTCON _ _ _ _
+ INDF0 INDF1 PCL STATUS FSR0L FSR0H FSR1L FSR1H BSR WREG PCLATH INTCON _ _ _ _
];
-
define DATA offset=0x0004 size=2 [ FSR0 FSR1 ];
-
@endif
# Additional Data Bank data registers are defined in the .PSPEC file.
diff --git a/Ghidra/Processors/PIC/data/languages/pic16_instructions.sinc b/Ghidra/Processors/PIC/data/languages/pic16_instructions.sinc
index 4bec48f478..4d31346ed3 100644
--- a/Ghidra/Processors/PIC/data/languages/pic16_instructions.sinc
+++ b/Ghidra/Processors/PIC/data/languages/pic16_instructions.sinc
@@ -25,7 +25,6 @@ define token instr16(16)
uf7 = (4,6)
fsr = (2,2)
fsrk = (6,6)
- fregCore = (0,3)
k5 = (0,4)
k6 = (0,5)
k7 = (0,6)
@@ -44,15 +43,7 @@ define context contextreg
;
-@if PROCESSOR == "PIC_16"
-attach variables [ fregCore ] [
- INDF TMR0 PCL STATUS FSR PORTA PORTB PORTC PORTD PORTE PCLATH INTCON _ _ _ _
-];
-
-@elif PROCESSOR == "PIC_16F"
-attach variables [ fregCore ] [
- INDF0 INDF1 PCL STATUS FSR0L FSR0H FSR1L FSR1H BSR W PCLATH INTCON _ _ _ _
-];
+@if PROCESSOR == "PIC_16F"
attach names [IntConBits] [ IOCIF INTF TMR0IF IOCIE INTE TMR0IE PEIE GIE ];
@@ -178,31 +169,45 @@ srcREG: fv is uf7=0x7 & lf7 [fv = 0x70 + lf7; ] {
export *[DATA]:1 addr;
}
+# The registers listed here are explicitly defined as registers in sleigh.
+# There are other registers but they are named in the .pspec file.
+# The reason this is done is to have cross references created to certain registers, and to have
+# only the registers that must be accessed directly in sleigh (e.g. PCL, FSR) defined in sleigh.
+# Register explicitly defined in sleigh will not have xref's created to them.
+# Registers named only in the .pspec file will have xref's to them in most cases.
+#
+# Also, these registers ignore RP, or BSR which allow more registers to be in a different register bank.
+#
+# PIC16 : INDF _ PCL STATUS FSR _ _ _ _ _ PCLATH INTCON _ _ _ _
+# PIC16F: INDF0 INDF1 PCL STATUS FSR0L FSR0H FSR1L FSR1H BSR W PCLATH INTCON _ _ _ _
+
# File register index (f7=0): INDF use implies indirect data access using FSR value and IRP bit in STATUS reg
@if PROCESSOR == "PIC_16"
-srcREG: fregCore is f7=0 & fregCore {
+srcREG: INDF is f7=0 & INDF {
addr:2 = (zext(IRP) << 8) + zext(FSR);
export *[DATA]:1 addr;
}
-srcREG: fregCore is f7=1 & fregCore {
- rpval:2 = zext(RP == 1) + zext(RP == 2);
- addr:2 = (zext(rpval) << 7) + 1;
- export *[DATA]:1 addr;
+srcREG: lf7 is f7=1 & lf7 {
+ rpval:2 = zext(RP == 1) + zext(RP == 3);
+ addr:2 = (zext(rpval) << 7) + 1;
+ export *[DATA]:1 addr;
}
+
@elif PROCESSOR == "PIC_16F"
-srcREG: fregCore is f7=0 & fregCore {
+
+srcREG: INDF0 is f7=0 & INDF0 {
addr:2 = FSR0;
export *[DATA]:1 addr;
}
-srcREG: fregCore is f7=1 & fregCore {
+srcREG: INDF1 is f7=1 & INDF1 {
addr:2 = FSR1;
export *[DATA]:1 addr;
}
@endif
# Special File Registers always mapped to Bank-0
-srcREG: fregCore is f7=0x02 & fregCore {
+srcREG: PCL is f7=0x02 & PCL {
# PCL and PCLATH must be latched
addr:2 = inst_start >> 1; # Compensate for CODE wordsize
PCL = addr:1;
@@ -210,17 +215,19 @@ srcREG: fregCore is f7=0x02 & fregCore {
export PCL;
}
-srcREG: fregCore is f7=0x03 & fregCore { export fregCore; }
-srcREG: fregCore is f7=0x04 & fregCore { export fregCore; }
-@if PROCESSOR == "PIC_16F"
-srcREG: fregCore is f7=0x05 & fregCore { export fregCore; }
-srcREG: fregCore is f7=0x06 & fregCore { export fregCore; }
-srcREG: fregCore is f7=0x07 & fregCore { export fregCore; }
-srcREG: fregCore is f7=0x08 & fregCore { export fregCore; }
-srcREG: fregCore is f7=0x09 & fregCore { export fregCore; }
+srcREG: STATUS is f7=0x03 & STATUS { export STATUS; }
+@if PROCESSOR == "PIC_16"
+srcREG: FSR is f7=0x04 & FSR { export FSR; }
+@elif PROCESSOR == "PIC_16F"
+srcREG: FSR0L is f7=0x04 & FSR0L { export FSR0L; }
+srcREG: FSR0H is f7=0x05 & FSR0H { export FSR0H; }
+srcREG: FSR1L is f7=0x06 & FSR1L { export FSR1L; }
+srcREG: FSR1H is f7=0x07 & FSR1H { export FSR1H; }
+srcREG: BSR is f7=0x08 & BSR { export BSR; }
+srcREG: W is f7=0x09 & W { export W; }
@endif
-srcREG: fregCore is f7=0x0a & fregCore { export fregCore; }
-srcREG: fregCore is f7=0x0b & fregCore { export fregCore; }
+srcREG: PCLATH is f7=0x0a & PCLATH { export PCLATH; }
+srcREG: INTCON is f7=0x0b & INTCON { export INTCON; }
# Destination register (either srcREG or W)
@@ -230,7 +237,7 @@ destREG: "0" is d=0 { export W; }
destREG: "1" is d=1 & f7 & srcREG { export srcREG; }
# Destination register: Special File Registers always mapped to Bank-0
-destREG: "1" is d=1 & f7=0x02 & fregCore { export fregCore; } # PCL (special behavior reqd)
+destREG: "1" is d=1 & f7=0x02 { export PCL; } # PCL (special behavior reqd)
# Destination operand representation (w: W register is destination; f: specified srcREG is destination)
D: "w" is d=0 { }
@@ -238,13 +245,13 @@ D: "f" is d=1 { }
# Absolute address generated from k11 and PCLATH<4:3>
absAddr11: k11 is k11 {
- addr:2 = ((zext(PCLATH) & 0x78) << 8) + k11;
+ addr:2 = ((zext(PCLATH) & 0x18) << 8) | k11;
export addr;
}
@if PROCESSOR == "PIC_16F"
-# Absolute address generated from k11 and PCLATH<4:3>
+# Relative address
relAddr9: addr is sk9 [ addr = inst_next + sk9; ] {
export *[CODE]:2 addr;
}
@@ -327,7 +334,7 @@ trisREG: "7" is l5=7 { local trl:2 = 0x10E; export *[DATA]:1 trl; } #
tmp:1 = addr:1;
setAddFlags(tmp, W);
tmp = tmp + W;
- addr = (zext(PCLATH) << 8) + zext(tmp);
+ addr = ((zext(PCLATH) & 0x1F) << 8) | zext(tmp);
PCL = tmp;
setResultFlags(tmp);
goto [addr];
@@ -365,7 +372,7 @@ trisREG: "7" is l5=7 { local trl:2 = 0x10E; export *[DATA]:1 trl; } #
$(C) = $(C) | tc;
val = val + tmpC;
- addr = (zext(PCLATH) << 8) + zext(val);
+ addr = ((zext(PCLATH) & 0x1F) << 8) | zext(val);
PCL = val;
setResultFlags(val);
goto [addr];
@@ -799,7 +806,7 @@ srcFSRk: sk6"["fsrk"]" is fsrk & sk6 {
}
:MOVLP imm7 is op7=0x63 & imm7 {
- PCLATH = imm7;
+ PCLATH = imm7 & 0x1F;
}
@endif
@@ -831,7 +838,7 @@ srcFSRk: sk6"["fsrk"]" is fsrk & sk6 {
# --00 0000 1fff ffff
# 0000 0000 1000 0010 -> MOVWF PCL
PCL = W;
- addr:2 = (zext(PCLATH) << 8) + zext(PCL);
+ addr:2 = ((zext(PCLATH) & 0x1F) << 8) | zext(PCL);
goto [addr];
}
diff --git a/Ghidra/Processors/PIC/data/languages/pic16f.pspec b/Ghidra/Processors/PIC/data/languages/pic16f.pspec
index 44a15b649d..a821ddbec2 100644
--- a/Ghidra/Processors/PIC/data/languages/pic16f.pspec
+++ b/Ghidra/Processors/PIC/data/languages/pic16f.pspec
@@ -10,9 +10,102 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic16Analyzer.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic16Analyzer.java
index 64fd79747f..2a42b481b3 100644
--- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic16Analyzer.java
+++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic16Analyzer.java
@@ -53,6 +53,9 @@ public class Pic16Analyzer extends ConstantPropagationAnalyzer {
@Override
public boolean canAnalyze(Program p) {
+ if (!super.canAnalyze(p)) {
+ return false;
+ }
Language lang = p.getLanguage();
statusReg = p.getRegister("STATUS");
pclathReg = p.getRegister("PCLATH");
@@ -63,6 +66,10 @@ public class Pic16Analyzer extends ConstantPropagationAnalyzer {
rpStatusReg = p.getRegister("RP");
irpStatusReg = p.getRegister("IRP");
+ // set default analysis options
+ minSpeculativeRefAddress = 4;
+ minStoreLoadRefAddress = 4;
+
return lang.getProcessor() == PicProcessor.PROCESSOR_PIC_16 && pclathReg != null;
}
@@ -82,25 +89,6 @@ public class Pic16Analyzer extends ConstantPropagationAnalyzer {
// use context to fill out addresses on certain instructions
ConstantPropagationContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, trustWriteMemOption) {
- @Override
- public boolean evaluateReference(VarnodeContext context, Instruction instr, int pcodeop, Address address,
- int size, DataType dataType, RefType refType) {
- AddressSpace space = address.getAddressSpace();
-
- if (address.isExternalAddress()) {
- return true;
- }
-
- if (space.hasMappedRegisters()) {
- return true;
- }
- boolean isCodeSpace = address.getAddressSpace().getName().equals(CODE_SPACE_NAME);
- if (refType.isComputed() && refType.isFlow() && isCodeSpace) {
- return true;
- }
- return super.evaluateReference(context, instr, pcodeop, address, size, dataType, refType);
- }
-
@Override
public boolean evaluateDestination(VarnodeContext context, Instruction instruction) {
FlowType flowType = instruction.getFlowType();
@@ -111,11 +99,9 @@ public class Pic16Analyzer extends ConstantPropagationAnalyzer {
Reference[] refs = instruction.getReferencesFrom();
if (refs.length == 1 && refs[0].getReferenceType().isFlow()) {
writeContext(refs[0].getToAddress(), context);
- Address dest = refs[0].getToAddress();
- disassemblyPoints.addRange(dest, dest);
}
- return false;
+ return super.evaluateDestination(context, instruction);
}
private void writeContext(Address dest, VarnodeContext context) {
@@ -157,11 +143,6 @@ public class Pic16Analyzer extends ConstantPropagationAnalyzer {
AddressSet result = symEval.flowConstants(flowStart, flowSet, eval, true, monitor);
- if (!disassemblyPoints.isEmpty()) {
- AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
- mgr.disassemble(disassemblyPoints);
- }
-
return result;
}