File 0004-Add-offset-to-sleigh-Java.patch of Package ghidra

From a04b8dc5840d7aa2353204fc2daa64fc32e22f11 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <kkaempf@gmail.com>
Date: Sun, 30 Oct 2022 22:18:33 +0100
Subject: [PATCH 4/8] Add offset to sleigh Java
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This provides Sleigh access to the offset property of the ParserWalker,
giving the offset of the currently parsed byte from inst_start.

Signed-off-by: Klaus Kämpf <kkaempf@gmail.com>
---
 .../Decompiler/src/main/doc/sleigh.xml        |  7 ++
 .../ghidra/sleigh/grammar/SleighCompiler.g    |  6 ++
 .../expression/OffsetInstructionValue.java    | 73 ++++++++++++++++
 .../sleigh/expression/PatternExpression.java  |  3 +
 .../sleigh/symbol/OffsetSymbol.java           | 73 ++++++++++++++++
 .../processors/sleigh/symbol/SymbolTable.java |  3 +
 .../processors/sleigh/template/ConstTpl.java  |  8 ++
 .../util/pcode/AbstractPcodeFormatter.java    |  3 +
 .../java/ghidra/pcode/utils/SlaFormat.java    |  4 +
 .../ghidra/pcodeCPort/semantics/ConstTpl.java |  8 +-
 .../slgh_compile/SleighCompile.java           |  2 +
 .../pcodeCPort/slgh_compile/Yylval.java       |  1 +
 .../OffsetInstructionValue.java               | 59 +++++++++++++
 .../slghpatexpress/PatternExpression.java     |  1 -
 .../pcodeCPort/slghsymbol/OffsetSymbol.java   | 87 +++++++++++++++++++
 .../pcodeCPort/slghsymbol/symbol_type.java    |  1 +
 .../program/model/lang/PcodeParser.java       |  1 +
 17 files changed, 337 insertions(+), 3 deletions(-)
 create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/OffsetInstructionValue.java
 create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/OffsetSymbol.java
 create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/OffsetInstructionValue.java
 create mode 100644 Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/OffsetSymbol.java

diff --git a/Ghidra/Features/Decompiler/src/main/doc/sleigh.xml b/Ghidra/Features/Decompiler/src/main/doc/sleigh.xml
index d4af0e8599..a36cf1f308 100644
--- a/Ghidra/Features/Decompiler/src/main/doc/sleigh.xml
+++ b/Ghidra/Features/Decompiler/src/main/doc/sleigh.xml
@@ -1097,6 +1097,10 @@ We list all of the symbols that are predefined by SLEIGH.
   <td><code>epsilon</code></td>
   <td>A special identifier indicating an empty bit pattern.</td>
 </tr>
+<tr>
+  <td><code>operand_offset</code></td>
+  <td>Offset of the address of the current operand. Useful for variable-length instructions.</td>
+</tr>
 </tbody>
 </table>
 </informalexample>
@@ -1113,6 +1117,9 @@ identifiers are address spaces. The <emphasis>epsilon</emphasis>
 identifier is inherited from SLED and is a specific symbol equivalent
 to the constant zero. The <emphasis>instruction</emphasis> identifier
 is the root instruction table.
+<emphasis>operand_offset</emphasis> was introduced to support VAX
+variable-length, multi-operand instructions. PC-relative addressing in
+VAX is relative to the operand address, not the instruction address.
 </para>
 </sect2>
 </sect1>
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g b/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g
index d254d2bd92..46d32ef429 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g
+++ b/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g
@@ -342,6 +342,7 @@ specific_symbol[String purpose] returns [SpecificSymbol symbol]
 			if (sym == null) {
 				unknownSymbolError($s.getText(), find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
 			} else if(sym.getType() != symbol_type.start_symbol
+					&& sym.getType() != symbol_type.offset_symbol
 					&& sym.getType() != symbol_type.end_symbol
 					&& sym.getType() != symbol_type.next2_symbol
 					&& sym.getType() != symbol_type.flowdest_symbol
@@ -841,6 +842,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
                 }
                 $expr = os.getPatternExpression();
 			} else if(sym.getType() == symbol_type.start_symbol
+					|| sym.getType() == symbol_type.offset_symbol
 					|| sym.getType() == symbol_type.end_symbol
 					|| sym.getType() == symbol_type.next2_symbol
 					|| sym.getType() == symbol_type.flowdest_symbol
@@ -876,6 +878,7 @@ pattern_symbol2[String purpose] returns [PatternExpression expr]
 			if (sym == null) {
 				unknownSymbolError($s.getText(), find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
 			} else if(sym.getType() == symbol_type.start_symbol
+					|| sym.getType() == symbol_type.offset_symbol
 					|| sym.getType() == symbol_type.end_symbol
 					|| sym.getType() == symbol_type.next2_symbol
 					|| sym.getType() == symbol_type.flowdest_symbol
@@ -949,6 +952,7 @@ cstatement[VectorSTL<ContextChange> r]
 							|| sym.getType() == symbol_type.name_symbol
 							|| sym.getType() == symbol_type.varnodelist_symbol
 							|| sym.getType() == symbol_type.start_symbol
+							|| sym.getType() == symbol_type.offset_symbol
 							|| sym.getType() == symbol_type.end_symbol
 							|| sym.getType() == symbol_type.next2_symbol
 							|| sym.getType() == symbol_type.flowdest_symbol
@@ -1184,6 +1188,7 @@ assignment returns [VectorSTL<OpTpl> value]
                                               bitSym.getBitOffset(),
                                               bitSym.numBits(),e);
 			} else if(sym.getType() != symbol_type.start_symbol
+					&& sym.getType() != symbol_type.offset_symbol
 					&& sym.getType() != symbol_type.end_symbol
 					&& sym.getType() != symbol_type.next2_symbol
 					&& sym.getType() != symbol_type.flowdest_symbol
@@ -1528,6 +1533,7 @@ expr_apply returns [Object value]
 						pcode.reportError(find($t), "macro invocation not allowed as expression");
 					}
 				} else if(sym.getType() == symbol_type.start_symbol
+					|| sym.getType() == symbol_type.offset_symbol
 					|| sym.getType() == symbol_type.end_symbol
 					|| sym.getType() == symbol_type.next2_symbol
 					|| sym.getType() == symbol_type.flowdest_symbol
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/OffsetInstructionValue.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/OffsetInstructionValue.java
new file mode 100644
index 0000000000..c04bd7412a
--- /dev/null
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/OffsetInstructionValue.java
@@ -0,0 +1,73 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Feb 8, 2005
+ *
+ */
+package ghidra.app.plugin.processors.sleigh.expression;
+
+import static ghidra.pcode.utils.SlaFormat.*;
+
+import ghidra.app.plugin.processors.sleigh.ParserWalker;
+import ghidra.app.plugin.processors.sleigh.SleighLanguage;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.mem.MemoryAccessException;
+import ghidra.program.model.pcode.Decoder;
+import ghidra.program.model.pcode.DecoderException;
+
+/**
+ * The offset value of the current instructions address
+ */
+public class OffsetInstructionValue extends PatternValue {
+	private static final int HASH = "[inst_offset]".hashCode();
+
+	@Override
+	public int hashCode() {
+		return HASH;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		return obj instanceof OffsetInstructionValue;
+	}
+
+	@Override
+	public long minValue() {
+		return 0;
+	}
+
+	@Override
+	public long maxValue() {
+		return 0;
+	}
+
+	@Override
+	public long getValue(ParserWalker walker) throws MemoryAccessException {
+		return walker.getOffset(-1);
+	}
+
+	@Override
+	public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
+		int el = decoder.openElement(ELEM_OFFSET_EXP);
+		decoder.closeElement(el);
+		// Nothing to do
+	}
+
+	@Override
+	public String toString() {
+		return "[inst_offset]";
+	}
+}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/PatternExpression.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/PatternExpression.java
index 3818f96ee1..f91fe4122d 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/PatternExpression.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/expression/PatternExpression.java
@@ -54,6 +54,9 @@ public abstract class PatternExpression {
 		else if (el == ELEM_START_EXP.id()) {
 			res = new StartInstructionValue();
 		}
+		else if (el == ELEM_OFFSET_EXP.id()) {
+			res = new OffsetInstructionValue();
+                }
 		else if (el == ELEM_END_EXP.id()) {
 			res = new EndInstructionValue();
 		}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/OffsetSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/OffsetSymbol.java
new file mode 100644
index 0000000000..042e7277db
--- /dev/null
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/OffsetSymbol.java
@@ -0,0 +1,73 @@
+/* ###
+ * 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.
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Feb 8, 2005
+ *
+ */
+package ghidra.app.plugin.processors.sleigh.symbol;
+
+import static ghidra.pcode.utils.SlaFormat.*;
+
+import java.util.ArrayList;
+
+import ghidra.app.plugin.processors.sleigh.*;
+import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
+import ghidra.app.plugin.processors.sleigh.expression.OffsetInstructionValue;
+import ghidra.program.model.mem.MemoryAccessException;
+import ghidra.program.model.pcode.Decoder;
+import ghidra.program.model.pcode.DecoderException;
+
+/**
+ * TripleSymbol with semantic value equal to offset of instruction's
+ * operand current address
+ */
+public class OffsetSymbol extends SpecificSymbol {
+
+	private PatternExpression patexp;
+	
+	@Override
+	public PatternExpression getPatternExpression() {
+		return patexp;
+	}
+
+	@Override
+	public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
+		hand.space = walker.getCurSpace();
+		hand.offset_space = null;
+		hand.offset_offset = walker.getAddr().getOffset();
+		hand.size = hand.space.getPointerSize();
+	}
+
+	@Override
+	public String print(ParserWalker walker) throws MemoryAccessException {
+		long val = walker.getAddr().getOffset();
+		return "0x" + Long.toHexString(val);
+	}
+
+	@Override
+	public void printList(ParserWalker walker, ArrayList<Object> list) {
+		list.add(walker.getParentHandle());
+	}
+
+	@Override
+	public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
+//		int element = decoder.openElement(ELEM_OFFSET_SYM);
+		patexp = new OffsetInstructionValue();
+		decoder.closeElement(ELEM_OFFSET_SYM.id());
+	}
+
+}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/SymbolTable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/SymbolTable.java
index 1b3f1ae1be..d77f1b5021 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/SymbolTable.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/symbol/SymbolTable.java
@@ -174,6 +174,9 @@ public class SymbolTable {
 		else if (el == ELEM_START_SYM_HEAD.id()) {
 			sym = new StartSymbol();
 		}
+		else if (el == ELEM_OFFSET_SYM_HEAD.id()) {
+			sym = new OffsetSymbol();
+		}
 		else if (el == ELEM_END_SYM_HEAD.id()) {
 			sym = new EndSymbol();
 		}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/template/ConstTpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/template/ConstTpl.java
index 75cc37f1e2..73e90e92fb 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/template/ConstTpl.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/template/ConstTpl.java
@@ -46,6 +46,7 @@ public class ConstTpl {
 	public static final int J_FLOWREF_SIZE = 10;
 	public static final int J_FLOWDEST = 11;
 	public static final int J_FLOWDEST_SIZE = 12;
+	public static final int J_OFFSET = 13;
 
 	public static final int V_SPACE = 0;
 	public static final int V_OFFSET = 1;
@@ -140,6 +141,8 @@ public class ConstTpl {
 		switch (type) {
 			case J_START:
 				return walker.getAddr().getOffset();
+			case J_OFFSET:
+				return walker.getAddr().getOffset();
 			case J_NEXT:
 				return walker.getNaddr().getOffset();
 			case J_NEXT2:
@@ -302,6 +305,9 @@ public class ConstTpl {
 		else if (el == ELEM_CONST_START.id()) {
 			type = J_START;
 		}
+		else if (el == ELEM_CONST_OFFSET.id()) {
+			type = J_OFFSET;
+		}
 		else if (el == ELEM_CONST_NEXT.id()) {
 			type = J_NEXT;
 		}
@@ -376,6 +382,8 @@ public class ConstTpl {
 				return "[next2]";
 			case J_START:
 				return "[start]";
+			case J_OFFSET:
+				return "[offset]";
 			case J_RELATIVE:
 				return "[rel:" + Long.toHexString(value_real) + "]";
 		}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/pcode/AbstractPcodeFormatter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/pcode/AbstractPcodeFormatter.java
index e0a52013d6..808dd4596b 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/pcode/AbstractPcodeFormatter.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/pcode/AbstractPcodeFormatter.java
@@ -173,6 +173,9 @@ public abstract class AbstractPcodeFormatter<T, A extends Appender<T>>
 			if (offset.getType() == ConstTpl.J_START) {
 				appender.appendLabel("inst_start");
 			}
+			else if (offset.getType() == ConstTpl.J_OFFSET) {
+				appender.appendLabel("operand_offset");
+			}
 			else if (offset.getType() == ConstTpl.J_NEXT) {
 				appender.appendLabel("inst_next");
 			}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/SlaFormat.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/SlaFormat.java
index 742341daa6..7209f25a61 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/SlaFormat.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/SlaFormat.java
@@ -191,6 +191,10 @@ public class SlaFormat {
 	public static final ElementId ELEM_CONST_FLOWDEST = new ElementId("const_flowdest", 87);
 	public static final ElementId ELEM_CONST_FLOWDEST_SIZE =
 		new ElementId("const_flowdest_size", 88);
+	public static final ElementId ELEM_OFFSET_EXP = new ElementId("offset_exp", 89);
+	public static final ElementId ELEM_OFFSET_SYM = new ElementId("offset_sym", 90);
+	public static final ElementId ELEM_OFFSET_SYM_HEAD = new ElementId("offset_sym_head",91);
+	public static final ElementId ELEM_CONST_OFFSET = new ElementId("const_offset",92);
 
 	/**
 	 * Try to read the header bytes of the .sla format from the given stream. If the header bytes
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/semantics/ConstTpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/semantics/ConstTpl.java
index 4c84b4d94e..88b28eff01 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/semantics/ConstTpl.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/semantics/ConstTpl.java
@@ -45,7 +45,8 @@ public class ConstTpl {
 		j_flowref,
 		j_flowref_size,
 		j_flowdest,
-		j_flowdest_size
+		j_flowdest_size,
+		j_offset
 	}
 
 	public enum v_field {
@@ -263,6 +264,10 @@ public class ConstTpl {
 				encoder.openElement(ELEM_CONST_START);
 				encoder.closeElement(ELEM_CONST_START);
 				break;
+			case j_offset:
+				encoder.openElement(ELEM_CONST_OFFSET);
+				encoder.closeElement(ELEM_CONST_OFFSET);
+				break;
 			case j_next:
 				encoder.openElement(ELEM_CONST_NEXT);
 				encoder.closeElement(ELEM_CONST_NEXT);
@@ -307,5 +312,4 @@ public class ConstTpl {
 				break;
 		}
 	}
-
 }
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
index a953e401ff..1fb0b64069 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
@@ -290,6 +290,8 @@ public class SleighCompile extends SleighBase {
 		symtab.addSymbol(spacesym);
 		StartSymbol startsym = new StartSymbol(location, "inst_start", getConstantSpace());
 		symtab.addSymbol(startsym);
+		OffsetSymbol offsetsym = new OffsetSymbol(location, "operand_offset", getConstantSpace());
+		symtab.addSymbol(offsetsym);
 		EndSymbol endsym = new EndSymbol(location, "inst_next", getConstantSpace());
 		symtab.addSymbol(endsym);
 		Next2Symbol next2sym = new Next2Symbol(location, "inst_next2", getConstantSpace());
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/Yylval.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/Yylval.java
index f165ca6b8b..dc57400015 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/Yylval.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/Yylval.java
@@ -30,6 +30,7 @@ class Yylval {
     VarnodeListSymbol varlistsym;
     OperandSymbol operandsym;
     StartSymbol startsym;
+    OffsetSymbol offsetsym;
     EndSymbol endsym;
 	Next2Symbol next2sym;
     SubtableSymbol subtablesym;
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/OffsetInstructionValue.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/OffsetInstructionValue.java
new file mode 100644
index 0000000000..8684da3830
--- /dev/null
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/OffsetInstructionValue.java
@@ -0,0 +1,59 @@
+/* ###
+ * 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.
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.pcodeCPort.slghpatexpress;
+
+import static ghidra.pcode.utils.SlaFormat.*;
+
+import java.io.IOException;
+
+import generic.stl.VectorSTL;
+import ghidra.program.model.pcode.Encoder;
+import ghidra.sleigh.grammar.Location;
+
+public class OffsetInstructionValue extends PatternValue {
+
+	public OffsetInstructionValue(Location location) {
+		super(location);
+	}
+
+	@Override
+	public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
+		return new TokenPattern(location);
+	}
+
+	@Override
+	public TokenPattern genPattern(long val) {
+		return new TokenPattern(location);
+	}
+
+	@Override
+	public long minValue() {
+		return 0;
+	}
+
+	@Override
+	public long maxValue() {
+		return 0;
+	}
+
+	@Override
+	public void encode(Encoder encoder) throws IOException {
+		encoder.openElement(ELEM_OFFSET_EXP);
+		encoder.closeElement(ELEM_OFFSET_EXP);
+	}
+
+}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/PatternExpression.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/PatternExpression.java
index 12955493dd..38651b908a 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/PatternExpression.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/PatternExpression.java
@@ -60,5 +60,4 @@ public abstract class PatternExpression {
 			p.dispose();
 		}
 	}
-
 }
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/OffsetSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/OffsetSymbol.java
new file mode 100644
index 0000000000..9b753b8d66
--- /dev/null
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/OffsetSymbol.java
@@ -0,0 +1,87 @@
+/* ###
+ * 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.
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.pcodeCPort.slghsymbol;
+
+import static ghidra.pcode.utils.SlaFormat.*;
+
+import java.io.IOException;
+
+import ghidra.pcodeCPort.semantics.ConstTpl;
+import ghidra.pcodeCPort.semantics.VarnodeTpl;
+import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
+import ghidra.pcodeCPort.slghpatexpress.OffsetInstructionValue;
+import ghidra.pcodeCPort.space.AddrSpace;
+import ghidra.program.model.pcode.Encoder;
+import ghidra.sleigh.grammar.Location;
+
+public class OffsetSymbol extends SpecificSymbol {
+	private AddrSpace const_space;
+	private PatternExpression patexp;
+
+	OffsetSymbol(Location location) {
+		super(location);
+		patexp = null;
+	}
+
+	@Override
+	public PatternExpression getPatternExpression() {
+		return patexp;
+	}
+
+	@Override
+	public symbol_type getType() {
+		return symbol_type.offset_symbol;
+	}
+
+	public OffsetSymbol(Location location, String nm, AddrSpace cspc) {
+		super(location, nm);
+		const_space = cspc;
+		patexp = new OffsetInstructionValue(location);
+		patexp.layClaim();
+	}
+
+	@Override
+	public void dispose() {
+		if (patexp != null) {
+			PatternExpression.release(patexp);
+		}
+	}
+
+// Returns current operand offset as a constant
+	@Override
+	public VarnodeTpl getVarnode() {
+		ConstTpl spc = new ConstTpl(const_space);
+		ConstTpl off = new ConstTpl(ConstTpl.const_type.j_offset);
+		ConstTpl sz_zero = new ConstTpl();
+		return new VarnodeTpl(location, spc, off, sz_zero);
+	}
+
+	@Override
+	public void encode(Encoder encoder) throws IOException {
+		encoder.openElement(ELEM_OFFSET_SYM);
+		encoder.writeUnsignedInteger(ATTRIB_ID, id);
+		encoder.closeElement(ELEM_OFFSET_SYM);
+	}
+
+	@Override
+	public void encodeHeader(Encoder encoder) throws IOException {
+		encoder.openElement(ELEM_OFFSET_SYM_HEAD);
+		encodeSleighSymbolHeader(encoder);
+		encoder.closeElement(ELEM_OFFSET_SYM_HEAD);
+	}
+
+}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/symbol_type.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/symbol_type.java
index b29cc3f238..1c14a38090 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/symbol_type.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/symbol_type.java
@@ -26,6 +26,7 @@ public enum symbol_type {
 	varnodelist_symbol,
 	operand_symbol,
 	start_symbol,  // inst_start, inst_ref, inst_def
+        offset_symbol,
 	end_symbol,    // inst_next
 	next2_symbol,    // inst_next2
 	subtable_symbol,
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeParser.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeParser.java
index 8166b87ef8..eee777c613 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeParser.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/PcodeParser.java
@@ -84,6 +84,7 @@ public class PcodeParser extends PcodeCompile {
 
 		Location internalLoc = Location.INTERNALLY_DEFINED;
 		symbolMap.put("inst_start", new StartSymbol(internalLoc, "inst_start", getConstantSpace()));
+		symbolMap.put("operand_offset", new OffsetSymbol(internalLoc, "operand_offset", getConstantSpace()));
 		symbolMap.put("inst_next", new EndSymbol(internalLoc, "inst_next", getConstantSpace()));
 		symbolMap.put("inst_next2", new Next2Symbol(internalLoc, "inst_next2", getConstantSpace()));
 		symbolMap.put("inst_ref", new FlowRefSymbol(internalLoc, "inst_ref", getConstantSpace()));
-- 
2.49.0

openSUSE Build Service is sponsored by