mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/GP-2480_ghidra1_Sleigh_inst_next2'
Conflicts: Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/pcode/exec/trace/TracePcodeEmulatorTest.java
This commit is contained in:
commit
ca80be44ff
121 changed files with 4074 additions and 4553 deletions
|
@ -105,14 +105,14 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
|
||||||
assertTrue(
|
assertTrue(
|
||||||
helper.patchInstructionAction.isAddToPopup(listingProvider.getActionContext(null)));
|
helper.patchInstructionAction.isAddToPopup(listingProvider.getActionContext(null)));
|
||||||
Instruction ins =
|
Instruction ins =
|
||||||
helper.patchInstructionAt(tb.addr(0x00400123), "imm r0,#0x0", "imm r0,#1234");
|
helper.patchInstructionAt(tb.addr(0x00400123), "imm r0,#0x0", "imm r0,#0x3d2");
|
||||||
assertEquals(2, ins.getLength());
|
assertEquals(2, ins.getLength());
|
||||||
|
|
||||||
long snap = traceManager.getCurrent().getViewSnap();
|
long snap = traceManager.getCurrent().getViewSnap();
|
||||||
assertTrue(DBTraceUtils.isScratch(snap));
|
assertTrue(DBTraceUtils.isScratch(snap));
|
||||||
byte[] bytes = new byte[2];
|
byte[] bytes = new byte[2];
|
||||||
view.getMemory().getBytes(tb.addr(0x00400123), bytes);
|
view.getMemory().getBytes(tb.addr(0x00400123), bytes);
|
||||||
assertArrayEquals(tb.arr(0x40, 1234), bytes);
|
assertArrayEquals(tb.arr(0x30, 0xd2), bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -86,8 +86,8 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
|
||||||
|
|
||||||
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0));
|
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0));
|
||||||
iit = asm.assemble(start,
|
iit = asm.assemble(start,
|
||||||
"imm r0, #1234",
|
"imm r0, #0x3d2",
|
||||||
"imm r1, #2045"); // 11 bits unsigned
|
"imm r1, #911"); // 10 bits unsigned
|
||||||
|
|
||||||
}
|
}
|
||||||
imm1234 = iit.next();
|
imm1234 = iit.next();
|
||||||
|
|
|
@ -246,7 +246,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
||||||
"pc = 0x00400000;",
|
"pc = 0x00400000;",
|
||||||
"sp = 0x00110000;"),
|
"sp = 0x00110000;"),
|
||||||
List.of(
|
List.of(
|
||||||
"imm r0, #1234")); // decimal
|
"imm r0, #911")); // decimal
|
||||||
|
|
||||||
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.trace, 0);
|
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.trace, 0);
|
||||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||||
|
@ -261,7 +261,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
||||||
TraceSleighUtils.evaluate("sp", tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate("sp", tb.trace, 1, thread, 0));
|
||||||
assertEquals(BigInteger.valueOf(0x00400002),
|
assertEquals(BigInteger.valueOf(0x00400002),
|
||||||
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
|
||||||
assertEquals(BigInteger.valueOf(1234),
|
assertEquals(BigInteger.valueOf(911),
|
||||||
TraceSleighUtils.evaluate("r0", tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate("r0", tb.trace, 1, thread, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,9 +278,9 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
||||||
"sp = 0x00110000;"),
|
"sp = 0x00110000;"),
|
||||||
List.of(
|
List.of(
|
||||||
"brds 0x00400006",
|
"brds 0x00400006",
|
||||||
"imm r0, #1234", // decimal
|
"imm r0, #911", // decimal
|
||||||
"imm r0, #2020",
|
"imm r0, #860",
|
||||||
"imm r1, #2021"));
|
"imm r1, #861"));
|
||||||
|
|
||||||
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.trace, 0);
|
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.trace, 0);
|
||||||
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||||
|
@ -294,9 +294,9 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
||||||
|
|
||||||
assertEquals(BigInteger.valueOf(0x00400008),
|
assertEquals(BigInteger.valueOf(0x00400008),
|
||||||
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
|
||||||
assertEquals(BigInteger.valueOf(1234),
|
assertEquals(BigInteger.valueOf(911),
|
||||||
TraceSleighUtils.evaluate("r0", tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate("r0", tb.trace, 1, thread, 0));
|
||||||
assertEquals(BigInteger.valueOf(2021),
|
assertEquals(BigInteger.valueOf(861),
|
||||||
TraceSleighUtils.evaluate("r1", tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate("r1", tb.trace, 1, thread, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,9 @@ public abstract class AbstractPcodeFormatter<T, A extends Appender<T>>
|
||||||
else if (offset.getType() == ConstTpl.J_NEXT) {
|
else if (offset.getType() == ConstTpl.J_NEXT) {
|
||||||
appender.appendLabel("inst_next");
|
appender.appendLabel("inst_next");
|
||||||
}
|
}
|
||||||
|
else if (offset.getType() == ConstTpl.J_NEXT2) {
|
||||||
|
appender.appendLabel("inst_next2");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
formatAddress(appender, null, offset, size);
|
formatAddress(appender, null, offset, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,6 +494,27 @@ public class ToyProgramBuilder extends ProgramBuilder {
|
||||||
addInstructionWords(address, (short) (0xe000 | (relDest << 4))); // breq rel
|
addInstructionWords(address, (short) (0xe000 | (relDest << 4))); // breq rel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add conditional skip (consumes 2-bytes)
|
||||||
|
* @param offset instruction address offset
|
||||||
|
* @throws MemoryAccessException
|
||||||
|
*/
|
||||||
|
public void addBytesSkipConditional(long offset)
|
||||||
|
throws MemoryAccessException {
|
||||||
|
addBytesSkipConditional(toHex(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add conditional skip (consumes 2-bytes)
|
||||||
|
* @param addr instruction address
|
||||||
|
* @throws MemoryAccessException
|
||||||
|
*/
|
||||||
|
public void addBytesSkipConditional(String addr)
|
||||||
|
throws MemoryAccessException {
|
||||||
|
Address address = addr(addr);
|
||||||
|
addInstructionWords(address, (short) (0x8000)); // skeq
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add branch w/ delay slot (consumes 4-bytes)
|
* Add branch w/ delay slot (consumes 4-bytes)
|
||||||
* @param offset instruction address offset
|
* @param offset instruction address offset
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.assembler;
|
package ghidra.app.plugin.core.assembler;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ public class AssemblerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testActionPatchInstructionNoExisting() throws Exception {
|
public void testActionPatchInstructionNoExisting() throws Exception {
|
||||||
Address address = space.getAddress(0x00400000);
|
Address address = space.getAddress(0x00400000);
|
||||||
Instruction ins = helper.patchInstructionAt(address, "", "imm r0, #1234");
|
Instruction ins = helper.patchInstructionAt(address, "", "imm r0, #911");
|
||||||
assertEquals("imm r0,#0x4d2", ins.toString());
|
assertEquals("imm r0,#0x38f", ins.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -99,11 +99,11 @@ public class AssemblerPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Address address = space.getAddress(0x00400000);
|
Address address = space.getAddress(0x00400000);
|
||||||
Assembler asm = Assemblers.getAssembler(program);
|
Assembler asm = Assemblers.getAssembler(program);
|
||||||
try (ProgramTransaction trans = ProgramTransaction.open(program, "Assemble pre-existing")) {
|
try (ProgramTransaction trans = ProgramTransaction.open(program, "Assemble pre-existing")) {
|
||||||
asm.assemble(address, "imm r0,#0x4d2");
|
asm.assemble(address, "imm r0,#0x3d2");
|
||||||
trans.commit();
|
trans.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction ins = helper.patchInstructionAt(address, "imm r0,#0x4d2", "imm r0, #123");
|
Instruction ins = helper.patchInstructionAt(address, "imm r0,#0x3d2", "imm r0, #123");
|
||||||
assertEquals("imm r0,#0x7b", ins.toString());
|
assertEquals("imm r0,#0x7b", ins.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ src/decompile/datatests/pointersub.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/promotecompare.xml||GHIDRA||||END|
|
src/decompile/datatests/promotecompare.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/readvolatile.xml||GHIDRA||||END|
|
src/decompile/datatests/readvolatile.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/sbyte.xml||GHIDRA||||END|
|
src/decompile/datatests/sbyte.xml||GHIDRA||||END|
|
||||||
|
src/decompile/datatests/skipnext2.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/statuscmp.xml||GHIDRA||||END|
|
src/decompile/datatests/statuscmp.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/threedim.xml||GHIDRA||||END|
|
src/decompile/datatests/threedim.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/twodim.xml||GHIDRA||||END|
|
src/decompile/datatests/twodim.xml||GHIDRA||||END|
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
#include "slghsymbol.hh"
|
#include "slghsymbol.hh"
|
||||||
#include "translate.hh"
|
#include "translate.hh"
|
||||||
|
|
||||||
ParserContext::ParserContext(ContextCache *ccache)
|
ParserContext::ParserContext(ContextCache *ccache,Translate *trans)
|
||||||
|
|
||||||
{
|
{
|
||||||
parsestate = 0;
|
parsestate = uninitialized;
|
||||||
contcache = ccache;
|
contcache = ccache;
|
||||||
|
translate = trans;
|
||||||
if (ccache != (ContextCache *)0) {
|
if (ccache != (ContextCache *)0) {
|
||||||
contextsize = ccache->getDatabase()->getContextSize();
|
contextsize = ccache->getDatabase()->getContextSize();
|
||||||
context = new uintm[ contextsize ];
|
context = new uintm[ contextsize ];
|
||||||
|
@ -43,6 +44,18 @@ void ParserContext::initialize(int4 maxstate,int4 maxparam,AddrSpace *spc)
|
||||||
base_state = &state[0];
|
base_state = &state[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Address &ParserContext::getN2addr(void) const
|
||||||
|
|
||||||
|
{
|
||||||
|
if (n2addr.isInvalid()) {
|
||||||
|
if (translate == (Translate *)0 || parsestate == uninitialized)
|
||||||
|
throw LowlevelError("inst_next2 not available in this context");
|
||||||
|
int4 length = translate->instructionLength(naddr);
|
||||||
|
n2addr = naddr + length;
|
||||||
|
}
|
||||||
|
return n2addr;
|
||||||
|
}
|
||||||
|
|
||||||
uintm ParserContext::getInstructionBytes(int4 bytestart,int4 size,uint4 off) const
|
uintm ParserContext::getInstructionBytes(int4 bytestart,int4 size,uint4 off) const
|
||||||
|
|
||||||
{ // Get bytes from the instruction stream into a intm
|
{ // Get bytes from the instruction stream into a intm
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct ContextSet { // Instructions for setting a global context value
|
||||||
|
|
||||||
class ParserWalker; // Forward declaration
|
class ParserWalker; // Forward declaration
|
||||||
class ParserWalkerChange;
|
class ParserWalkerChange;
|
||||||
|
class Translate;
|
||||||
|
|
||||||
class ParserContext {
|
class ParserContext {
|
||||||
friend class ParserWalker;
|
friend class ParserWalker;
|
||||||
|
@ -75,6 +76,7 @@ public:
|
||||||
pcode = 2 // Instruction is parsed in preparation for generating p-code
|
pcode = 2 // Instruction is parsed in preparation for generating p-code
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
|
Translate *translate; // Instruction parser
|
||||||
int4 parsestate;
|
int4 parsestate;
|
||||||
AddrSpace *const_space;
|
AddrSpace *const_space;
|
||||||
uint1 buf[16]; // Buffer of bytes in the instruction stream
|
uint1 buf[16]; // Buffer of bytes in the instruction stream
|
||||||
|
@ -84,13 +86,14 @@ private:
|
||||||
vector<ContextSet> contextcommit;
|
vector<ContextSet> contextcommit;
|
||||||
Address addr; // Address of start of instruction
|
Address addr; // Address of start of instruction
|
||||||
Address naddr; // Address of next instruction
|
Address naddr; // Address of next instruction
|
||||||
|
mutable Address n2addr; // Address of instruction after the next
|
||||||
Address calladdr; // For injections, this is the address of the call being overridden
|
Address calladdr; // For injections, this is the address of the call being overridden
|
||||||
vector<ConstructState> state; // Current resolved instruction
|
vector<ConstructState> state; // Current resolved instruction
|
||||||
ConstructState *base_state;
|
ConstructState *base_state;
|
||||||
int4 alloc; // Number of ConstructState's allocated
|
int4 alloc; // Number of ConstructState's allocated
|
||||||
int4 delayslot; // delayslot depth
|
int4 delayslot; // delayslot depth
|
||||||
public:
|
public:
|
||||||
ParserContext(ContextCache *ccache);
|
ParserContext(ContextCache *ccache,Translate *trans);
|
||||||
~ParserContext(void) { if (context != (uintm *)0) delete [] context; }
|
~ParserContext(void) { if (context != (uintm *)0) delete [] context; }
|
||||||
uint1 *getBuffer(void) { return buf; }
|
uint1 *getBuffer(void) { return buf; }
|
||||||
void initialize(int4 maxstate,int4 maxparam,AddrSpace *spc);
|
void initialize(int4 maxstate,int4 maxparam,AddrSpace *spc);
|
||||||
|
@ -98,7 +101,7 @@ public:
|
||||||
void setParserState(int4 st) { parsestate = st; }
|
void setParserState(int4 st) { parsestate = st; }
|
||||||
void deallocateState(ParserWalkerChange &walker);
|
void deallocateState(ParserWalkerChange &walker);
|
||||||
void allocateOperand(int4 i,ParserWalkerChange &walker);
|
void allocateOperand(int4 i,ParserWalkerChange &walker);
|
||||||
void setAddr(const Address &ad) { addr = ad; }
|
void setAddr(const Address &ad) { addr = ad; n2addr = Address(); }
|
||||||
void setNaddr(const Address &ad) { naddr = ad; }
|
void setNaddr(const Address &ad) { naddr = ad; }
|
||||||
void setCalladdr(const Address &ad) { calladdr = ad; }
|
void setCalladdr(const Address &ad) { calladdr = ad; }
|
||||||
void addCommit(TripleSymbol *sym,int4 num,uintm mask,bool flow,ConstructState *point);
|
void addCommit(TripleSymbol *sym,int4 num,uintm mask,bool flow,ConstructState *point);
|
||||||
|
@ -106,6 +109,7 @@ public:
|
||||||
void applyCommits(void);
|
void applyCommits(void);
|
||||||
const Address &getAddr(void) const { return addr; }
|
const Address &getAddr(void) const { return addr; }
|
||||||
const Address &getNaddr(void) const { return naddr; }
|
const Address &getNaddr(void) const { return naddr; }
|
||||||
|
const Address &getN2addr(void) const;
|
||||||
const Address &getDestAddr(void) const { return calladdr; }
|
const Address &getDestAddr(void) const { return calladdr; }
|
||||||
const Address &getRefAddr(void) const { return calladdr; }
|
const Address &getRefAddr(void) const { return calladdr; }
|
||||||
AddrSpace *getCurSpace(void) const { return addr.getSpace(); }
|
AddrSpace *getCurSpace(void) const { return addr.getSpace(); }
|
||||||
|
@ -147,6 +151,7 @@ public:
|
||||||
AddrSpace *getConstSpace(void) const { return const_context->getConstSpace(); }
|
AddrSpace *getConstSpace(void) const { return const_context->getConstSpace(); }
|
||||||
const Address &getAddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getAddr(); } return const_context->getAddr(); }
|
const Address &getAddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getAddr(); } return const_context->getAddr(); }
|
||||||
const Address &getNaddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getNaddr();} return const_context->getNaddr(); }
|
const Address &getNaddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getNaddr();} return const_context->getNaddr(); }
|
||||||
|
const Address &getN2addr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getN2addr();} return const_context->getN2addr(); }
|
||||||
const Address &getRefAddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getRefAddr();} return const_context->getRefAddr(); }
|
const Address &getRefAddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getRefAddr();} return const_context->getRefAddr(); }
|
||||||
const Address &getDestAddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getDestAddr();} return const_context->getDestAddr(); }
|
const Address &getDestAddr(void) const { if (cross_context != (const ParserContext *)0) { return cross_context->getDestAddr();} return const_context->getDestAddr(); }
|
||||||
int4 getLength(void) const { return const_context->getLength(); }
|
int4 getLength(void) const { return const_context->getLength(); }
|
||||||
|
|
|
@ -791,7 +791,7 @@ void Funcdata::doLiveInject(InjectPayload *payload,const Address &addr,BlockBasi
|
||||||
|
|
||||||
emitter.setFuncdata(this);
|
emitter.setFuncdata(this);
|
||||||
context.clear();
|
context.clear();
|
||||||
context.baseaddr = addr; // Shouldn't be using inst_next and inst_start here
|
context.baseaddr = addr; // Shouldn't be using inst_next, inst_next2 or inst_start here
|
||||||
context.nextaddr = addr;
|
context.nextaddr = addr;
|
||||||
|
|
||||||
list<PcodeOp *>::const_iterator deaditer = obank.endDead();
|
list<PcodeOp *>::const_iterator deaditer = obank.endDead();
|
||||||
|
|
|
@ -333,7 +333,7 @@ void PcodeInjectLibrarySleigh::parseInject(InjectPayload *payload)
|
||||||
throw LowlevelError("Registering pcode snippet before language is instantiated");
|
throw LowlevelError("Registering pcode snippet before language is instantiated");
|
||||||
}
|
}
|
||||||
if (contextCache.pos == (ParserContext *)0) { // Make sure we have a context
|
if (contextCache.pos == (ParserContext *)0) { // Make sure we have a context
|
||||||
contextCache.pos = new ParserContext((ContextCache *)0);
|
contextCache.pos = new ParserContext((ContextCache *)0,(Translate *)0);
|
||||||
contextCache.pos->initialize(8,8,slgh->getConstantSpace());
|
contextCache.pos->initialize(8,8,slgh->getConstantSpace());
|
||||||
}
|
}
|
||||||
PcodeSnippet compiler(slgh);
|
PcodeSnippet compiler(slgh);
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
/// concrete Varnodes. This class contains the context dependent data to resolve:
|
/// concrete Varnodes. This class contains the context dependent data to resolve:
|
||||||
/// - inst_start -- the address where the injection occurs
|
/// - inst_start -- the address where the injection occurs
|
||||||
/// - inst_next -- the address of the instruction following (the instruction being injected)
|
/// - inst_next -- the address of the instruction following (the instruction being injected)
|
||||||
|
/// - inst_next2 -- the address of the instruction after the next instruction (Not Supported)
|
||||||
/// - inst_dest -- Original destination of CALL being injected
|
/// - inst_dest -- Original destination of CALL being injected
|
||||||
/// - inst_ref -- Target of reference on injected instruction
|
/// - inst_ref -- Target of reference on injected instruction
|
||||||
/// - \<input> -- Input Varnode of the injection referenced by name
|
/// - \<input> -- Input Varnode of the injection referenced by name
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,6 +38,7 @@
|
||||||
LabelSymbol *labelsym;
|
LabelSymbol *labelsym;
|
||||||
StartSymbol *startsym;
|
StartSymbol *startsym;
|
||||||
EndSymbol *endsym;
|
EndSymbol *endsym;
|
||||||
|
Next2Symbol *next2sym;
|
||||||
OperandSymbol *operandsym;
|
OperandSymbol *operandsym;
|
||||||
VarnodeSymbol *varsym;
|
VarnodeSymbol *varsym;
|
||||||
SpecificSymbol *specsym;
|
SpecificSymbol *specsym;
|
||||||
|
@ -76,6 +77,7 @@
|
||||||
%token <operandsym> OPERANDSYM
|
%token <operandsym> OPERANDSYM
|
||||||
%token <startsym> STARTSYM
|
%token <startsym> STARTSYM
|
||||||
%token <endsym> ENDSYM
|
%token <endsym> ENDSYM
|
||||||
|
%token <next2sym> NEXT2SYM
|
||||||
%token <labelsym> LABELSYM
|
%token <labelsym> LABELSYM
|
||||||
|
|
||||||
%type <param> paramlist
|
%type <param> paramlist
|
||||||
|
@ -195,6 +197,7 @@ sizedstar: '*' '[' SPACESYM ']' ':' INTEGER { $$ = new StarQuality; $$->size = *
|
||||||
;
|
;
|
||||||
jumpdest: STARTSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
jumpdest: STARTSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
||||||
| ENDSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
| ENDSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
||||||
|
| NEXT2SYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
||||||
| INTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::j_curspace_size)); delete $1; }
|
| INTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::j_curspace_size)); delete $1; }
|
||||||
| BADINTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,0),ConstTpl(ConstTpl::j_curspace_size)); yyerror("Parsed integer is too big (overflow)"); }
|
| BADINTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,0),ConstTpl(ConstTpl::j_curspace_size)); yyerror("Parsed integer is too big (overflow)"); }
|
||||||
| INTEGER '[' SPACESYM ']' { AddrSpace *spc = $3->getSpace(); $$ = new VarnodeTpl(ConstTpl(spc),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::real,spc->getAddrSize())); delete $1; }
|
| INTEGER '[' SPACESYM ']' { AddrSpace *spc = $3->getSpace(); $$ = new VarnodeTpl(ConstTpl(spc),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::real,spc->getAddrSize())); delete $1; }
|
||||||
|
@ -221,6 +224,7 @@ specificsymbol: VARSYM { $$ = $1; }
|
||||||
| OPERANDSYM { $$ = $1; }
|
| OPERANDSYM { $$ = $1; }
|
||||||
| STARTSYM { $$ = $1; }
|
| STARTSYM { $$ = $1; }
|
||||||
| ENDSYM { $$ = $1; }
|
| ENDSYM { $$ = $1; }
|
||||||
|
| NEXT2SYM { $$ = $1; }
|
||||||
;
|
;
|
||||||
paramlist: /* EMPTY */ { $$ = new vector<ExprTree *>; }
|
paramlist: /* EMPTY */ { $$ = new vector<ExprTree *>; }
|
||||||
| expr { $$ = new vector<ExprTree *>; $$->push_back($1); }
|
| expr { $$ = new vector<ExprTree *>; $$->push_back($1); }
|
||||||
|
@ -749,6 +753,9 @@ int4 PcodeSnippet::lex(void)
|
||||||
case SleighSymbol::end_symbol:
|
case SleighSymbol::end_symbol:
|
||||||
yylval.endsym = (EndSymbol *)sym;
|
yylval.endsym = (EndSymbol *)sym;
|
||||||
return ENDSYM;
|
return ENDSYM;
|
||||||
|
case SleighSymbol::next2_symbol:
|
||||||
|
yylval.next2sym = (Next2Symbol *)sym;
|
||||||
|
return NEXT2SYM;
|
||||||
case SleighSymbol::label_symbol:
|
case SleighSymbol::label_symbol:
|
||||||
yylval.labelsym = (LabelSymbol *)sym;
|
yylval.labelsym = (LabelSymbol *)sym;
|
||||||
return LABELSYM;
|
return LABELSYM;
|
||||||
|
|
|
@ -121,6 +121,8 @@ uintb ConstTpl::fix(const ParserWalker &walker) const
|
||||||
return walker.getAddr().getOffset(); // Fill in starting address placeholder with real address
|
return walker.getAddr().getOffset(); // Fill in starting address placeholder with real address
|
||||||
case j_next:
|
case j_next:
|
||||||
return walker.getNaddr().getOffset(); // Fill in next address placeholder with real address
|
return walker.getNaddr().getOffset(); // Fill in next address placeholder with real address
|
||||||
|
case j_next2:
|
||||||
|
return walker.getN2addr().getOffset(); // Fill in next2 address placeholder with real address
|
||||||
case j_flowref:
|
case j_flowref:
|
||||||
return walker.getRefAddr().getOffset();
|
return walker.getRefAddr().getOffset();
|
||||||
case j_flowref_size:
|
case j_flowref_size:
|
||||||
|
@ -349,6 +351,9 @@ void ConstTpl::saveXml(ostream &s) const
|
||||||
case j_next:
|
case j_next:
|
||||||
s << "next\"/>";
|
s << "next\"/>";
|
||||||
break;
|
break;
|
||||||
|
case j_next2:
|
||||||
|
s << "next2\"/>";
|
||||||
|
break;
|
||||||
case j_curspace:
|
case j_curspace:
|
||||||
s << "curspace\"/>";
|
s << "curspace\"/>";
|
||||||
break;
|
break;
|
||||||
|
@ -404,6 +409,9 @@ void ConstTpl::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
||||||
else if (typestring=="next") {
|
else if (typestring=="next") {
|
||||||
type = j_next;
|
type = j_next;
|
||||||
}
|
}
|
||||||
|
else if (typestring=="next2") {
|
||||||
|
type = j_next2;
|
||||||
|
}
|
||||||
else if (typestring=="curspace") {
|
else if (typestring=="curspace") {
|
||||||
type = j_curspace;
|
type = j_curspace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ class Translate; // Forward declaration
|
||||||
class HandleTpl; // Forward declaration
|
class HandleTpl; // Forward declaration
|
||||||
class ConstTpl {
|
class ConstTpl {
|
||||||
public:
|
public:
|
||||||
enum const_type { real=0, handle=1, j_start=2, j_next=3, j_curspace=4,
|
enum const_type { real=0, handle=1, j_start=2, j_next=3, j_next2=4, j_curspace=5,
|
||||||
j_curspace_size=5, spaceid=6, j_relative=7,
|
j_curspace_size=6, spaceid=7, j_relative=8,
|
||||||
j_flowref=8, j_flowref_size=9, j_flowdest=10, j_flowdest_size=11 };
|
j_flowref=9, j_flowref_size=10, j_flowdest=11, j_flowdest_size=12 };
|
||||||
enum v_field { v_space=0, v_offset=1, v_size=2, v_offset_plus=3 };
|
enum v_field { v_space=0, v_offset=1, v_size=2, v_offset_plus=3 };
|
||||||
private:
|
private:
|
||||||
const_type type;
|
const_type type;
|
||||||
|
|
|
@ -444,7 +444,7 @@ void DisassemblyCache::initialize(int4 min,int4 hashsize)
|
||||||
nextfree = 0;
|
nextfree = 0;
|
||||||
hashtable = new ParserContext *[hashsize];
|
hashtable = new ParserContext *[hashsize];
|
||||||
for(int4 i=0;i<minimumreuse;++i) {
|
for(int4 i=0;i<minimumreuse;++i) {
|
||||||
ParserContext *pos = new ParserContext(contextcache);
|
ParserContext *pos = new ParserContext(contextcache,translate);
|
||||||
pos->initialize(75,20,constspace);
|
pos->initialize(75,20,constspace);
|
||||||
list[i] = pos;
|
list[i] = pos;
|
||||||
}
|
}
|
||||||
|
@ -462,13 +462,15 @@ void DisassemblyCache::free(void)
|
||||||
delete [] hashtable;
|
delete [] hashtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \param trans is the Translate object instantiating this cache (for inst_next2 callbacks)
|
||||||
/// \param ccache is the ContextCache front-end shared across all the parser contexts
|
/// \param ccache is the ContextCache front-end shared across all the parser contexts
|
||||||
/// \param cspace is the constant address space used for minting constant Varnodes
|
/// \param cspace is the constant address space used for minting constant Varnodes
|
||||||
/// \param cachesize is the number of distinct ParserContext objects in this cache
|
/// \param cachesize is the number of distinct ParserContext objects in this cache
|
||||||
/// \param windowsize is the size of the ParserContext hash-table
|
/// \param windowsize is the size of the ParserContext hash-table
|
||||||
DisassemblyCache::DisassemblyCache(ContextCache *ccache,AddrSpace *cspace,int4 cachesize,int4 windowsize)
|
DisassemblyCache::DisassemblyCache(Translate *trans,ContextCache *ccache,AddrSpace *cspace,int4 cachesize,int4 windowsize)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
translate = trans;
|
||||||
contextcache = ccache;
|
contextcache = ccache;
|
||||||
constspace = cspace;
|
constspace = cspace;
|
||||||
initialize(cachesize,windowsize); // Set default settings for the cache
|
initialize(cachesize,windowsize); // Set default settings for the cache
|
||||||
|
@ -559,7 +561,7 @@ void Sleigh::initialize(DocumentStorage &store)
|
||||||
parser_cachesize = 8;
|
parser_cachesize = 8;
|
||||||
parser_windowsize = 256;
|
parser_windowsize = 256;
|
||||||
}
|
}
|
||||||
discache = new DisassemblyCache(cache,getConstantSpace(),parser_cachesize,parser_windowsize);
|
discache = new DisassemblyCache(this,cache,getConstantSpace(),parser_cachesize,parser_windowsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Obtain a parse tree for the instruction at the given address
|
/// \brief Obtain a parse tree for the instruction at the given address
|
||||||
|
|
|
@ -103,6 +103,7 @@ public:
|
||||||
/// accessing the ContextDatabase and resolving context variables from the SLEIGH spec.
|
/// accessing the ContextDatabase and resolving context variables from the SLEIGH spec.
|
||||||
/// ParserContext objects are stored in a hash-table keyed by the address of the instruction.
|
/// ParserContext objects are stored in a hash-table keyed by the address of the instruction.
|
||||||
class DisassemblyCache {
|
class DisassemblyCache {
|
||||||
|
Translate *translate; ///< The Translate object that owns this cache
|
||||||
ContextCache *contextcache; ///< Cached values from the ContextDatabase
|
ContextCache *contextcache; ///< Cached values from the ContextDatabase
|
||||||
AddrSpace *constspace; ///< The constant address space
|
AddrSpace *constspace; ///< The constant address space
|
||||||
int4 minimumreuse; ///< Can call getParserContext this many times, before a ParserContext is reused
|
int4 minimumreuse; ///< Can call getParserContext this many times, before a ParserContext is reused
|
||||||
|
@ -113,7 +114,7 @@ class DisassemblyCache {
|
||||||
void initialize(int4 min,int4 hashsize); ///< Initialize the hash-table of ParserContexts
|
void initialize(int4 min,int4 hashsize); ///< Initialize the hash-table of ParserContexts
|
||||||
void free(void); ///< Free the hash-table of ParserContexts
|
void free(void); ///< Free the hash-table of ParserContexts
|
||||||
public:
|
public:
|
||||||
DisassemblyCache(ContextCache *ccache,AddrSpace *cspace,int4 cachesize,int4 windowsize); ///< Constructor
|
DisassemblyCache(Translate *trans,ContextCache *ccache,AddrSpace *cspace,int4 cachesize,int4 windowsize); ///< Constructor
|
||||||
~DisassemblyCache(void) { free(); } ///< Destructor
|
~DisassemblyCache(void) { free(); } ///< Destructor
|
||||||
ParserContext *getParserContext(const Address &addr); ///< Get the parser for a particular Address
|
ParserContext *getParserContext(const Address &addr); ///< Get the parser for a particular Address
|
||||||
};
|
};
|
||||||
|
|
|
@ -1789,7 +1789,7 @@ SleighCompile::SleighCompile(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the address spaces: \b const, \b unique, and \b other.
|
/// Create the address spaces: \b const, \b unique, and \b other.
|
||||||
/// Define the special symbols: \b inst_start, \b inst_next, \b epsilon.
|
/// Define the special symbols: \b inst_start, \b inst_next, \b inst_next2, \b epsilon.
|
||||||
/// Define the root subtable symbol: \b instruction
|
/// Define the root subtable symbol: \b instruction
|
||||||
void SleighCompile::predefinedSymbols(void)
|
void SleighCompile::predefinedSymbols(void)
|
||||||
|
|
||||||
|
@ -1813,6 +1813,8 @@ void SleighCompile::predefinedSymbols(void)
|
||||||
symtab.addSymbol(startsym);
|
symtab.addSymbol(startsym);
|
||||||
EndSymbol *endsym = new EndSymbol("inst_next",getConstantSpace());
|
EndSymbol *endsym = new EndSymbol("inst_next",getConstantSpace());
|
||||||
symtab.addSymbol(endsym);
|
symtab.addSymbol(endsym);
|
||||||
|
Next2Symbol *next2sym = new Next2Symbol("inst_next2",getConstantSpace());
|
||||||
|
symtab.addSymbol(next2sym);
|
||||||
EpsilonSymbol *epsilon = new EpsilonSymbol("epsilon",getConstantSpace());
|
EpsilonSymbol *epsilon = new EpsilonSymbol("epsilon",getConstantSpace());
|
||||||
symtab.addSymbol(epsilon);
|
symtab.addSymbol(epsilon);
|
||||||
pcode.setConstantSpace(getConstantSpace());
|
pcode.setConstantSpace(getConstantSpace());
|
||||||
|
@ -2907,20 +2909,23 @@ ConstructTpl *SleighCompile::setResultStarVarnode(ConstructTpl *ct,StarQuality *
|
||||||
/// The new change operation is added to the current list.
|
/// The new change operation is added to the current list.
|
||||||
/// When executed, the change operation will assign a new value to the given context variable
|
/// When executed, the change operation will assign a new value to the given context variable
|
||||||
/// using the specified expression. The change only applies within the parsing of a single instruction.
|
/// using the specified expression. The change only applies within the parsing of a single instruction.
|
||||||
/// Because we are in the middle of parsing, the \b inst_next value has not been computed yet
|
/// Because we are in the middle of parsing, the \b inst_next and \b inst_next2 values have not
|
||||||
/// So we check to make sure the value expression doesn't use this symbol.
|
/// been computed yet. So we check to make sure the value expression doesn't use this symbol.
|
||||||
/// \param vec is the current list of change operations
|
/// \param vec is the current list of change operations
|
||||||
/// \param sym is the given context variable affected by the operation
|
/// \param sym is the given context variable affected by the operation
|
||||||
/// \param pe is the specified expression
|
/// \param pe is the specified expression
|
||||||
/// \return \b true if the expression does not use the \b inst_next symbol
|
/// \return \b true if the expression does not use the \b inst_next or \b inst_next2 symbol
|
||||||
bool SleighCompile::contextMod(vector<ContextChange *> *vec,ContextSymbol *sym,PatternExpression *pe)
|
bool SleighCompile::contextMod(vector<ContextChange *> *vec,ContextSymbol *sym,PatternExpression *pe)
|
||||||
|
|
||||||
{
|
{
|
||||||
vector<const PatternValue *> vallist;
|
vector<const PatternValue *> vallist;
|
||||||
pe->listValues(vallist);
|
pe->listValues(vallist);
|
||||||
for(uint4 i=0;i<vallist.size();++i)
|
for(uint4 i=0;i<vallist.size();++i) {
|
||||||
if (dynamic_cast<const EndInstructionValue *>(vallist[i]) != (const EndInstructionValue *)0)
|
if (dynamic_cast<const EndInstructionValue *>(vallist[i]) != (const EndInstructionValue *)0)
|
||||||
return false;
|
return false;
|
||||||
|
if (dynamic_cast<const Next2InstructionValue *>(vallist[i]) != (const Next2InstructionValue *)0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Otherwise we generate a "temporary" change to context instruction (ContextOp)
|
// Otherwise we generate a "temporary" change to context instruction (ContextOp)
|
||||||
ContextField *field = (ContextField *)sym->getPatternValue();
|
ContextField *field = (ContextField *)sym->getPatternValue();
|
||||||
ContextOp *op = new ContextOp(field->getStartBit(),field->getEndBit(),pe);
|
ContextOp *op = new ContextOp(field->getStartBit(),field->getEndBit(),pe);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -45,8 +45,8 @@
|
||||||
This special exception was added by the Free Software Foundation in
|
This special exception was added by the Free Software Foundation in
|
||||||
version 2.2 of Bison. */
|
version 2.2 of Bison. */
|
||||||
|
|
||||||
#ifndef YY_YY_SRC_DECOMPILE_CPP_SLGHPARSE_HH_INCLUDED
|
#ifndef YY_YY_SLGHPARSE_HH_INCLUDED
|
||||||
# define YY_YY_SRC_DECOMPILE_CPP_SLGHPARSE_HH_INCLUDED
|
# define YY_YY_SLGHPARSE_HH_INCLUDED
|
||||||
/* Debug traces. */
|
/* Debug traces. */
|
||||||
#ifndef YYDEBUG
|
#ifndef YYDEBUG
|
||||||
# define YYDEBUG 0
|
# define YYDEBUG 0
|
||||||
|
@ -168,9 +168,10 @@ extern int yydebug;
|
||||||
OPERANDSYM = 363,
|
OPERANDSYM = 363,
|
||||||
STARTSYM = 364,
|
STARTSYM = 364,
|
||||||
ENDSYM = 365,
|
ENDSYM = 365,
|
||||||
MACROSYM = 366,
|
NEXT2SYM = 366,
|
||||||
LABELSYM = 367,
|
MACROSYM = 367,
|
||||||
SUBTABLESYM = 368
|
LABELSYM = 368,
|
||||||
|
SUBTABLESYM = 369
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ extern int yydebug;
|
||||||
|
|
||||||
union YYSTYPE
|
union YYSTYPE
|
||||||
{
|
{
|
||||||
#line 29 "src/decompile/cpp/slghparse.y" /* yacc.c:1909 */
|
#line 29 "slghparse.y" /* yacc.c:1909 */
|
||||||
|
|
||||||
char ch;
|
char ch;
|
||||||
uintb *i;
|
uintb *i;
|
||||||
|
@ -212,6 +213,7 @@ union YYSTYPE
|
||||||
SubtableSymbol *subtablesym;
|
SubtableSymbol *subtablesym;
|
||||||
StartSymbol *startsym;
|
StartSymbol *startsym;
|
||||||
EndSymbol *endsym;
|
EndSymbol *endsym;
|
||||||
|
Next2Symbol *next2sym;
|
||||||
OperandSymbol *operandsym;
|
OperandSymbol *operandsym;
|
||||||
VarnodeListSymbol *varlistsym;
|
VarnodeListSymbol *varlistsym;
|
||||||
VarnodeSymbol *varsym;
|
VarnodeSymbol *varsym;
|
||||||
|
@ -223,7 +225,7 @@ union YYSTYPE
|
||||||
FamilySymbol *famsym;
|
FamilySymbol *famsym;
|
||||||
SpecificSymbol *specsym;
|
SpecificSymbol *specsym;
|
||||||
|
|
||||||
#line 212 "src/decompile/cpp/slghparse.hh" /* yacc.c:1909 */
|
#line 214 "slghparse.hh" /* yacc.c:1909 */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union YYSTYPE YYSTYPE;
|
typedef union YYSTYPE YYSTYPE;
|
||||||
|
@ -236,4 +238,4 @@ extern YYSTYPE yylval;
|
||||||
|
|
||||||
int yyparse (void);
|
int yyparse (void);
|
||||||
|
|
||||||
#endif /* !YY_YY_SRC_DECOMPILE_CPP_SLGHPARSE_HH_INCLUDED */
|
#endif /* !YY_YY_SLGHPARSE_HH_INCLUDED */
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
SubtableSymbol *subtablesym;
|
SubtableSymbol *subtablesym;
|
||||||
StartSymbol *startsym;
|
StartSymbol *startsym;
|
||||||
EndSymbol *endsym;
|
EndSymbol *endsym;
|
||||||
|
Next2Symbol *next2sym;
|
||||||
OperandSymbol *operandsym;
|
OperandSymbol *operandsym;
|
||||||
VarnodeListSymbol *varlistsym;
|
VarnodeListSymbol *varlistsym;
|
||||||
VarnodeSymbol *varsym;
|
VarnodeSymbol *varsym;
|
||||||
|
@ -121,6 +122,7 @@
|
||||||
%token <operandsym> OPERANDSYM
|
%token <operandsym> OPERANDSYM
|
||||||
%token <startsym> STARTSYM
|
%token <startsym> STARTSYM
|
||||||
%token <endsym> ENDSYM
|
%token <endsym> ENDSYM
|
||||||
|
%token <next2sym> NEXT2SYM
|
||||||
%token <macrosym> MACROSYM
|
%token <macrosym> MACROSYM
|
||||||
%token <labelsym> LABELSYM
|
%token <labelsym> LABELSYM
|
||||||
%token <subtablesym> SUBTABLESYM
|
%token <subtablesym> SUBTABLESYM
|
||||||
|
@ -331,7 +333,7 @@ contextblock: { $$ = (vector<ContextChange *> *)0; }
|
||||||
| '[' contextlist ']' { $$ = $2; }
|
| '[' contextlist ']' { $$ = $2; }
|
||||||
;
|
;
|
||||||
contextlist: { $$ = new vector<ContextChange *>; }
|
contextlist: { $$ = new vector<ContextChange *>; }
|
||||||
| contextlist CONTEXTSYM '=' pexpression ';' { $$ = $1; if (!slgh->contextMod($1,$2,$4)) { string errmsg="Cannot use 'inst_next' to set context variable: "+$2->getName(); yyerror(errmsg.c_str()); YYERROR; } }
|
| contextlist CONTEXTSYM '=' pexpression ';' { $$ = $1; if (!slgh->contextMod($1,$2,$4)) { string errmsg="Cannot use 'inst_next' or 'inst_next2' to set context variable: "+$2->getName(); yyerror(errmsg.c_str()); YYERROR; } }
|
||||||
| contextlist GLOBALSET_KEY '(' familysymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
|
| contextlist GLOBALSET_KEY '(' familysymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
|
||||||
| contextlist GLOBALSET_KEY '(' specificsymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
|
| contextlist GLOBALSET_KEY '(' specificsymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
|
||||||
| contextlist OPERANDSYM '=' pexpression ';' { $$ = $1; slgh->defineOperand($2,$4); }
|
| contextlist OPERANDSYM '=' pexpression ';' { $$ = $1; slgh->defineOperand($2,$4); }
|
||||||
|
@ -456,6 +458,7 @@ sizedstar: '*' '[' SPACESYM ']' ':' INTEGER { $$ = new StarQuality; $$->size = *
|
||||||
;
|
;
|
||||||
jumpdest: STARTSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
jumpdest: STARTSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
||||||
| ENDSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
| ENDSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
||||||
|
| NEXT2SYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),sym->getOffset(),ConstTpl(ConstTpl::j_curspace_size)); delete sym; }
|
||||||
| INTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::j_curspace_size)); delete $1; }
|
| INTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::j_curspace_size)); delete $1; }
|
||||||
| BADINTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,0),ConstTpl(ConstTpl::j_curspace_size)); yyerror("Parsed integer is too big (overflow)"); }
|
| BADINTEGER { $$ = new VarnodeTpl(ConstTpl(ConstTpl::j_curspace),ConstTpl(ConstTpl::real,0),ConstTpl(ConstTpl::j_curspace_size)); yyerror("Parsed integer is too big (overflow)"); }
|
||||||
| OPERANDSYM { $$ = $1->getVarnode(); $1->setCodeAddress(); }
|
| OPERANDSYM { $$ = $1->getVarnode(); $1->setCodeAddress(); }
|
||||||
|
@ -499,6 +502,7 @@ specificsymbol: VARSYM { $$ = $1; }
|
||||||
| OPERANDSYM { $$ = $1; }
|
| OPERANDSYM { $$ = $1; }
|
||||||
| STARTSYM { $$ = $1; }
|
| STARTSYM { $$ = $1; }
|
||||||
| ENDSYM { $$ = $1; }
|
| ENDSYM { $$ = $1; }
|
||||||
|
| NEXT2SYM { $$ = $1; }
|
||||||
;
|
;
|
||||||
charstring: CHAR { $$ = new string; (*$$) += $1; }
|
charstring: CHAR { $$ = new string; (*$$) += $1; }
|
||||||
| charstring CHAR { $$ = $1; (*$$) += $2; }
|
| charstring CHAR { $$ = $1; (*$$) += $2; }
|
||||||
|
@ -573,6 +577,7 @@ anysymbol: SPACESYM { $$ = $1; }
|
||||||
| OPERANDSYM { $$ = $1; }
|
| OPERANDSYM { $$ = $1; }
|
||||||
| STARTSYM { $$ = $1; }
|
| STARTSYM { $$ = $1; }
|
||||||
| ENDSYM { $$ = $1; }
|
| ENDSYM { $$ = $1; }
|
||||||
|
| NEXT2SYM { $$ = $1; }
|
||||||
| BITSYM { $$ = $1; }
|
| BITSYM { $$ = $1; }
|
||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
|
|
|
@ -165,6 +165,19 @@ public:
|
||||||
virtual void restoreXml(const Element *el,Translate *trans) {}
|
virtual void restoreXml(const Element *el,Translate *trans) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Next2InstructionValue : public PatternValue {
|
||||||
|
public:
|
||||||
|
Next2InstructionValue(void) {}
|
||||||
|
virtual intb getValue(ParserWalker &walker) const {
|
||||||
|
return (intb)AddrSpace::byteToAddress(walker.getN2addr().getOffset(),walker.getN2addr().getSpace()->getWordSize()); }
|
||||||
|
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); }
|
||||||
|
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
|
||||||
|
virtual intb minValue(void) const { return (intb)0; }
|
||||||
|
virtual intb maxValue(void) const { return (intb)0; }
|
||||||
|
virtual void saveXml(ostream &s) const { s << "<next2_exp/>"; }
|
||||||
|
virtual void restoreXml(const Element *el,Translate *trans) {}
|
||||||
|
};
|
||||||
|
|
||||||
class Constructor; // Forward declaration
|
class Constructor; // Forward declaration
|
||||||
class OperandSymbol;
|
class OperandSymbol;
|
||||||
class OperandValue : public PatternValue {
|
class OperandValue : public PatternValue {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -429,6 +429,9 @@ int4 find_symbol(void) {
|
||||||
case SleighSymbol::end_symbol:
|
case SleighSymbol::end_symbol:
|
||||||
yylval.endsym = (EndSymbol *)sym;
|
yylval.endsym = (EndSymbol *)sym;
|
||||||
return ENDSYM;
|
return ENDSYM;
|
||||||
|
case SleighSymbol::next2_symbol:
|
||||||
|
yylval.next2sym = (Next2Symbol *)sym;
|
||||||
|
return NEXT2SYM;
|
||||||
case SleighSymbol::subtable_symbol:
|
case SleighSymbol::subtable_symbol:
|
||||||
yylval.subtablesym = (SubtableSymbol *)sym;
|
yylval.subtablesym = (SubtableSymbol *)sym;
|
||||||
return SUBTABLESYM;
|
return SUBTABLESYM;
|
||||||
|
|
|
@ -252,6 +252,8 @@ void SymbolTable::restoreSymbolHeader(const Element *el)
|
||||||
sym = new StartSymbol();
|
sym = new StartSymbol();
|
||||||
else if (el->getName() == "end_sym_head")
|
else if (el->getName() == "end_sym_head")
|
||||||
sym = new EndSymbol();
|
sym = new EndSymbol();
|
||||||
|
else if (el->getName() == "next2_sym_head")
|
||||||
|
sym = new Next2Symbol();
|
||||||
else if (el->getName() == "subtable_sym_head")
|
else if (el->getName() == "subtable_sym_head")
|
||||||
sym = new SubtableSymbol();
|
sym = new SubtableSymbol();
|
||||||
else if (el->getName() == "flowdest_sym_head")
|
else if (el->getName() == "flowdest_sym_head")
|
||||||
|
@ -1254,6 +1256,70 @@ void EndSymbol::restoreXml(const Element *el,SleighBase *trans)
|
||||||
patexp->layClaim();
|
patexp->layClaim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Next2Symbol::Next2Symbol(const string &nm,AddrSpace *cspc) : SpecificSymbol(nm)
|
||||||
|
|
||||||
|
{
|
||||||
|
const_space = cspc;
|
||||||
|
patexp = new Next2InstructionValue();
|
||||||
|
patexp->layClaim();
|
||||||
|
}
|
||||||
|
|
||||||
|
Next2Symbol::~Next2Symbol(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (patexp != (PatternExpression *)0)
|
||||||
|
PatternExpression::release(patexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
VarnodeTpl *Next2Symbol::getVarnode(void) const
|
||||||
|
|
||||||
|
{ // Return instruction offset after next instruction offset as a constant
|
||||||
|
ConstTpl spc(const_space);
|
||||||
|
ConstTpl off(ConstTpl::j_next2);
|
||||||
|
ConstTpl sz_zero;
|
||||||
|
return new VarnodeTpl(spc,off,sz_zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next2Symbol::getFixedHandle(FixedHandle &hand,ParserWalker &walker) const
|
||||||
|
|
||||||
|
{
|
||||||
|
hand.space = walker.getCurSpace();
|
||||||
|
hand.offset_space = (AddrSpace *)0;
|
||||||
|
hand.offset_offset = walker.getN2addr().getOffset(); // Get instruction address after next instruction
|
||||||
|
hand.size = hand.space->getAddrSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next2Symbol::print(ostream &s,ParserWalker &walker) const
|
||||||
|
|
||||||
|
{
|
||||||
|
intb val = (intb) walker.getN2addr().getOffset();
|
||||||
|
s << "0x" << hex << val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next2Symbol::saveXml(ostream &s) const
|
||||||
|
|
||||||
|
{
|
||||||
|
s << "<next2_sym";
|
||||||
|
SleighSymbol::saveXmlHeader(s);
|
||||||
|
s << "/>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next2Symbol::saveXmlHeader(ostream &s) const
|
||||||
|
|
||||||
|
{
|
||||||
|
s << "<next2_sym_head";
|
||||||
|
SleighSymbol::saveXmlHeader(s);
|
||||||
|
s << "/>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Next2Symbol::restoreXml(const Element *el,SleighBase *trans)
|
||||||
|
|
||||||
|
{
|
||||||
|
const_space = trans->getConstantSpace();
|
||||||
|
patexp = new Next2InstructionValue();
|
||||||
|
patexp->layClaim();
|
||||||
|
}
|
||||||
|
|
||||||
FlowDestSymbol::FlowDestSymbol(const string &nm,AddrSpace *cspc) : SpecificSymbol(nm)
|
FlowDestSymbol::FlowDestSymbol(const string &nm,AddrSpace *cspc) : SpecificSymbol(nm)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ class SleighSymbol {
|
||||||
public:
|
public:
|
||||||
enum symbol_type { space_symbol, token_symbol, userop_symbol, value_symbol, valuemap_symbol,
|
enum symbol_type { space_symbol, token_symbol, userop_symbol, value_symbol, valuemap_symbol,
|
||||||
name_symbol, varnode_symbol, varnodelist_symbol, operand_symbol,
|
name_symbol, varnode_symbol, varnodelist_symbol, operand_symbol,
|
||||||
start_symbol, end_symbol, subtable_symbol, macro_symbol, section_symbol,
|
start_symbol, end_symbol, next2_symbol, subtable_symbol, macro_symbol, section_symbol,
|
||||||
bitrange_symbol, context_symbol, epsilon_symbol, label_symbol,
|
bitrange_symbol, context_symbol, epsilon_symbol, label_symbol,
|
||||||
dummy_symbol };
|
dummy_symbol };
|
||||||
private:
|
private:
|
||||||
|
@ -391,6 +391,23 @@ public:
|
||||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Next2Symbol : public SpecificSymbol {
|
||||||
|
AddrSpace *const_space;
|
||||||
|
PatternExpression *patexp;
|
||||||
|
public:
|
||||||
|
Next2Symbol(void) { patexp = (PatternExpression *)0; } // For use with restoreXml
|
||||||
|
Next2Symbol(const string &nm,AddrSpace *cspc);
|
||||||
|
virtual ~Next2Symbol(void);
|
||||||
|
virtual VarnodeTpl *getVarnode(void) const;
|
||||||
|
virtual PatternExpression *getPatternExpression(void) const { return patexp; }
|
||||||
|
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||||
|
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||||
|
virtual symbol_type getType(void) const { return next2_symbol; }
|
||||||
|
virtual void saveXml(ostream &s) const;
|
||||||
|
virtual void saveXmlHeader(ostream &s) const;
|
||||||
|
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||||
|
};
|
||||||
|
|
||||||
class FlowDestSymbol : public SpecificSymbol {
|
class FlowDestSymbol : public SpecificSymbol {
|
||||||
AddrSpace *const_space;
|
AddrSpace *const_space;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<decompilertest>
|
||||||
|
<binaryimage arch="Toy:BE:32:builder.align2:default">
|
||||||
|
<!--
|
||||||
|
Test SLEIGH inst_next2 functionality via the Toy "skeq", (skip if equal) instruction
|
||||||
|
-->
|
||||||
|
<bytechunk space="ram" offset="0x10">
|
||||||
|
0a0acec58000c0abdfcaf400
|
||||||
|
</bytechunk>
|
||||||
|
<symbol name="skipinst" space="ram" offset="0x10"/>
|
||||||
|
</binaryimage>
|
||||||
|
<script>
|
||||||
|
<com>lo fu skipinst</com>
|
||||||
|
<com>decompile</com>
|
||||||
|
<com>print C</com>
|
||||||
|
<com>quit</com>
|
||||||
|
</script>
|
||||||
|
<stringmatch name="Skip Instruction #1" min="1" max="1">if \(param_1 != 5\)</stringmatch>
|
||||||
|
<stringmatch name="Skip Instruction #2" min="1" max="1">iVar1 = param_2 \+ 10;</stringmatch>
|
||||||
|
</decompilertest>
|
|
@ -506,8 +506,8 @@ parameters in the actual p-code operation, or an exception will be thrown during
|
||||||
As with a <code><callfixup></code>, the <code><body></code> tag is fed straight to the SLEIGH semantic
|
As with a <code><callfixup></code>, the <code><body></code> tag is fed straight to the SLEIGH semantic
|
||||||
parser. It can refer to registers via their symbolic name defined in SLEIGH, it can refer to the operator parameters
|
parser. It can refer to registers via their symbolic name defined in SLEIGH, it can refer to the operator parameters
|
||||||
via their <code><input></code> or <code><output></code> names, and it can also refer to
|
via their <code><input></code> or <code><output></code> names, and it can also refer to
|
||||||
<code>inst_start</code> and <code>inst_next</code> as addresses describing the instruction containing the
|
<code>inst_start</code>, <code>inst_next</code> and <code>inst_next2</code> as addresses describing the instruction
|
||||||
<code>CALLOTHER</code>.
|
containing the <code>CALLOTHER</code>.
|
||||||
</para>
|
</para>
|
||||||
<example>
|
<example>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<article>
|
<article id="pcoderef_title">
|
||||||
<info>
|
<info>
|
||||||
<title>P-Code Reference Manual</title>
|
<title>P-Code Reference Manual</title>
|
||||||
<releaseinfo>Last updated September 5, 2019</releaseinfo>
|
<releaseinfo>Last updated September 5, 2019</releaseinfo>
|
||||||
|
@ -184,7 +184,7 @@ longer match their <emphasis>raw p-code</emphasis> form.
|
||||||
<para>
|
<para>
|
||||||
The core concepts of p-code are:
|
The core concepts of p-code are:
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2 id="pcoderef_address_space">
|
||||||
<title>Address Space</title>
|
<title>Address Space</title>
|
||||||
<para>
|
<para>
|
||||||
The <emphasis role="bold">address space</emphasis> for p-code is a generalization
|
The <emphasis role="bold">address space</emphasis> for p-code is a generalization
|
||||||
|
@ -224,7 +224,7 @@ right byte offset when dereferencing the pointer. The wordsize attribute has no
|
||||||
any of the other p-code operations.
|
any of the other p-code operations.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="pcoderef_varnode">
|
||||||
<title>Varnode</title>
|
<title>Varnode</title>
|
||||||
<para>
|
<para>
|
||||||
A <emphasis role="bold">varnode</emphasis> is a generalization of
|
A <emphasis role="bold">varnode</emphasis> is a generalization of
|
||||||
|
@ -270,7 +270,7 @@ of the constant. As with other varnodes, constants only have a type forced
|
||||||
on them by the p-code operations that use them.
|
on them by the p-code operations that use them.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="pcoderef_pcode_operation">
|
||||||
<title>P-code Operation</title>
|
<title>P-code Operation</title>
|
||||||
<para>
|
<para>
|
||||||
A <emphasis role="bold">p-code operation</emphasis> is the analog of a
|
A <emphasis role="bold">p-code operation</emphasis> is the analog of a
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<article>
|
<article id="sleigh_title">
|
||||||
<info>
|
<info>
|
||||||
<title>SLEIGH</title>
|
<title>SLEIGH</title>
|
||||||
<subtitle>A Language for Rapid Processor Specification</subtitle>
|
<subtitle>A Language for Rapid Processor Specification</subtitle>
|
||||||
<pubdate>Originally published December 16, 2005</pubdate>
|
<pubdate>Originally published December 16, 2005</pubdate>
|
||||||
<releaseinfo>Last updated October 28, 2020</releaseinfo>
|
<releaseinfo>Last updated August 24, 2022</releaseinfo>
|
||||||
</info>
|
</info>
|
||||||
<simplesect>
|
<simplesect id="sleigh_history">
|
||||||
<info>
|
<info>
|
||||||
<title>History</title>
|
<title>History</title>
|
||||||
</info>
|
</info>
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
</para>
|
</para>
|
||||||
</simplesect>
|
</simplesect>
|
||||||
|
|
||||||
<simplesect>
|
<simplesect id="sleigh_overview">
|
||||||
<info>
|
<info>
|
||||||
<title>Overview</title>
|
<title>Overview</title>
|
||||||
</info>
|
</info>
|
||||||
|
@ -70,7 +70,7 @@ will always refer to this target of the specification.
|
||||||
Italics are used when defining terms and for named entities. Bold is used for SLEIGH keywords.
|
Italics are used when defining terms and for named entities. Bold is used for SLEIGH keywords.
|
||||||
</para>
|
</para>
|
||||||
</simplesect>
|
</simplesect>
|
||||||
<sect1>
|
<sect1 id="sleigh_introduction">
|
||||||
<title>Introduction to P-Code</title>
|
<title>Introduction to P-Code</title>
|
||||||
<para>
|
<para>
|
||||||
Although p-code is a distinct language from SLEIGH, because a major
|
Although p-code is a distinct language from SLEIGH, because a major
|
||||||
|
@ -128,7 +128,7 @@ the <emphasis>operation</emphasis>. These are generalizations of the
|
||||||
computing concepts of RAM, registers, and machine instructions
|
computing concepts of RAM, registers, and machine instructions
|
||||||
respectively.
|
respectively.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2 id="sleigh_address_spaces">
|
||||||
<title>Address Spaces</title>
|
<title>Address Spaces</title>
|
||||||
<para>
|
<para>
|
||||||
An <emphasis>address</emphasis> space for p-code is a generalization of
|
An <emphasis>address</emphasis> space for p-code is a generalization of
|
||||||
|
@ -227,7 +227,7 @@ different way. Any consistent meaning assigned to a particular varnode
|
||||||
must be provided and enforced by the specification designer.
|
must be provided and enforced by the specification designer.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_operations">
|
||||||
<title>Operations</title>
|
<title>Operations</title>
|
||||||
<para>
|
<para>
|
||||||
P-code is intended to emulate a target processor by substituting a
|
P-code is intended to emulate a target processor by substituting a
|
||||||
|
@ -331,7 +331,7 @@ follow a specific format as parsed by the SLEIGH compiler. In this
|
||||||
section, we list the basic formatting rules for this file as enforced
|
section, we list the basic formatting rules for this file as enforced
|
||||||
by the compiler.
|
by the compiler.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2 id="sleigh_comments">
|
||||||
<title>Comments</title>
|
<title>Comments</title>
|
||||||
<para>
|
<para>
|
||||||
Comments start with the ‘#’ character and continue to the end of the
|
Comments start with the ‘#’ character and continue to the end of the
|
||||||
|
@ -340,7 +340,7 @@ constructor (see <xref linkend="sleigh_display_section"/>) where the ‘#’ cha
|
||||||
interpreted as something that should be printed in disassembly.
|
interpreted as something that should be printed in disassembly.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_identifiers">
|
||||||
<title>Identifiers</title>
|
<title>Identifiers</title>
|
||||||
<para>
|
<para>
|
||||||
Identifiers are made up of letters a-z, capitals A-Z, digits 0-9 and
|
Identifiers are made up of letters a-z, capitals A-Z, digits 0-9 and
|
||||||
|
@ -348,7 +348,7 @@ the characters ‘.’ and ‘_’. An identifier can use these characters in
|
||||||
any order and for any length, but it must not start with a digit.
|
any order and for any length, but it must not start with a digit.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_strings">
|
||||||
<title>Strings</title>
|
<title>Strings</title>
|
||||||
<para>
|
<para>
|
||||||
String literals can be used, when specifying names and when specifying
|
String literals can be used, when specifying names and when specifying
|
||||||
|
@ -358,7 +358,7 @@ character ‘”’ and all characters in between lose their special
|
||||||
meaning.
|
meaning.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_integers">
|
||||||
<title>Integers</title>
|
<title>Integers</title>
|
||||||
<para>
|
<para>
|
||||||
Integers are specified either in a decimal format or in a standard
|
Integers are specified either in a decimal format or in a standard
|
||||||
|
@ -383,7 +383,7 @@ be thought of as having arbitrary precision. Currently, SLEIGH stores
|
||||||
integers internally with 64 bits of precision.
|
integers internally with 64 bits of precision.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_white_space">
|
||||||
<title>White Space</title>
|
<title>White Space</title>
|
||||||
<para>
|
<para>
|
||||||
White space characters include space, tab, line-feed, vertical
|
White space characters include space, tab, line-feed, vertical
|
||||||
|
@ -419,7 +419,7 @@ included files can have their
|
||||||
own <emphasis role="bold">@include</emphasis> directives.
|
own <emphasis role="bold">@include</emphasis> directives.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_preprocessor_macros">
|
||||||
<title>Preprocessor Macros</title>
|
<title>Preprocessor Macros</title>
|
||||||
<para>
|
<para>
|
||||||
SLEIGH allows simple (unparameterized) macro definitions and
|
SLEIGH allows simple (unparameterized) macro definitions and
|
||||||
|
@ -449,7 +449,7 @@ definition of a macro from that point on in the file.
|
||||||
</informalexample>
|
</informalexample>
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_conditional_compilation">
|
||||||
<title>Conditional Compilation</title>
|
<title>Conditional Compilation</title>
|
||||||
<para>
|
<para>
|
||||||
SLEIGH supports several directives that allow conditional inclusion of
|
SLEIGH supports several directives that allow conditional inclusion of
|
||||||
|
@ -466,7 +466,7 @@ second <emphasis role="bold">@if...</emphasis> <emphasis role="bold">@endif</emp
|
||||||
pair can occur inside an initial <emphasis role="bold">@if</emphasis>
|
pair can occur inside an initial <emphasis role="bold">@if</emphasis>
|
||||||
and <emphasis role="bold">@endif</emphasis>.
|
and <emphasis role="bold">@endif</emphasis>.
|
||||||
</para>
|
</para>
|
||||||
<sect3>
|
<sect3 id="sleigh_ifdef">
|
||||||
<title>@ifdef and @ifndef</title>
|
<title>@ifdef and @ifndef</title>
|
||||||
<para>
|
<para>
|
||||||
The <emphasis role="bold">@ifdef</emphasis> directive is followed by a
|
The <emphasis role="bold">@ifdef</emphasis> directive is followed by a
|
||||||
|
@ -491,7 +491,7 @@ an <emphasis role="bold">@if</emphasis>
|
||||||
or <emphasis role="bold">@elif</emphasis> directive (See below).
|
or <emphasis role="bold">@elif</emphasis> directive (See below).
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_if">
|
||||||
<title>@if</title>
|
<title>@if</title>
|
||||||
<para>
|
<para>
|
||||||
The <emphasis role="bold">@if</emphasis> directive is followed by a
|
The <emphasis role="bold">@if</emphasis> directive is followed by a
|
||||||
|
@ -519,7 +519,7 @@ is defined.
|
||||||
</informalexample>
|
</informalexample>
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_else">
|
||||||
<title>@else and @elif</title>
|
<title>@else and @elif</title>
|
||||||
<para>
|
<para>
|
||||||
An <emphasis role="bold">@else</emphasis> directive splits the lines
|
An <emphasis role="bold">@else</emphasis> directive splits the lines
|
||||||
|
@ -583,7 +583,7 @@ endianess when labeling instruction fields and when defining overlapping registe
|
||||||
otherwise the specification language hides endianess issues.
|
otherwise the specification language hides endianess issues.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_alignment_definition">
|
||||||
<title>Alignment Definition</title>
|
<title>Alignment Definition</title>
|
||||||
<para>
|
<para>
|
||||||
An alignment definition looks like
|
An alignment definition looks like
|
||||||
|
@ -599,7 +599,7 @@ the address against this value and can opt to flag an unaligned
|
||||||
instruction as an error.
|
instruction as an error.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_space_definitions">
|
||||||
<title>Space Definitions</title>
|
<title>Space Definitions</title>
|
||||||
<para>
|
<para>
|
||||||
The definition of an address space looks like
|
The definition of an address space looks like
|
||||||
|
@ -752,7 +752,7 @@ define register offset=0 size=1
|
||||||
</informalexample>
|
</informalexample>
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_bitrange_registers">
|
||||||
<title>Bit Range Registers</title>
|
<title>Bit Range Registers</title>
|
||||||
<para>
|
<para>
|
||||||
Many processors define registers that either consist of a single bit
|
Many processors define registers that either consist of a single bit
|
||||||
|
@ -822,7 +822,7 @@ the <emphasis role="bold">define bitrange</emphasis> statement can be
|
||||||
used as an alternate syntax for defining overlapping registers.
|
used as an alternate syntax for defining overlapping registers.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_userdefined_operations">
|
||||||
<title>User-Defined Operations</title>
|
<title>User-Defined Operations</title>
|
||||||
<para>
|
<para>
|
||||||
The specification designer can define new p-code operations using
|
The specification designer can define new p-code operations using
|
||||||
|
@ -933,7 +933,7 @@ can be used in the definition of other <emphasis>table</emphasis>
|
||||||
symbols until the root symbol is fully described. The root symbol has
|
symbols until the root symbol is fully described. The root symbol has
|
||||||
the predefined identifier <emphasis>instruction</emphasis>.
|
the predefined identifier <emphasis>instruction</emphasis>.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2 id="sleigh_notes_namespaces">
|
||||||
<title>Notes on Namespaces</title>
|
<title>Notes on Namespaces</title>
|
||||||
<para>
|
<para>
|
||||||
Almost all identifiers live in the same global "scope". The global scope includes
|
Almost all identifiers live in the same global "scope". The global scope includes
|
||||||
|
@ -1006,6 +1006,10 @@ We list all of the symbols that are predefined by SLEIGH.
|
||||||
<td><code>inst_next</code></td>
|
<td><code>inst_next</code></td>
|
||||||
<td>Offset of the address of the next instruction.</td>
|
<td>Offset of the address of the next instruction.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>inst_next2</code></td>
|
||||||
|
<td>Offset of the address of the instruction after the next instruction.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>epsilon</code></td>
|
<td><code>epsilon</code></td>
|
||||||
<td>A special identifier indicating an empty bit pattern.</td>
|
<td>A special identifier indicating an empty bit pattern.</td>
|
||||||
|
@ -1019,7 +1023,8 @@ and <emphasis>inst_next</emphasis>. These are family symbols which map
|
||||||
in the context of particular instruction to the integer offset of
|
in the context of particular instruction to the integer offset of
|
||||||
either the address of the instruction or the address of the next
|
either the address of the instruction or the address of the next
|
||||||
instruction respectively. These are used in any relative branching
|
instruction respectively. These are used in any relative branching
|
||||||
situation. The other symbols are rarely
|
situation. The <emphasis>inst_next2</emphasis> is intended for conditional
|
||||||
|
skip instruction situations. The remaining symbols are rarely
|
||||||
used. The <emphasis>const</emphasis> and <emphasis>unique</emphasis>
|
used. The <emphasis>const</emphasis> and <emphasis>unique</emphasis>
|
||||||
identifiers are address spaces. The <emphasis>epsilon</emphasis>
|
identifiers are address spaces. The <emphasis>epsilon</emphasis>
|
||||||
identifier is inherited from SLED and is a specific symbol equivalent
|
identifier is inherited from SLED and is a specific symbol equivalent
|
||||||
|
@ -1088,7 +1093,7 @@ manner of repeats and overlaps in the fields so long as they all have
|
||||||
different names.
|
different names.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_fields_family">
|
||||||
<title>Fields as Family Symbols</title>
|
<title>Fields as Family Symbols</title>
|
||||||
<para>
|
<para>
|
||||||
Fields are the most basic form of family symbol; they define a natural
|
Fields are the most basic form of family symbol; they define a natural
|
||||||
|
@ -1112,7 +1117,7 @@ representation. The default is hexadecimal. [Currently
|
||||||
the <emphasis role="bold">dec</emphasis> attribute is not supported]
|
the <emphasis role="bold">dec</emphasis> attribute is not supported]
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_alternate_meanings">
|
||||||
<title>Attaching Alternate Meanings to Fields</title>
|
<title>Attaching Alternate Meanings to Fields</title>
|
||||||
<para>
|
<para>
|
||||||
The default interpretation of a field is probably the most natural but
|
The default interpretation of a field is probably the most natural but
|
||||||
|
@ -1122,7 +1127,7 @@ is used to alter either the display or semantic meaning of fields into
|
||||||
the most common (and basic) interpretations. More complex
|
the most common (and basic) interpretations. More complex
|
||||||
interpretations must be built up out of tables.
|
interpretations must be built up out of tables.
|
||||||
</para>
|
</para>
|
||||||
<sect3>
|
<sect3 id="sleigh_attaching_registers">
|
||||||
<title>Attaching Registers</title>
|
<title>Attaching Registers</title>
|
||||||
<para>
|
<para>
|
||||||
Probably <emphasis>the</emphasis> most common processor interpretation
|
Probably <emphasis>the</emphasis> most common processor interpretation
|
||||||
|
@ -1160,7 +1165,7 @@ display meaning. Instead this encoding is flagged as an invalid form
|
||||||
of the instruction.
|
of the instruction.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_attaching_integers">
|
||||||
<title>Attaching Other Integers</title>
|
<title>Attaching Other Integers</title>
|
||||||
<para>
|
<para>
|
||||||
Sometimes a processor interprets a field as an integer but not the
|
Sometimes a processor interprets a field as an integer but not the
|
||||||
|
@ -1181,7 +1186,7 @@ the <emphasis>fieldlist</emphasis>. [Currently SLEIGH does not support
|
||||||
unspecified positions in the list using a ‘_’]
|
unspecified positions in the list using a ‘_’]
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_attaching_names">
|
||||||
<title>Attaching Names</title>
|
<title>Attaching Names</title>
|
||||||
<para>
|
<para>
|
||||||
It is possible to just modify the display characteristics of a field
|
It is possible to just modify the display characteristics of a field
|
||||||
|
@ -1293,7 +1298,7 @@ associated with it. Most of this chapter is devoted to describing how
|
||||||
to define a single constructor. The issues involved in combining
|
to define a single constructor. The issues involved in combining
|
||||||
multiple constructors into a single table are addressed in <xref linkend="sleigh_tables"/>.
|
multiple constructors into a single table are addressed in <xref linkend="sleigh_tables"/>.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2 id="sleigh_sections_constructor">
|
||||||
<title>The Five Sections of a Constructor</title>
|
<title>The Five Sections of a Constructor</title>
|
||||||
<para>
|
<para>
|
||||||
A single complex statement in the specification file describes a
|
A single complex statement in the specification file describes a
|
||||||
|
@ -1324,7 +1329,7 @@ the syntax typically fits on a single line. We describe each section
|
||||||
in turn.
|
in turn.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_table_header">
|
||||||
<title>The Table Header</title>
|
<title>The Table Header</title>
|
||||||
<para>
|
<para>
|
||||||
Every constructor must be part of a table, which is the element with
|
Every constructor must be part of a table, which is the element with
|
||||||
|
@ -1459,7 +1464,7 @@ assure uniqueness, but for reverse engineering applications there is
|
||||||
no such requirement.
|
no such requirement.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_caret">
|
||||||
<title>The '^' character</title>
|
<title>The '^' character</title>
|
||||||
<para>
|
<para>
|
||||||
The ‘^’ character in the display section is used to separate
|
The ‘^’ character in the display section is used to separate
|
||||||
|
@ -1505,7 +1510,7 @@ constructor’s <emphasis>pattern</emphasis>, the subset of possible
|
||||||
instruction encodings that the designer wants
|
instruction encodings that the designer wants
|
||||||
to <emphasis>match</emphasis> the constructor being defined.
|
to <emphasis>match</emphasis> the constructor being defined.
|
||||||
</para>
|
</para>
|
||||||
<sect3>
|
<sect3 id="sleigh_constraints">
|
||||||
<title>Constraints</title>
|
<title>Constraints</title>
|
||||||
<para>
|
<para>
|
||||||
The patterns required for processor specifications can almost always
|
The patterns required for processor specifications can almost always
|
||||||
|
@ -1562,7 +1567,7 @@ all possible. The <emphasis>logical or</emphasis> operator usually
|
||||||
requires two or more mask/value style checks to correctly implement.
|
requires two or more mask/value style checks to correctly implement.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_defining_operands">
|
||||||
<title>Defining Operands and Invoking Subtables</title>
|
<title>Defining Operands and Invoking Subtables</title>
|
||||||
<para>
|
<para>
|
||||||
The principle way of defining a constructor operand, left undefined
|
The principle way of defining a constructor operand, left undefined
|
||||||
|
@ -1622,7 +1627,7 @@ grammar’s start symbol. So this link from local to global is simply a
|
||||||
statement of the grouping of old symbols into the new constructor.
|
statement of the grouping of old symbols into the new constructor.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_variable_length">
|
||||||
<title>Variable Length Instructions</title>
|
<title>Variable Length Instructions</title>
|
||||||
<para>
|
<para>
|
||||||
There are some additional complexities to designing a specification
|
There are some additional complexities to designing a specification
|
||||||
|
@ -1644,7 +1649,7 @@ final length of the instruction. SLEIGH has two operators that are
|
||||||
specific to variable length instruction sets and that give the
|
specific to variable length instruction sets and that give the
|
||||||
designer control over how tokens fit together.
|
designer control over how tokens fit together.
|
||||||
</para>
|
</para>
|
||||||
<sect4>
|
<sect4 id="sleigh_semicolon">
|
||||||
<title>The ';' Operator</title>
|
<title>The ';' Operator</title>
|
||||||
<para>
|
<para>
|
||||||
The most important operator for patterns defining variable length
|
The most important operator for patterns defining variable length
|
||||||
|
@ -1705,7 +1710,7 @@ order. Also these operators have higher precedence than the ‘;’
|
||||||
operator, so parentheses may be necessary to get the intended meaning.
|
operator, so parentheses may be necessary to get the intended meaning.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_ellipsis">
|
||||||
<title>The '...' Operator</title>
|
<title>The '...' Operator</title>
|
||||||
<para>
|
<para>
|
||||||
The ellipsis operator ‘...’ is used to satisfy the token matching
|
The ellipsis operator ‘...’ is used to satisfy the token matching
|
||||||
|
@ -1779,7 +1784,7 @@ you need to break up the parsing of an instruction along lines that
|
||||||
don’t quite match the assembly.
|
don’t quite match the assembly.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_empty_patterns">
|
||||||
<title>Empty Patterns</title>
|
<title>Empty Patterns</title>
|
||||||
<para>
|
<para>
|
||||||
Occasionally there is a need for an empty pattern when building
|
Occasionally there is a need for an empty pattern when building
|
||||||
|
@ -1788,7 +1793,7 @@ symbol <emphasis>epsilon</emphasis> which has been traditionally used
|
||||||
to indicate an empty pattern.
|
to indicate an empty pattern.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_advanced_constraints">
|
||||||
<title>Advanced Constraints</title>
|
<title>Advanced Constraints</title>
|
||||||
<para>
|
<para>
|
||||||
A constraint does not have to be of the form “field = constant”,
|
A constraint does not have to be of the form “field = constant”,
|
||||||
|
@ -2152,7 +2157,7 @@ operation, <emphasis>INT_ADD</emphasis>, where the input varnodes
|
||||||
are <emphasis>r1</emphasis> and <emphasis>r2</emphasis> and the output
|
are <emphasis>r1</emphasis> and <emphasis>r2</emphasis> and the output
|
||||||
varnode is <emphasis>r1</emphasis>.
|
varnode is <emphasis>r1</emphasis>.
|
||||||
</para>
|
</para>
|
||||||
<sect3>
|
<sect3 id="sleigh_expressions">
|
||||||
<title>Expressions</title>
|
<title>Expressions</title>
|
||||||
<para>
|
<para>
|
||||||
Expressions are built out of symbols and the binary and unary
|
Expressions are built out of symbols and the binary and unary
|
||||||
|
@ -2166,7 +2171,7 @@ have a precedence, which is used by the SLEIGH compiler to determine
|
||||||
the ordering of the final p-code operations. Parentheses can be used
|
the ordering of the final p-code operations. Parentheses can be used
|
||||||
within expressions to affect this order.
|
within expressions to affect this order.
|
||||||
</para>
|
</para>
|
||||||
<sect4>
|
<sect4 id="sleigh_arithmetic_logical">
|
||||||
<title>Arithmetic, Logical and Boolean Operators</title>
|
<title>Arithmetic, Logical and Boolean Operators</title>
|
||||||
<para>
|
<para>
|
||||||
For the most part these operators should be familiar to software
|
For the most part these operators should be familiar to software
|
||||||
|
@ -2227,7 +2232,7 @@ address if the <emphasis role="bold">wordsize</emphasis> attribute is
|
||||||
set to something other than one.
|
set to something other than one.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_extension">
|
||||||
<title>Extension</title>
|
<title>Extension</title>
|
||||||
<para>
|
<para>
|
||||||
Most processors have instructions that extend small values into big
|
Most processors have instructions that extend small values into big
|
||||||
|
@ -2248,7 +2253,7 @@ the <emphasis>INT_SEXT</emphasis> operation is invoked with
|
||||||
the <emphasis role="bold">sext</emphasis> operator.
|
the <emphasis role="bold">sext</emphasis> operator.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_truncation">
|
||||||
<title>Truncation</title>
|
<title>Truncation</title>
|
||||||
<para>
|
<para>
|
||||||
There are two forms of syntax indicating a truncation of the input
|
There are two forms of syntax indicating a truncation of the input
|
||||||
|
@ -2372,7 +2377,7 @@ the offset portion of the address, and to copy the desired value, the
|
||||||
‘*’ operator must have a <emphasis>register</emphasis> space override.
|
‘*’ operator must have a <emphasis>register</emphasis> space override.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_managed_code">
|
||||||
<title>Managed Code Operations</title>
|
<title>Managed Code Operations</title>
|
||||||
<para>
|
<para>
|
||||||
SLEIGH provides basic support for instructions where encoding and context
|
SLEIGH provides basic support for instructions where encoding and context
|
||||||
|
@ -2432,7 +2437,7 @@ define pcodeop arctan;
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_statements">
|
||||||
<title>Statements</title>
|
<title>Statements</title>
|
||||||
<para>
|
<para>
|
||||||
We describe the types of semantic statements that are allowed in SLEIGH.
|
We describe the types of semantic statements that are allowed in SLEIGH.
|
||||||
|
@ -2501,7 +2506,7 @@ Use of the <emphasis role="bold">local</emphasis> keyword is preferred
|
||||||
and may be enforced in future compiler versions.
|
and may be enforced in future compiler versions.
|
||||||
</para></warning>
|
</para></warning>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_storage_statements">
|
||||||
<title>Storage Statements</title>
|
<title>Storage Statements</title>
|
||||||
<para>
|
<para>
|
||||||
SLEIGH supports fairly standard <emphasis>storage statement</emphasis>
|
SLEIGH supports fairly standard <emphasis>storage statement</emphasis>
|
||||||
|
@ -2531,7 +2536,7 @@ not a byte address if the <emphasis role="bold">wordsize</emphasis>
|
||||||
attribute is set to something other than one.
|
attribute is set to something other than one.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_exports">
|
||||||
<title>Exports</title>
|
<title>Exports</title>
|
||||||
<para>
|
<para>
|
||||||
The semantic section doesn’t just specify how to generate p-code for a
|
The semantic section doesn’t just specify how to generate p-code for a
|
||||||
|
@ -2582,7 +2587,7 @@ would in a normal expression (see
|
||||||
varnode being modified to be exported as an integer constant.
|
varnode being modified to be exported as an integer constant.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_dynamic_references">
|
||||||
<title>Dynamic References</title>
|
<title>Dynamic References</title>
|
||||||
<para>
|
<para>
|
||||||
The only other operator allowed as part of
|
The only other operator allowed as part of
|
||||||
|
@ -2640,7 +2645,7 @@ addressing mode implementations from instruction semantics at higher
|
||||||
levels.
|
levels.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_branching_statements">
|
||||||
<title>Branching Statements</title>
|
<title>Branching Statements</title>
|
||||||
<para>
|
<para>
|
||||||
This section discusses statements that generate p-code branching
|
This section discusses statements that generate p-code branching
|
||||||
|
@ -2868,6 +2873,26 @@ the <emphasis>BRANCH</emphasis>, <emphasis>CBRANCH</emphasis>,
|
||||||
or <emphasis>CALL</emphasis> operation.
|
or <emphasis>CALL</emphasis> operation.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
|
<sect4 id="sleigh_skip_instruction_branching">
|
||||||
|
<title>Skip Instruction Branching</title>
|
||||||
|
<para>
|
||||||
|
Many processors have a conditional-skip-instruction which must branch over the next instruction
|
||||||
|
based upon some condition. The <emphasis>inst_next2</emphasis> symbol has been provided for
|
||||||
|
this purpose.
|
||||||
|
<informalexample>
|
||||||
|
<programlisting>
|
||||||
|
:skip.eq is opcode=10 {
|
||||||
|
if (zeroflag!=0) goto inst_next2;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</informalexample>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In the example above, the branch address will be determined by adding the parsed-length of the next
|
||||||
|
instruction to the value of <emphasis>inst_next</emphasis> causing a branch over the next
|
||||||
|
instruction when the condition is satisfied.
|
||||||
|
</para>
|
||||||
|
</sect4>
|
||||||
<sect4 id="sleigh_bitrange_assign">
|
<sect4 id="sleigh_bitrange_assign">
|
||||||
<title>Bit Range Assignments</title>
|
<title>Bit Range Assignments</title>
|
||||||
<para>
|
<para>
|
||||||
|
@ -2991,7 +3016,7 @@ each followed by a variation which corrects the error.
|
||||||
</informalexample>
|
</informalexample>
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_unimplemented_semantics">
|
||||||
<title>Unimplemented Semantics</title>
|
<title>Unimplemented Semantics</title>
|
||||||
<para>
|
<para>
|
||||||
The semantic section must be present for every constructor in the
|
The semantic section must be present for every constructor in the
|
||||||
|
@ -3148,7 +3173,7 @@ checking, can be used for various tricks in the specification but
|
||||||
should generally be avoided.
|
should generally be avoided.
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
<sect3>
|
<sect3 id="sleigh_specific_symbol_trees">
|
||||||
<title>Specific Symbol Trees</title>
|
<title>Specific Symbol Trees</title>
|
||||||
<para>
|
<para>
|
||||||
When the SLEIGH parser analyzes an instruction, it starts with the
|
When the SLEIGH parser analyzes an instruction, it starts with the
|
||||||
|
@ -3234,7 +3259,7 @@ determined by the matching constructor for
|
||||||
the <emphasis>op2</emphasis> table. SLEIGH generates the disassembly
|
the <emphasis>op2</emphasis> table. SLEIGH generates the disassembly
|
||||||
and p-code for these encodings by walking the trees.
|
and p-code for these encodings by walking the trees.
|
||||||
</para>
|
</para>
|
||||||
<sect4>
|
<sect4 id="sleigh_disassembly_trees">
|
||||||
<title>Disassembly Trees</title>
|
<title>Disassembly Trees</title>
|
||||||
<para>
|
<para>
|
||||||
If the nodes of each tree are replaced with the display information of
|
If the nodes of each tree are replaced with the display information of
|
||||||
|
@ -3260,7 +3285,7 @@ walking the tree, SLEIGH obtains the final illustrated assembly
|
||||||
statements corresponding to the original instruction encodings.
|
statements corresponding to the original instruction encodings.
|
||||||
</para>
|
</para>
|
||||||
</sect4>
|
</sect4>
|
||||||
<sect4>
|
<sect4 id="sleigh_pcode_trees">
|
||||||
<title>P-code Trees</title>
|
<title>P-code Trees</title>
|
||||||
<para>
|
<para>
|
||||||
A similar procedure produces the resulting p-code translation of the
|
A similar procedure produces the resulting p-code translation of the
|
||||||
|
@ -3341,7 +3366,7 @@ calls to other macros. A <emphasis role="bold">build</emphasis>
|
||||||
directive however should not be used in a macro.
|
directive however should not be used in a macro.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_build_directives">
|
||||||
<title>Build Directives</title>
|
<title>Build Directives</title>
|
||||||
<para>
|
<para>
|
||||||
Because the nodes of a specific symbol tree are traversed in a
|
Because the nodes of a specific symbol tree are traversed in a
|
||||||
|
@ -3395,7 +3420,7 @@ a <emphasis role="bold">build</emphasis> directive, followed by the
|
||||||
normal action of the instruction.
|
normal action of the instruction.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2>
|
<sect2 id="sleigh_delayslot_directives">
|
||||||
<title>Delay Slot Directives</title>
|
<title>Delay Slot Directives</title>
|
||||||
<para>
|
<para>
|
||||||
For processors with a pipe-lined architecture, multiple instructions
|
For processors with a pipe-lined architecture, multiple instructions
|
||||||
|
@ -3439,7 +3464,8 @@ by the condition.
|
||||||
<para>
|
<para>
|
||||||
Because the <emphasis role="bold">delayslot</emphasis> directive
|
Because the <emphasis role="bold">delayslot</emphasis> directive
|
||||||
combines two or more instructions into one, the meaning of the
|
combines two or more instructions into one, the meaning of the
|
||||||
symbol <emphasis>inst_next</emphasis> becomes ambiguous. It is not
|
symbols <emphasis>inst_next</emphasis> and <emphasis>inst_next2</emphasis>
|
||||||
|
become ambiguous. It is not
|
||||||
clear anymore what exactly the “next instruction” is. SLEIGH uses the
|
clear anymore what exactly the “next instruction” is. SLEIGH uses the
|
||||||
following conventions for interpreting
|
following conventions for interpreting
|
||||||
an <emphasis>inst_next</emphasis> symbol. If it is used in the
|
an <emphasis>inst_next</emphasis> symbol. If it is used in the
|
||||||
|
@ -3447,7 +3473,12 @@ semantic section, the symbol refers to the address of the instruction
|
||||||
after any instructions in the delay slot. However, if it is used in a
|
after any instructions in the delay slot. However, if it is used in a
|
||||||
disassembly action, the <emphasis>inst_next</emphasis> symbol refers
|
disassembly action, the <emphasis>inst_next</emphasis> symbol refers
|
||||||
to the address of the instruction immediately after the first
|
to the address of the instruction immediately after the first
|
||||||
instruction, even if there is a delay slot.
|
instruction, even if there is a delay slot. The use of the
|
||||||
|
<emphasis>inst_next2</emphasis> symbol may be inappropriate in conjunction
|
||||||
|
with <emphasis role="bold">delayslot</emphasis> use. While its use of the
|
||||||
|
next instruction address is identified by <emphasis>inst_next</emphasis>,
|
||||||
|
the length of the next instruction ignores any delay slots it may have
|
||||||
|
when computing the value of <emphasis>inst_next2</emphasis>.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
@ -3509,7 +3540,7 @@ just another field to use in our bit patterns. It gives us the extra
|
||||||
information we need to distinguish between different instructions
|
information we need to distinguish between different instructions
|
||||||
whose encodings are otherwise the same.
|
whose encodings are otherwise the same.
|
||||||
</para>
|
</para>
|
||||||
<sect2>
|
<sect2 id="sleigh_context_basic">
|
||||||
<title>Basic Use of Context Variables</title>
|
<title>Basic Use of Context Variables</title>
|
||||||
<para>
|
<para>
|
||||||
Suppose a processor supports the use of two different sets of
|
Suppose a processor supports the use of two different sets of
|
||||||
|
@ -3525,6 +3556,7 @@ define space ram type=ram_space size=4 default;
|
||||||
define space register type=register_space size=4;
|
define space register type=register_space size=4;
|
||||||
define register offset=0 size=4 [ r0 r1 r2 r3 r4 r5 r6 r7 ];
|
define register offset=0 size=4 [ r0 r1 r2 r3 r4 r5 r6 r7 ];
|
||||||
define register offset=0x100 size=4 [ s0 s1 s2 s3 s4 s5 s6 s7 ];
|
define register offset=0x100 size=4 [ s0 s1 s2 s3 s4 s5 s6 s7 ];
|
||||||
|
define register offset=0x200 size=4 [ statusreg ]; # define context bits (if defined, size must be multiple of 4-bytes)
|
||||||
|
|
||||||
define token instr(16)
|
define token instr(16)
|
||||||
op=(10,15) rreg1=(7,9) sreg1=(7,9) imm=(0,6)
|
op=(10,15) rreg1=(7,9) sreg1=(7,9) imm=(0,6)
|
||||||
|
|
|
@ -349,9 +349,10 @@ specific_symbol[String purpose] returns [SpecificSymbol symbol]
|
||||||
: ^(OP_IDENTIFIER s=.) {
|
: ^(OP_IDENTIFIER s=.) {
|
||||||
SleighSymbol sym = pcode.findSymbol($s.getText());
|
SleighSymbol sym = pcode.findSymbol($s.getText());
|
||||||
if (sym == null) {
|
if (sym == null) {
|
||||||
unknownSymbolError($s.getText(), find($s), "start, end, operand, epsilon, or varnode", purpose);
|
unknownSymbolError($s.getText(), find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
|
||||||
} else if(sym.getType() != symbol_type.start_symbol
|
} else if(sym.getType() != symbol_type.start_symbol
|
||||||
&& sym.getType() != symbol_type.end_symbol
|
&& sym.getType() != symbol_type.end_symbol
|
||||||
|
&& sym.getType() != symbol_type.next2_symbol
|
||||||
&& sym.getType() != symbol_type.operand_symbol
|
&& sym.getType() != symbol_type.operand_symbol
|
||||||
&& sym.getType() != symbol_type.epsilon_symbol
|
&& sym.getType() != symbol_type.epsilon_symbol
|
||||||
&& sym.getType() != symbol_type.varnode_symbol) {
|
&& sym.getType() != symbol_type.varnode_symbol) {
|
||||||
|
@ -839,7 +840,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
|
||||||
: ^(OP_IDENTIFIER s=.) {
|
: ^(OP_IDENTIFIER s=.) {
|
||||||
SleighSymbol sym = sc.findSymbol($s.getText());
|
SleighSymbol sym = sc.findSymbol($s.getText());
|
||||||
if (sym == null) {
|
if (sym == null) {
|
||||||
unknownSymbolError($s.getText(), find($s), "start, end, operand, epsilon, or varnode", purpose);
|
unknownSymbolError($s.getText(), find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
|
||||||
} else if(sym.getType() == symbol_type.operand_symbol) {
|
} else if(sym.getType() == symbol_type.operand_symbol) {
|
||||||
OperandSymbol os = (OperandSymbol) sym;
|
OperandSymbol os = (OperandSymbol) sym;
|
||||||
if (os.getDefiningSymbol() != null && os.getDefiningSymbol().getType() == symbol_type.subtable_symbol) {
|
if (os.getDefiningSymbol() != null && os.getDefiningSymbol().getType() == symbol_type.subtable_symbol) {
|
||||||
|
@ -848,6 +849,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
|
||||||
$expr = os.getPatternExpression();
|
$expr = os.getPatternExpression();
|
||||||
} else if(sym.getType() == symbol_type.start_symbol
|
} else if(sym.getType() == symbol_type.start_symbol
|
||||||
|| sym.getType() == symbol_type.end_symbol
|
|| sym.getType() == symbol_type.end_symbol
|
||||||
|
|| sym.getType() == symbol_type.next2_symbol
|
||||||
|| sym.getType() == symbol_type.epsilon_symbol
|
|| sym.getType() == symbol_type.epsilon_symbol
|
||||||
|| sym.getType() == symbol_type.varnode_symbol) {
|
|| sym.getType() == symbol_type.varnode_symbol) {
|
||||||
SpecificSymbol ss = (SpecificSymbol) sym;
|
SpecificSymbol ss = (SpecificSymbol) sym;
|
||||||
|
@ -864,7 +866,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
|
||||||
reportError(find($s), "Global symbol '" + sym.getName() + "' is not allowed in action expression");
|
reportError(find($s), "Global symbol '" + sym.getName() + "' is not allowed in action expression");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wrongSymbolTypeError(sym, find($s), "start, end, operand, epsilon, or varnode", purpose);
|
wrongSymbolTypeError(sym, find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| t=OP_WILDCARD {
|
| t=OP_WILDCARD {
|
||||||
|
@ -877,9 +879,10 @@ pattern_symbol2[String purpose] returns [PatternExpression expr]
|
||||||
: ^(OP_IDENTIFIER s=.) {
|
: ^(OP_IDENTIFIER s=.) {
|
||||||
SleighSymbol sym = sc.findSymbol($s.getText());
|
SleighSymbol sym = sc.findSymbol($s.getText());
|
||||||
if (sym == null) {
|
if (sym == null) {
|
||||||
unknownSymbolError($s.getText(), find($s), "start, end, operand, epsilon, or varnode", purpose);
|
unknownSymbolError($s.getText(), find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
|
||||||
} else if(sym.getType() == symbol_type.start_symbol
|
} else if(sym.getType() == symbol_type.start_symbol
|
||||||
|| sym.getType() == symbol_type.end_symbol
|
|| sym.getType() == symbol_type.end_symbol
|
||||||
|
|| sym.getType() == symbol_type.next2_symbol
|
||||||
|| sym.getType() == symbol_type.operand_symbol
|
|| sym.getType() == symbol_type.operand_symbol
|
||||||
|| sym.getType() == symbol_type.epsilon_symbol
|
|| sym.getType() == symbol_type.epsilon_symbol
|
||||||
|| sym.getType() == symbol_type.varnode_symbol) {
|
|| sym.getType() == symbol_type.varnode_symbol) {
|
||||||
|
@ -893,7 +896,7 @@ pattern_symbol2[String purpose] returns [PatternExpression expr]
|
||||||
FamilySymbol z = (FamilySymbol) sym;
|
FamilySymbol z = (FamilySymbol) sym;
|
||||||
$expr = z.getPatternValue();
|
$expr = z.getPatternValue();
|
||||||
} else {
|
} else {
|
||||||
wrongSymbolTypeError(sym, find($s), "start, end, operand, epsilon, or varnode", purpose);
|
wrongSymbolTypeError(sym, find($s), "start, end, next2, operand, epsilon, or varnode", purpose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| t=OP_WILDCARD {
|
| t=OP_WILDCARD {
|
||||||
|
@ -922,7 +925,7 @@ cstatement[VectorSTL<ContextChange> r]
|
||||||
} else if(sym.getType() == symbol_type.context_symbol) {
|
} else if(sym.getType() == symbol_type.context_symbol) {
|
||||||
ContextSymbol t = (ContextSymbol) sym;
|
ContextSymbol t = (ContextSymbol) sym;
|
||||||
if (!sc.contextMod(r, t, e)) {
|
if (!sc.contextMod(r, t, e)) {
|
||||||
reportError(find($id), "Cannot use 'inst_next' to set context variable: '" + t.getName() + "'");
|
reportError(find($id), "Cannot use 'inst_next' or 'inst_next2' to set context variable: '" + t.getName() + "'");
|
||||||
}
|
}
|
||||||
} else if(sym.getType() == symbol_type.operand_symbol) {
|
} else if(sym.getType() == symbol_type.operand_symbol) {
|
||||||
OperandSymbol t = (OperandSymbol) sym;
|
OperandSymbol t = (OperandSymbol) sym;
|
||||||
|
@ -950,6 +953,7 @@ cstatement[VectorSTL<ContextChange> r]
|
||||||
|| sym.getType() == symbol_type.varnodelist_symbol
|
|| sym.getType() == symbol_type.varnodelist_symbol
|
||||||
|| sym.getType() == symbol_type.start_symbol
|
|| sym.getType() == symbol_type.start_symbol
|
||||||
|| sym.getType() == symbol_type.end_symbol
|
|| sym.getType() == symbol_type.end_symbol
|
||||||
|
|| sym.getType() == symbol_type.next2_symbol
|
||||||
|| sym.getType() == symbol_type.operand_symbol
|
|| sym.getType() == symbol_type.operand_symbol
|
||||||
|| sym.getType() == symbol_type.epsilon_symbol
|
|| sym.getType() == symbol_type.epsilon_symbol
|
||||||
|| sym.getType() == symbol_type.varnode_symbol) {
|
|| sym.getType() == symbol_type.varnode_symbol) {
|
||||||
|
@ -1176,10 +1180,11 @@ assignment returns [VectorSTL<OpTpl> value]
|
||||||
$value = pcode.newOutput(find(id), false, e, $id.getText());
|
$value = pcode.newOutput(find(id), false, e, $id.getText());
|
||||||
} else if(sym.getType() != symbol_type.start_symbol
|
} else if(sym.getType() != symbol_type.start_symbol
|
||||||
&& sym.getType() != symbol_type.end_symbol
|
&& sym.getType() != symbol_type.end_symbol
|
||||||
|
&& sym.getType() != symbol_type.next2_symbol
|
||||||
&& sym.getType() != symbol_type.operand_symbol
|
&& sym.getType() != symbol_type.operand_symbol
|
||||||
&& sym.getType() != symbol_type.epsilon_symbol
|
&& sym.getType() != symbol_type.epsilon_symbol
|
||||||
&& sym.getType() != symbol_type.varnode_symbol) {
|
&& sym.getType() != symbol_type.varnode_symbol) {
|
||||||
wrongSymbolTypeError(sym, find(id), "start, end, operand, epsilon, or varnode", "assignment");
|
wrongSymbolTypeError(sym, find(id), "start, end, next2, operand, epsilon, or varnode", "assignment");
|
||||||
} else {
|
} else {
|
||||||
VarnodeTpl v = ((SpecificSymbol) sym).getVarnode();
|
VarnodeTpl v = ((SpecificSymbol) sym).getVarnode();
|
||||||
e.setOutput(find(t), v);
|
e.setOutput(find(t), v);
|
||||||
|
@ -1309,7 +1314,9 @@ jump_symbol[String purpose] returns [VarnodeTpl value]
|
||||||
SleighSymbol sym = pcode.findSymbol($s.getText());
|
SleighSymbol sym = pcode.findSymbol($s.getText());
|
||||||
if (sym == null) {
|
if (sym == null) {
|
||||||
unknownSymbolError($s.getText(), find($s), "start, end, or operand", purpose);
|
unknownSymbolError($s.getText(), find($s), "start, end, or operand", purpose);
|
||||||
} else if(sym.getType() == symbol_type.start_symbol || sym.getType() == symbol_type.end_symbol) {
|
} else if (sym.getType() == symbol_type.start_symbol ||
|
||||||
|
sym.getType() == symbol_type.end_symbol ||
|
||||||
|
sym.getType() == symbol_type.next2_symbol) {
|
||||||
SpecificSymbol ss = (SpecificSymbol) sym;
|
SpecificSymbol ss = (SpecificSymbol) sym;
|
||||||
$value = new VarnodeTpl(find($s), new ConstTpl(ConstTpl.const_type.j_curspace),
|
$value = new VarnodeTpl(find($s), new ConstTpl(ConstTpl.const_type.j_curspace),
|
||||||
ss.getVarnode().getOffset(),
|
ss.getVarnode().getOffset(),
|
||||||
|
@ -1489,6 +1496,7 @@ expr_apply returns [Object value]
|
||||||
}
|
}
|
||||||
} else if(sym.getType() == symbol_type.start_symbol
|
} else if(sym.getType() == symbol_type.start_symbol
|
||||||
|| sym.getType() == symbol_type.end_symbol
|
|| sym.getType() == symbol_type.end_symbol
|
||||||
|
|| sym.getType() == symbol_type.next2_symbol
|
||||||
|| sym.getType() == symbol_type.operand_symbol
|
|| sym.getType() == symbol_type.operand_symbol
|
||||||
|| sym.getType() == symbol_type.epsilon_symbol
|
|| sym.getType() == symbol_type.epsilon_symbol
|
||||||
|| sym.getType() == symbol_type.varnode_symbol) {
|
|| sym.getType() == symbol_type.varnode_symbol) {
|
||||||
|
|
|
@ -573,6 +573,10 @@ public class SleighAssemblerBuilder implements AssemblerBuilder {
|
||||||
else if (sym instanceof EndSymbol) {
|
else if (sym instanceof EndSymbol) {
|
||||||
// Ignore. We handle inst_next in semantic processing
|
// Ignore. We handle inst_next in semantic processing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (sym instanceof Next2Symbol) {
|
||||||
|
// Ignore. We handle inst_next2 in semantic processing
|
||||||
|
}
|
||||||
else if (sym instanceof UseropSymbol) {
|
else if (sym instanceof UseropSymbol) {
|
||||||
// Ignore. We don't do pcode.
|
// Ignore. We don't do pcode.
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package ghidra.app.plugin.assembler.sleigh.expr;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.assembler.sleigh.sem.*;
|
||||||
|
import ghidra.app.plugin.processors.sleigh.expression.EndInstructionValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Solves" expressions of {@code inst_next2}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Works like the constant solver, but takes the value of {@code inst_next}, which is given by the
|
||||||
|
* assembly address and the resulting instruction length.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE:</b> This solver requires backfill, since the value of {@code inst_next2} is not known
|
||||||
|
* until possible prefixes have been considered.
|
||||||
|
*/
|
||||||
|
public class Next2InstructionValueSolver extends AbstractExpressionSolver<EndInstructionValue> {
|
||||||
|
|
||||||
|
public Next2InstructionValueSolver() {
|
||||||
|
super(EndInstructionValue.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssemblyResolution solve(EndInstructionValue iv, MaskedLong goal, Map<String, Long> vals,
|
||||||
|
AssemblyResolvedPatterns cur, Set<SolverHint> hints, String description) {
|
||||||
|
throw new AssertionError(
|
||||||
|
"INTERNAL: Should never be asked to solve for " + AssemblyTreeResolver.INST_NEXT2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MaskedLong getValue(EndInstructionValue iv, Map<String, Long> vals,
|
||||||
|
AssemblyResolvedPatterns cur) throws NeedsBackfillException {
|
||||||
|
Long instNext = vals.get(AssemblyTreeResolver.INST_NEXT2);
|
||||||
|
if (instNext == null) {
|
||||||
|
throw new NeedsBackfillException(AssemblyTreeResolver.INST_NEXT2);
|
||||||
|
}
|
||||||
|
return MaskedLong.fromLong(instNext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInstructionLength(EndInstructionValue iv) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MaskedLong valueForResolution(EndInstructionValue exp, Map<String, Long> vals,
|
||||||
|
AssemblyResolvedPatterns rc) {
|
||||||
|
Long instNext = vals.get(AssemblyTreeResolver.INST_NEXT2);
|
||||||
|
if (instNext == null) {
|
||||||
|
/**
|
||||||
|
* This method is used in forward state construction, so just leave unknown. This may
|
||||||
|
* cause unresolvable trees to get generated, but we can't know that until we try to
|
||||||
|
* resolve them.
|
||||||
|
*/
|
||||||
|
return MaskedLong.UNKS;
|
||||||
|
}
|
||||||
|
return MaskedLong.fromLong(instNext);
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,6 +53,7 @@ public class RecursiveDescentSolver {
|
||||||
new ContextFieldSolver().register(this);
|
new ContextFieldSolver().register(this);
|
||||||
new DivExpressionSolver().register(this);
|
new DivExpressionSolver().register(this);
|
||||||
new EndInstructionValueSolver().register(this);
|
new EndInstructionValueSolver().register(this);
|
||||||
|
new Next2InstructionValueSolver().register(this);
|
||||||
new LeftShiftExpressionSolver().register(this);
|
new LeftShiftExpressionSolver().register(this);
|
||||||
new MinusExpressionSolver().register(this);
|
new MinusExpressionSolver().register(this);
|
||||||
new MultExpressionSolver().register(this);
|
new MultExpressionSolver().register(this);
|
||||||
|
|
|
@ -78,6 +78,9 @@ public abstract class AbstractExpressionMatcher<T extends PatternExpression>
|
||||||
if (a instanceof EndInstructionValue) {
|
if (a instanceof EndInstructionValue) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (a instanceof Next2InstructionValue) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (a instanceof StartInstructionValue) {
|
if (a instanceof StartInstructionValue) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class AssemblyTreeResolver {
|
||||||
|
|
||||||
public static final String INST_START = "inst_start";
|
public static final String INST_START = "inst_start";
|
||||||
public static final String INST_NEXT = "inst_next";
|
public static final String INST_NEXT = "inst_next";
|
||||||
|
public static final String INST_NEXT2 = "inst_next2";
|
||||||
|
|
||||||
protected final SleighLanguage lang;
|
protected final SleighLanguage lang;
|
||||||
protected final Address at;
|
protected final Address at;
|
||||||
|
@ -195,6 +196,8 @@ public class AssemblyTreeResolver {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
vals.put(INST_NEXT, at.add(rc.getInstructionLength()).getAddressableWordOffset());
|
vals.put(INST_NEXT, at.add(rc.getInstructionLength()).getAddressableWordOffset());
|
||||||
|
// inst_next2 use not really supported
|
||||||
|
vals.put(INST_NEXT2, at.add(rc.getInstructionLength()).getAddressableWordOffset());
|
||||||
DBG.println("Backfilling: " + rc);
|
DBG.println("Backfilling: " + rc);
|
||||||
AssemblyResolution ar = rc.backfill(SOLVER, vals);
|
AssemblyResolution ar = rc.backfill(SOLVER, vals);
|
||||||
DBG.println("Backfilled final: " + ar);
|
DBG.println("Backfilled final: " + ar);
|
||||||
|
|
|
@ -210,6 +210,12 @@ public class ParserWalker {
|
||||||
return context.getNaddr();
|
return context.getNaddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Address getN2addr() {
|
||||||
|
if (cross_context != null)
|
||||||
|
return cross_context.getN2addr();
|
||||||
|
return context.getN2addr();
|
||||||
|
}
|
||||||
|
|
||||||
public AddressSpace getCurSpace() {
|
public AddressSpace getCurSpace() {
|
||||||
return context.getCurSpace();
|
return context.getCurSpace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ public abstract class PcodeEmit {
|
||||||
if (opcode == PcodeOp.BRANCH) {
|
if (opcode == PcodeOp.BRANCH) {
|
||||||
int offsetType = inputs[0].getOffset().getType();
|
int offsetType = inputs[0].getOffset().getType();
|
||||||
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
|
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
|
||||||
offsetType == ConstTpl.J_NEXT) {
|
offsetType == ConstTpl.J_NEXT || offsetType == ConstTpl.J_NEXT2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
OpTpl callopt = new OpTpl(PcodeOp.CALL, null, inputs);
|
OpTpl callopt = new OpTpl(PcodeOp.CALL, null, inputs);
|
||||||
|
@ -269,7 +269,7 @@ public abstract class PcodeEmit {
|
||||||
else if (opcode == PcodeOp.CBRANCH) {
|
else if (opcode == PcodeOp.CBRANCH) {
|
||||||
int offsetType = inputs[0].getOffset().getType();
|
int offsetType = inputs[0].getOffset().getType();
|
||||||
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
|
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
|
||||||
offsetType == ConstTpl.J_NEXT) {
|
offsetType == ConstTpl.J_NEXT || offsetType == ConstTpl.J_NEXT2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ public abstract class PcodeEmit {
|
||||||
if (opcode == PcodeOp.BRANCH || opcode == PcodeOp.CALL) {
|
if (opcode == PcodeOp.BRANCH || opcode == PcodeOp.CALL) {
|
||||||
int offsetType = inputs[0].getOffset().getType();
|
int offsetType = inputs[0].getOffset().getType();
|
||||||
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
|
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
|
||||||
offsetType == ConstTpl.J_NEXT) {
|
offsetType == ConstTpl.J_NEXT || offsetType == ConstTpl.J_NEXT2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,6 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
private final static Address[] emptyFlow = new Address[0];
|
private final static Address[] emptyFlow = new Address[0];
|
||||||
|
|
||||||
private ContextCache contextCache;
|
private ContextCache contextCache;
|
||||||
// private InstructionContext instructionContextCache;
|
|
||||||
private int length;
|
private int length;
|
||||||
private ConstructState rootState;
|
private ConstructState rootState;
|
||||||
private ConstructState mnemonicState; // state for print mnemonic
|
private ConstructState mnemonicState; // state for print mnemonic
|
||||||
|
@ -236,6 +235,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
if (destType == ConstTpl.J_NEXT) {
|
if (destType == ConstTpl.J_NEXT) {
|
||||||
flags = BRANCH_TO_END;
|
flags = BRANCH_TO_END;
|
||||||
}
|
}
|
||||||
|
else if (destType == ConstTpl.J_NEXT2) {
|
||||||
|
flags = JUMPOUT;
|
||||||
|
}
|
||||||
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) {
|
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) {
|
||||||
flags = JUMPOUT;
|
flags = JUMPOUT;
|
||||||
}
|
}
|
||||||
|
@ -674,6 +676,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
Address addr = getHandleAddr(hand, parsecontext.getAddr().getAddressSpace());
|
Address addr = getHandleAddr(hand, parsecontext.getAddr().getAddressSpace());
|
||||||
res.add(addr);
|
res.add(addr);
|
||||||
}
|
}
|
||||||
|
else if (rec.op.getInput()[0].getOffset().getType() == ConstTpl.J_NEXT2) {
|
||||||
|
res.add(parsecontext.getN2addr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,7 @@ import ghidra.app.plugin.processors.sleigh.symbol.OperandSymbol;
|
||||||
import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol;
|
import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -33,8 +32,9 @@ import ghidra.program.model.mem.MemoryAccessException;
|
||||||
|
|
||||||
public class SleighParserContext implements ParserContext {
|
public class SleighParserContext implements ParserContext {
|
||||||
private MemBuffer memBuffer;
|
private MemBuffer memBuffer;
|
||||||
private Address addr; // Address of start of instruction
|
private Address addr; // Address of start of instruction (inst_start)
|
||||||
private Address nextInstrAddr; // Address of next instruction
|
private Address nextInstrAddr; // Address of next instruction (inst_next)
|
||||||
|
private Address next2InstAddr; // Address of instruction after next instruction (inst_next2)
|
||||||
private Address refAddr; // corresponds to inst_ref for call-fixup use
|
private Address refAddr; // corresponds to inst_ref for call-fixup use
|
||||||
private Address destAddr; // corresponds to inst_dest for call-fixup use
|
private Address destAddr; // corresponds to inst_dest for call-fixup use
|
||||||
private SleighInstructionPrototype prototype;
|
private SleighInstructionPrototype prototype;
|
||||||
|
@ -71,7 +71,8 @@ public class SleighParserContext implements ParserContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for building precompiled templates
|
* Constructor for building precompiled templates.
|
||||||
|
* NOTE: This form does not support use of <code>inst_next2</next>.
|
||||||
* @param aAddr = address to which 'inst_start' resolves
|
* @param aAddr = address to which 'inst_start' resolves
|
||||||
* @param nAddr = address to which 'inst_next' resolves
|
* @param nAddr = address to which 'inst_next' resolves
|
||||||
* @param rAddr = special address associated with original call
|
* @param rAddr = special address associated with original call
|
||||||
|
@ -172,22 +173,99 @@ public class SleighParserContext implements ParserContext {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get address of current instruction
|
||||||
|
* @return address of current instruction
|
||||||
|
*/
|
||||||
public Address getAddr() {
|
public Address getAddr() {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get address of instruction after current instruction. This may return null if this context
|
||||||
|
* instance does not support use of {@code inst_next} or next address falls beyond end of
|
||||||
|
* address space.
|
||||||
|
* @return address of next instruction or null
|
||||||
|
*/
|
||||||
public Address getNaddr() {
|
public Address getNaddr() {
|
||||||
return nextInstrAddr;
|
return nextInstrAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get address of instruction after the next instruction. This may return {@link #getNaddr()}
|
||||||
|
* if this context instance does not support use of {@code inst_next2} or parse of next
|
||||||
|
* instruction fails.
|
||||||
|
* @return address of instruction after the next instruction or null
|
||||||
|
*/
|
||||||
|
public Address getN2addr() {
|
||||||
|
if (next2InstAddr != null) {
|
||||||
|
return next2InstAddr;
|
||||||
|
}
|
||||||
|
next2InstAddr = computeNext2Address();
|
||||||
|
if (next2InstAddr == null) {
|
||||||
|
// unsupported use of inst_next2 or parse failure on next instruction
|
||||||
|
// returns same as inst_next
|
||||||
|
next2InstAddr = nextInstrAddr;
|
||||||
|
}
|
||||||
|
return next2InstAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address after the next instruction (inst_next2). The length of next instruction
|
||||||
|
* based on attempted parse of next instruction and does not consider any delayslot use.
|
||||||
|
* The current instructions context is used during the parse.
|
||||||
|
* @return address after the next instruction or null if unable/failed to determine
|
||||||
|
*/
|
||||||
|
private Address computeNext2Address() {
|
||||||
|
if (memBuffer == null || nextInstrAddr == null) {
|
||||||
|
return null; // not supported without memBuffer for parse
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Address nextAddr = nextInstrAddr;
|
||||||
|
Language language = prototype.getLanguage();
|
||||||
|
|
||||||
|
// limitation: assumes same context as current instruction
|
||||||
|
ProcessorContextImpl ctx = new ProcessorContextImpl(language);
|
||||||
|
RegisterValue ctxVal = getContextRegisterValue();
|
||||||
|
if (ctxVal != null) {
|
||||||
|
ctx.setRegisterValue(ctxVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = (int) nextAddr.subtract(addr);
|
||||||
|
MemBuffer nearbymem = new WrappedMemBuffer(memBuffer, offset);
|
||||||
|
|
||||||
|
SleighInstructionPrototype proto =
|
||||||
|
(SleighInstructionPrototype) language.parse(nearbymem, ctx, true);
|
||||||
|
|
||||||
|
return nextAddr.addNoWrap(proto.getLength());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get address space containing current instruction
|
||||||
|
* @return address space containing current instruction
|
||||||
|
*/
|
||||||
public AddressSpace getCurSpace() {
|
public AddressSpace getCurSpace() {
|
||||||
return addr.getAddressSpace();
|
return addr.getAddressSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get constant address space
|
||||||
|
* @return constant address space
|
||||||
|
*/
|
||||||
public AddressSpace getConstSpace() {
|
public AddressSpace getConstSpace() {
|
||||||
return constantSpace;
|
return constantSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get memory buffer for current instruction which may also be used to parse next instruction
|
||||||
|
* or delay slot instructions.
|
||||||
|
* @return memory buffer for current instruction
|
||||||
|
*/
|
||||||
public MemBuffer getMemBuffer() {
|
public MemBuffer getMemBuffer() {
|
||||||
return memBuffer;
|
return memBuffer;
|
||||||
}
|
}
|
||||||
|
@ -251,6 +329,44 @@ public class SleighParserContext implements ParserContext {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the processor context value as a RegisterValue
|
||||||
|
* @return processor context value
|
||||||
|
*/
|
||||||
|
public RegisterValue getContextRegisterValue() {
|
||||||
|
|
||||||
|
Register baseContextRegister = prototype.getLanguage().getContextBaseRegister();
|
||||||
|
if (baseContextRegister == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert context int words to byte array for RegisterValue use
|
||||||
|
int ctxByteLen = baseContextRegister.getMinimumByteSize();
|
||||||
|
byte[] ctxValueBytes = new byte[ctxByteLen];
|
||||||
|
|
||||||
|
for (int i = 0; i < context.length; i++) {
|
||||||
|
int word = context[i];
|
||||||
|
for (int n = 3; n >= 0; --n) {
|
||||||
|
int byteIndex = (i * 4) + n;
|
||||||
|
setByte(ctxValueBytes, byteIndex, (byte) word);
|
||||||
|
word >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append mask to value array for RegisterValue use
|
||||||
|
byte[] ctxValueMaskBytes = new byte[2 * ctxByteLen];
|
||||||
|
Arrays.fill(ctxValueMaskBytes, 0, ctxByteLen, (byte) 0xff);
|
||||||
|
System.arraycopy(ctxValueBytes, 0, ctxValueMaskBytes, ctxByteLen, ctxByteLen);
|
||||||
|
|
||||||
|
return new RegisterValue(baseContextRegister, ctxValueMaskBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setByte(byte[] bytes, int index, byte b) {
|
||||||
|
if (index < bytes.length) {
|
||||||
|
bytes[index] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get bytes from context into an int
|
* Get bytes from context into an int
|
||||||
* @param bytestart is the index of the first byte to fetch
|
* @param bytestart is the index of the first byte to fetch
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package ghidra.app.plugin.processors.sleigh.expression;
|
||||||
|
|
||||||
|
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.xml.XmlPullParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The integer offset of the address following the current instruction
|
||||||
|
*/
|
||||||
|
public class Next2InstructionValue extends PatternValue {
|
||||||
|
private static final int HASH = "[inst_next2]".hashCode();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return HASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof Next2InstructionValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long minValue() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long maxValue() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||||
|
Address addr = walker.getN2addr();
|
||||||
|
return addr.getAddressableWordOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||||
|
parser.discardSubTree("next2_exp");
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[inst_next2]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,8 @@ public abstract class PatternExpression {
|
||||||
res = new StartInstructionValue();
|
res = new StartInstructionValue();
|
||||||
else if (nm.equals("end_exp"))
|
else if (nm.equals("end_exp"))
|
||||||
res = new EndInstructionValue();
|
res = new EndInstructionValue();
|
||||||
|
else if (nm.equals("next2_exp"))
|
||||||
|
res = new Next2InstructionValue();
|
||||||
else if (nm.equals("plus_exp"))
|
else if (nm.equals("plus_exp"))
|
||||||
res = new PlusExpression();
|
res = new PlusExpression();
|
||||||
else if (nm.equals("sub_exp"))
|
else if (nm.equals("sub_exp"))
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.processors.sleigh.*;
|
||||||
|
import ghidra.app.plugin.processors.sleigh.expression.Next2InstructionValue;
|
||||||
|
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||||
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
|
import ghidra.xml.XmlElement;
|
||||||
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Symbol with semantic value equal to offset of address immediately
|
||||||
|
* after the next instruction (inst_next2)
|
||||||
|
*/
|
||||||
|
public class Next2Symbol 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.getN2addr().getOffset();
|
||||||
|
hand.size = hand.space.getPointerSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||||
|
long val = walker.getN2addr().getOffset();
|
||||||
|
return "0x"+Long.toHexString(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||||
|
list.add(walker.getParentHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||||
|
XmlElement element = parser.start("next2_sym");
|
||||||
|
patexp = new Next2InstructionValue();
|
||||||
|
parser.end(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighException;
|
import ghidra.app.plugin.processors.sleigh.SleighException;
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
import ghidra.program.model.lang.UnknownInstructionException;
|
import ghidra.program.model.lang.UnknownInstructionException;
|
||||||
|
@ -26,8 +28,6 @@ import ghidra.util.xml.SpecXmlUtils;
|
||||||
import ghidra.xml.XmlElement;
|
import ghidra.xml.XmlElement;
|
||||||
import ghidra.xml.XmlPullParser;
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -152,6 +152,8 @@ public class SymbolTable {
|
||||||
sym = new StartSymbol();
|
sym = new StartSymbol();
|
||||||
else if (el.getName().equals("end_sym_head"))
|
else if (el.getName().equals("end_sym_head"))
|
||||||
sym = new EndSymbol();
|
sym = new EndSymbol();
|
||||||
|
else if (el.getName().equals("next2_sym_head"))
|
||||||
|
sym = new Next2Symbol();
|
||||||
else if (el.getName().equals("subtable_sym_head"))
|
else if (el.getName().equals("subtable_sym_head"))
|
||||||
sym = new SubtableSymbol();
|
sym = new SubtableSymbol();
|
||||||
else
|
else
|
||||||
|
|
|
@ -39,14 +39,15 @@ public class ConstTpl {
|
||||||
public static final int HANDLE = 1;
|
public static final int HANDLE = 1;
|
||||||
public static final int J_START = 2;
|
public static final int J_START = 2;
|
||||||
public static final int J_NEXT = 3;
|
public static final int J_NEXT = 3;
|
||||||
public static final int J_CURSPACE = 4;
|
public static final int J_NEXT2 = 4;
|
||||||
public static final int J_CURSPACE_SIZE = 5;
|
public static final int J_CURSPACE = 5;
|
||||||
public static final int SPACEID = 6;
|
public static final int J_CURSPACE_SIZE = 6;
|
||||||
public static final int J_RELATIVE = 7;
|
public static final int SPACEID = 7;
|
||||||
public static final int J_FLOWREF = 8;
|
public static final int J_RELATIVE = 8;
|
||||||
public static final int J_FLOWREF_SIZE = 9;
|
public static final int J_FLOWREF = 9;
|
||||||
public static final int J_FLOWDEST = 10;
|
public static final int J_FLOWREF_SIZE = 10;
|
||||||
public static final int J_FLOWDEST_SIZE = 11;
|
public static final int J_FLOWDEST = 11;
|
||||||
|
public static final int J_FLOWDEST_SIZE = 12;
|
||||||
|
|
||||||
public static final int V_SPACE = 0;
|
public static final int V_SPACE = 0;
|
||||||
public static final int V_OFFSET = 1;
|
public static final int V_OFFSET = 1;
|
||||||
|
@ -143,6 +144,8 @@ public class ConstTpl {
|
||||||
return walker.getAddr().getOffset();
|
return walker.getAddr().getOffset();
|
||||||
case J_NEXT:
|
case J_NEXT:
|
||||||
return walker.getNaddr().getOffset();
|
return walker.getNaddr().getOffset();
|
||||||
|
case J_NEXT2:
|
||||||
|
return walker.getN2addr().getOffset();
|
||||||
case J_FLOWREF:
|
case J_FLOWREF:
|
||||||
return walker.getFlowRefAddr().getOffset();
|
return walker.getFlowRefAddr().getOffset();
|
||||||
case J_FLOWREF_SIZE:
|
case J_FLOWREF_SIZE:
|
||||||
|
@ -315,6 +318,9 @@ public class ConstTpl {
|
||||||
else if (typestr.equals("next")) {
|
else if (typestr.equals("next")) {
|
||||||
type = J_NEXT;
|
type = J_NEXT;
|
||||||
}
|
}
|
||||||
|
else if (typestr.equals("next2")) {
|
||||||
|
type = J_NEXT2;
|
||||||
|
}
|
||||||
else if (typestr.equals("curspace")) {
|
else if (typestr.equals("curspace")) {
|
||||||
type = J_CURSPACE;
|
type = J_CURSPACE;
|
||||||
}
|
}
|
||||||
|
@ -379,6 +385,8 @@ public class ConstTpl {
|
||||||
return "[flowref_size]";
|
return "[flowref_size]";
|
||||||
case J_NEXT:
|
case J_NEXT:
|
||||||
return "[next]";
|
return "[next]";
|
||||||
|
case J_NEXT2:
|
||||||
|
return "[next2]";
|
||||||
case J_START:
|
case J_START:
|
||||||
return "[start]";
|
return "[start]";
|
||||||
case J_RELATIVE:
|
case J_RELATIVE:
|
||||||
|
|
|
@ -1,302 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package ghidra.pcodeCPort.context;
|
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighException;
|
|
||||||
import ghidra.pcodeCPort.address.Address;
|
|
||||||
import ghidra.pcodeCPort.globalcontext.ContextCache;
|
|
||||||
import ghidra.pcodeCPort.slghsymbol.*;
|
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
|
||||||
import ghidra.pcodeCPort.translate.BadDataError;
|
|
||||||
|
|
||||||
public class ParserContext {
|
|
||||||
public enum ContextState {
|
|
||||||
uninitialized, disassembly, pcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContextState parsestate;
|
|
||||||
private AddrSpace const_space;
|
|
||||||
private byte[] buf = new byte[16]; // Pointer to instruction bit stream
|
|
||||||
private int[] context; // Pointer to local context
|
|
||||||
private int contextsize; // Number of entries in context array
|
|
||||||
private ContextCache contcache; // Interface for getting/setting context
|
|
||||||
private VectorSTL<ContextSet> contextcommit = new VectorSTL<ContextSet>();
|
|
||||||
private Address addr; // Address of start of instruction
|
|
||||||
private Address naddr; // Address of next instruction
|
|
||||||
private VectorSTL<ConstructState> state = new VectorSTL<ConstructState>(); // Current resolved
|
|
||||||
// instruction
|
|
||||||
ConstructState base_state;
|
|
||||||
private ConstructState point; // Current substate
|
|
||||||
private boolean outofband;
|
|
||||||
private int oob_offset;
|
|
||||||
private int alloc; // Number of ConstructState's allocated
|
|
||||||
private int delayslot; // delayslot depth
|
|
||||||
|
|
||||||
public void dispose() {
|
|
||||||
if (context != null) {
|
|
||||||
context = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConstructState getState(int index) {
|
|
||||||
ConstructState constructState = state.get(index);
|
|
||||||
if (constructState == null) {
|
|
||||||
constructState = new ConstructState();
|
|
||||||
state.set(index, constructState);
|
|
||||||
}
|
|
||||||
return constructState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddr(Address ad) {
|
|
||||||
addr = ad;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNaddr(Address ad) {
|
|
||||||
naddr = ad;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearCommits() {
|
|
||||||
contextcommit.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getAddr() {
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getNaddr() {
|
|
||||||
return naddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddrSpace getCurSpace() {
|
|
||||||
return addr.getSpace();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddrSpace getConstSpace() {
|
|
||||||
return const_space;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContextWord(int i, int val, int mask) {
|
|
||||||
context[i] = (context[i] & (~mask)) | (mask & val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadContext() {
|
|
||||||
contcache.getContext(addr, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength() {
|
|
||||||
return base_state.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDelaySlot(int val) {
|
|
||||||
delayslot = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDelaySlot() {
|
|
||||||
return delayslot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParserContext(ContextCache ccache) {
|
|
||||||
parsestate = ContextState.uninitialized;
|
|
||||||
contcache = ccache;
|
|
||||||
if (ccache != null) {
|
|
||||||
contextsize = ccache.getDatabase().getContextSize();
|
|
||||||
context = new int[contextsize];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
contextsize = 0;
|
|
||||||
context = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resize(VectorSTL<ConstructState> list, int newsize) {
|
|
||||||
while (list.size() < newsize) {
|
|
||||||
list.push_back(new ConstructState());
|
|
||||||
}
|
|
||||||
while (list.size() > newsize) {
|
|
||||||
list.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBuffer() {
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initialize(int maxstate, int maxparam, AddrSpace spc) {
|
|
||||||
const_space = spc;
|
|
||||||
resize(state, maxstate);
|
|
||||||
getState(0).parent = null;
|
|
||||||
for (int i = 0; i < maxstate; ++i) {
|
|
||||||
resize(getState(i).resolve, maxparam);
|
|
||||||
}
|
|
||||||
base_state = getState(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContextState getParserState() {
|
|
||||||
return parsestate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParserState(ContextState st) {
|
|
||||||
parsestate = st;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deallocateState(ParserWalkerChange walker) {
|
|
||||||
alloc = 1;
|
|
||||||
walker.context = this;
|
|
||||||
walker.baseState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void allocateOperand(int i, ParserWalkerChange walker) {
|
|
||||||
ConstructState opstate = state.get(alloc++);
|
|
||||||
opstate.parent = walker.point;
|
|
||||||
opstate.ct = null;
|
|
||||||
walker.point.resolve.set(i, opstate);
|
|
||||||
walker.breadcrumb[walker.depth++] += 1;
|
|
||||||
walker.point = opstate;
|
|
||||||
walker.breadcrumb[walker.depth] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInstructionBytes(int bytestart, int size, int off) {
|
|
||||||
// Get bytes from the instruction stream into an int
|
|
||||||
// (assuming big endian format)
|
|
||||||
off += bytestart;
|
|
||||||
if (off >= 16) {
|
|
||||||
throw new BadDataError("Instruction is using more than 16 bytes");
|
|
||||||
}
|
|
||||||
int res = 0;
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
res <<= 8;
|
|
||||||
res |= buf[i + off];
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInstructionBits(int startbit, int size, int off) {
|
|
||||||
off += (startbit / 8);
|
|
||||||
if (off >= 16) {
|
|
||||||
throw new BadDataError("Instruction is using more than 16 bytes");
|
|
||||||
}
|
|
||||||
startbit = startbit % 8;
|
|
||||||
int bytesize = (startbit + size - 1) / 8 + 1;
|
|
||||||
int res = 0;
|
|
||||||
for (int i = 0; i < bytesize; ++i) {
|
|
||||||
res <<= 8;
|
|
||||||
res |= buf[i + off];
|
|
||||||
}
|
|
||||||
res <<= 8 * (4 - bytesize) + startbit; // Move starting bit to highest position
|
|
||||||
res >>= 8 * 4 - size; // Shift to bottom of intm
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get bytes from context into a intm
|
|
||||||
// Assume request is within a intm
|
|
||||||
public int getContextBytes(int bytestart, int size) {
|
|
||||||
int res = context[bytestart / 4];
|
|
||||||
res <<= (bytestart % 4) * 8;
|
|
||||||
res >>>= (4 - size) * 8;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getContextBits(int startbit, int size) {
|
|
||||||
int res = context[startbit / (8 * 4)]; // Get intm containing highest bit
|
|
||||||
res <<= (startbit % (8 * 4)); // Shift startbit to highest position
|
|
||||||
res >>>= (8 * 4 - size);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the offset into instruction bytes (for
|
|
||||||
// future calls into getInstructionBytes) without
|
|
||||||
// disturbing the tree walk
|
|
||||||
public void setOffsetOutOfBand(Constructor c, int index) {
|
|
||||||
outofband = true;
|
|
||||||
ConstructState pt = point;
|
|
||||||
while (pt.ct != c) {
|
|
||||||
if (pt == getState(0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pt = pt.parent;
|
|
||||||
}
|
|
||||||
OperandSymbol sym = c.getOperand(index);
|
|
||||||
int i = sym.getOffsetBase();
|
|
||||||
// if i<0, i.e. the offset of the operand is constructor relative
|
|
||||||
// its possible that the branch corresponding to the operand
|
|
||||||
// has not been constructed yet. Context expressions are
|
|
||||||
// evaluated BEFORE the constructors branches are created.
|
|
||||||
// So we have to construct the offset explicitly.
|
|
||||||
if (i < 0) {
|
|
||||||
oob_offset = pt.offset + sym.getRelativeOffset();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
oob_offset = pt.resolve.get(index).offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCommit(TripleSymbol sym, int num, int mask, boolean flow, ConstructState point) {
|
|
||||||
contextcommit.push_back(new ContextSet());
|
|
||||||
ContextSet set = contextcommit.back();
|
|
||||||
|
|
||||||
set.sym = sym;
|
|
||||||
set.point = point; // This is the current state
|
|
||||||
set.num = num;
|
|
||||||
set.mask = mask;
|
|
||||||
set.value = context[num] & mask;
|
|
||||||
set.flow = flow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyCommits() {
|
|
||||||
if (contextcommit.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ParserWalker walker = new ParserWalker(this);
|
|
||||||
walker.baseState();
|
|
||||||
|
|
||||||
IteratorSTL<ContextSet> iter;
|
|
||||||
for (iter = contextcommit.begin(); !iter.isEnd(); iter.increment()) {
|
|
||||||
TripleSymbol sym = iter.get().sym;
|
|
||||||
Address addr = null;
|
|
||||||
if (sym.getType() == symbol_type.operand_symbol) {
|
|
||||||
// The value for an OperandSymbol is probabably already
|
|
||||||
// calculated, we just need to find the right
|
|
||||||
// tree node of the state
|
|
||||||
int i = ((OperandSymbol) sym).getIndex();
|
|
||||||
FixedHandle h = (iter.get().point.resolve.get(i).hand);
|
|
||||||
addr = new Address(h.space, h.offset_offset);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FixedHandle hand = new FixedHandle();
|
|
||||||
sym.getFixedHandle(hand, walker);
|
|
||||||
addr = new Address(hand.space, hand.offset_offset);
|
|
||||||
}
|
|
||||||
// Commit context change
|
|
||||||
contcache.setContext(addr, iter.get().num, iter.get().mask, iter.get().value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns primary flow reference destination address for instruction or null
|
|
||||||
*/
|
|
||||||
public Address getFlowRefAddr() {
|
|
||||||
throw new SleighException("Flow reference (inst_ref) is undefined at " + getAddr());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns original flow destination address for instruction or null
|
|
||||||
*/
|
|
||||||
public Address getFlowDestAddr() {
|
|
||||||
throw new SleighException("Flow destination (inst_dest) is undefined at " + getAddr());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package ghidra.pcodeCPort.context;
|
|
||||||
|
|
||||||
import ghidra.pcodeCPort.address.Address;
|
|
||||||
import ghidra.pcodeCPort.slghsymbol.Constructor;
|
|
||||||
import ghidra.pcodeCPort.slghsymbol.OperandSymbol;
|
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
|
||||||
|
|
||||||
public class ParserWalker {
|
|
||||||
// A class for walking the ParserContext
|
|
||||||
private ParserContext const_context;
|
|
||||||
protected ConstructState point; // The current node being visited
|
|
||||||
protected int depth; // Depth of the current node
|
|
||||||
protected int[] breadcrumb; // Path of operands from root
|
|
||||||
|
|
||||||
public ParserWalker(ParserContext c) {
|
|
||||||
const_context = c;
|
|
||||||
breadcrumb = new int[32];
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParserContext getParserContext() {
|
|
||||||
return const_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void baseState() {
|
|
||||||
point = const_context.base_state;
|
|
||||||
depth = 0;
|
|
||||||
breadcrumb[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutOfBandState(Constructor ct, int index, ConstructState tempstate,
|
|
||||||
ParserWalker otherwalker) {
|
|
||||||
// Initialize walker for future calls into getInstructionBytes assuming -ct- is the current position in the walk
|
|
||||||
ConstructState pt = otherwalker.point;
|
|
||||||
int curdepth = otherwalker.depth;
|
|
||||||
while (pt.ct != ct) {
|
|
||||||
if (curdepth <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
curdepth -= 1;
|
|
||||||
pt = pt.parent;
|
|
||||||
}
|
|
||||||
OperandSymbol sym = ct.getOperand(index);
|
|
||||||
int i = sym.getOffsetBase();
|
|
||||||
// if i<0, i.e. the offset of the operand is constructor relative
|
|
||||||
// its possible that the branch corresponding to the operand
|
|
||||||
// has not been constructed yet. Context expressions are
|
|
||||||
// evaluated BEFORE the constructors branches are created.
|
|
||||||
// So we have to construct the offset explicitly.
|
|
||||||
if (i < 0) {
|
|
||||||
tempstate.offset = pt.offset + sym.getRelativeOffset();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tempstate.offset = pt.resolve.get(index).offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempstate.ct = ct;
|
|
||||||
tempstate.length = pt.length;
|
|
||||||
point = tempstate;
|
|
||||||
depth = 0;
|
|
||||||
breadcrumb[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isState() {
|
|
||||||
return (point != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pushOperand(int i) {
|
|
||||||
breadcrumb[depth++] = i + 1;
|
|
||||||
point = point.resolve.get(i);
|
|
||||||
breadcrumb[depth] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void popOperand() {
|
|
||||||
point = point.parent;
|
|
||||||
depth -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOffset(int i) {
|
|
||||||
if (i < 0) {
|
|
||||||
return point.offset;
|
|
||||||
}
|
|
||||||
ConstructState op = point.resolve.get(i);
|
|
||||||
return op.offset + op.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Constructor getConstructor() {
|
|
||||||
return point.ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOperand() {
|
|
||||||
return breadcrumb[depth];
|
|
||||||
}
|
|
||||||
|
|
||||||
public FixedHandle getParentHandle() {
|
|
||||||
return point.hand;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FixedHandle getFixedHandle(int i) {
|
|
||||||
return point.resolve.get(i).hand;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddrSpace getCurSpace() {
|
|
||||||
return const_context.getCurSpace();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddrSpace getConstSpace() {
|
|
||||||
return const_context.getConstSpace();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getAddr() {
|
|
||||||
return const_context.getAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getNaddr() {
|
|
||||||
return const_context.getNaddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getFlowRefAddr() {
|
|
||||||
return const_context.getFlowRefAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Address getFlowDestAddr() {
|
|
||||||
return const_context.getFlowDestAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength() {
|
|
||||||
return const_context.getLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInstructionBytes(int byteoff, int numbytes) {
|
|
||||||
return const_context.getInstructionBytes(byteoff, numbytes, point.offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getContextBytes(int byteoff, int numbytes) {
|
|
||||||
return const_context.getContextBytes(byteoff, numbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInstructionBits(int startbit, int size) {
|
|
||||||
return const_context.getInstructionBits(startbit, size, point.offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getContextBits(int startbit, int size) {
|
|
||||||
return const_context.getContextBits(startbit, size);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.context;
|
|
||||||
|
|
||||||
import ghidra.pcodeCPort.slghsymbol.Constructor;
|
|
||||||
|
|
||||||
public class ParserWalkerChange extends ParserWalker {
|
|
||||||
// Extension to walker that allows for on the fly modifications to tree
|
|
||||||
ParserContext context;
|
|
||||||
|
|
||||||
public ParserWalkerChange(ParserContext c) {
|
|
||||||
super(c);
|
|
||||||
context = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParserContext getParserContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConstructState getPoint() {
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffset(int off) {
|
|
||||||
point.offset = off;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConstructor(Constructor c) {
|
|
||||||
point.ct = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCurrentLength(int len) {
|
|
||||||
point.length = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void calcCurrentLength(int length, int numopers) {
|
|
||||||
// Calculate the length of the current constructor
|
|
||||||
// state assuming all its operands are constructed
|
|
||||||
length += point.offset; // Convert relative length to absolute length
|
|
||||||
for (int i = 0; i < numopers; ++i) {
|
|
||||||
ConstructState subpoint = point.resolve.get(i);
|
|
||||||
int sublength = subpoint.length + subpoint.offset;
|
|
||||||
// Since subpoint->offset is an absolute offset
|
|
||||||
// (relative to beginning of instruction) sublength
|
|
||||||
if (sublength > length) {
|
|
||||||
length = sublength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
point.length = length - point.offset; // Convert back to relative length
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,13 +20,10 @@ import java.io.PrintStream;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
import ghidra.pcodeCPort.space.spacetype;
|
import ghidra.pcodeCPort.space.spacetype;
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
|
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
|
|
||||||
public class ConstTpl {
|
public class ConstTpl {
|
||||||
|
@ -41,6 +38,7 @@ public class ConstTpl {
|
||||||
handle,
|
handle,
|
||||||
j_start,
|
j_start,
|
||||||
j_next,
|
j_next,
|
||||||
|
j_next2,
|
||||||
j_curspace,
|
j_curspace,
|
||||||
j_curspace_size,
|
j_curspace_size,
|
||||||
spaceid,
|
spaceid,
|
||||||
|
@ -198,138 +196,6 @@ public class ConstTpl {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long fix(ParserWalker walker) {
|
|
||||||
// Get the value of the ConstTpl in context
|
|
||||||
// NOTE: if the property is dynamic this returns the property
|
|
||||||
// of the temporary storage
|
|
||||||
switch (type) {
|
|
||||||
case j_start:
|
|
||||||
return walker.getAddr().getOffset(); // Fill in starting address placeholder with real address
|
|
||||||
case j_next:
|
|
||||||
return walker.getNaddr().getOffset(); // Fill in next address placeholder with real address
|
|
||||||
case j_curspace_size:
|
|
||||||
return walker.getCurSpace().getAddrSize();
|
|
||||||
case j_curspace:
|
|
||||||
return AddrSpaceToIdSymmetryMap.getID(walker.getCurSpace());
|
|
||||||
case handle: {
|
|
||||||
FixedHandle hand = walker.getFixedHandle(handle_index);
|
|
||||||
switch (select) {
|
|
||||||
case v_space:
|
|
||||||
if (hand.offset_space == null) {
|
|
||||||
return AddrSpaceToIdSymmetryMap.getID(hand.space);
|
|
||||||
}
|
|
||||||
return AddrSpaceToIdSymmetryMap.getID(hand.temp_space);
|
|
||||||
case v_offset:
|
|
||||||
if (hand.offset_space == null) {
|
|
||||||
return hand.offset_offset;
|
|
||||||
}
|
|
||||||
return hand.temp_offset;
|
|
||||||
case v_size:
|
|
||||||
return hand.size;
|
|
||||||
case v_offset_plus:
|
|
||||||
if (hand.space != walker.getConstSpace()) { // If we are not a constant
|
|
||||||
if (hand.offset_space == null) {
|
|
||||||
return hand.offset_offset + (value_real&0xffff);
|
|
||||||
}
|
|
||||||
return hand.temp_offset + (value_real&0xffff);
|
|
||||||
}
|
|
||||||
// If we are a constant, return a shifted value
|
|
||||||
long val;
|
|
||||||
if (hand.offset_space == null)
|
|
||||||
val = hand.offset_offset;
|
|
||||||
else
|
|
||||||
val = hand.temp_offset;
|
|
||||||
val >>= 8 * (value_real >> 16);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case j_relative:
|
|
||||||
case real:
|
|
||||||
return value_real;
|
|
||||||
case spaceid:
|
|
||||||
return AddrSpaceToIdSymmetryMap.getID(spaceid);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0; // Should never reach here
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the value of the ConstTpl in context
|
|
||||||
// when we know it is a space
|
|
||||||
public AddrSpace fixSpace(ParserWalker walker) {
|
|
||||||
// Get the value of the ConstTpl in context
|
|
||||||
// when we know it is a space
|
|
||||||
switch (type) {
|
|
||||||
case j_curspace:
|
|
||||||
return walker.getCurSpace();
|
|
||||||
case handle: {
|
|
||||||
FixedHandle hand = walker.getFixedHandle(handle_index);
|
|
||||||
switch (select) {
|
|
||||||
case v_space:
|
|
||||||
if (hand.offset_space == null) {
|
|
||||||
return hand.space;
|
|
||||||
}
|
|
||||||
return hand.temp_space;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case spaceid:
|
|
||||||
return spaceid;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
throw new LowlevelError("ConstTpl is not a spaceid as expected");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the space portion of a FixedHandle, base on this ConstTpl
|
|
||||||
public void fillinSpace(FixedHandle hand, ParserWalker walker) {
|
|
||||||
switch (type) {
|
|
||||||
case j_curspace:
|
|
||||||
hand.space = walker.getCurSpace();
|
|
||||||
return;
|
|
||||||
case handle: {
|
|
||||||
FixedHandle otherhand = walker.getFixedHandle(handle_index);
|
|
||||||
switch (select) {
|
|
||||||
case v_space:
|
|
||||||
hand.space = otherhand.space;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case spaceid:
|
|
||||||
hand.space = spaceid;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
throw new LowlevelError("ConstTpl is not a spaceid as expected");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fillin the offset portion of a FixedHandle, based on this ConstTpl
|
|
||||||
// If the offset value is dynamic, indicate this in the handle
|
|
||||||
// we don't just fill in the temporary variable offset
|
|
||||||
// we assume hand.space is already filled in
|
|
||||||
public void fillinOffset(FixedHandle hand, ParserWalker walker) {
|
|
||||||
if (type == const_type.handle) {
|
|
||||||
FixedHandle otherhand = walker.getFixedHandle(handle_index);
|
|
||||||
hand.offset_space = otherhand.offset_space;
|
|
||||||
hand.offset_offset = otherhand.offset_offset;
|
|
||||||
hand.offset_size = otherhand.offset_size;
|
|
||||||
hand.temp_space = otherhand.temp_space;
|
|
||||||
hand.temp_offset = otherhand.temp_offset;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset = fix(walker);
|
|
||||||
hand.offset_offset &= hand.space.getMask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyIntoMe(ConstTpl other) {
|
private void copyIntoMe(ConstTpl other) {
|
||||||
type = other.type;
|
type = other.type;
|
||||||
spaceid = other.spaceid;
|
spaceid = other.spaceid;
|
||||||
|
@ -434,6 +300,9 @@ public class ConstTpl {
|
||||||
case j_next:
|
case j_next:
|
||||||
s.append("next\"/>");
|
s.append("next\"/>");
|
||||||
break;
|
break;
|
||||||
|
case j_next2:
|
||||||
|
s.append("next2\"/>");
|
||||||
|
break;
|
||||||
case j_curspace:
|
case j_curspace:
|
||||||
s.append("curspace\"/>");
|
s.append("curspace\"/>");
|
||||||
break;
|
break;
|
||||||
|
@ -485,6 +354,9 @@ public class ConstTpl {
|
||||||
else if (typestring.equals("next")) {
|
else if (typestring.equals("next")) {
|
||||||
type = const_type.j_next;
|
type = const_type.j_next;
|
||||||
}
|
}
|
||||||
|
else if (typestring.equals("next2")) {
|
||||||
|
type = const_type.j_next2;
|
||||||
|
}
|
||||||
else if (typestring.equals("curspace")) {
|
else if (typestring.equals("curspace")) {
|
||||||
type = const_type.j_curspace;
|
type = const_type.j_curspace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,18 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.semantics;
|
package ghidra.pcodeCPort.semantics;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
|
||||||
import ghidra.pcodeCPort.space.spacetype;
|
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
|
||||||
public class HandleTpl {
|
public class HandleTpl {
|
||||||
|
|
||||||
private ConstTpl space;
|
private ConstTpl space;
|
||||||
|
@ -114,33 +110,6 @@ public class HandleTpl {
|
||||||
// Build handle to thing being pointed at by -vn-
|
// Build handle to thing being pointed at by -vn-
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fix(FixedHandle hand, ParserWalker walker) {
|
|
||||||
if (ptrspace.getType() == ConstTpl.const_type.real) {
|
|
||||||
// The export is unstarred, but this doesn't mean the varnode
|
|
||||||
// being exported isn't dynamic
|
|
||||||
space.fillinSpace(hand, walker);
|
|
||||||
hand.size = (int) size.fix(walker);
|
|
||||||
ptroffset.fillinOffset(hand, walker);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hand.space = space.fixSpace(walker);
|
|
||||||
hand.size = (int) size.fix(walker);
|
|
||||||
hand.offset_offset = ptroffset.fix(walker);
|
|
||||||
hand.offset_space = ptrspace.fixSpace(walker);
|
|
||||||
if (hand.offset_space.getType() == spacetype.IPTR_CONSTANT) {
|
|
||||||
// Handle could have been dynamic but wasn't
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset <<= hand.space.getScale();
|
|
||||||
hand.offset_offset &= hand.space.getMask();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hand.offset_size = (int) ptrsize.fix(walker);
|
|
||||||
hand.temp_space = temp_space.fixSpace(walker);
|
|
||||||
hand.temp_offset = temp_offset.fix(walker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changeHandleIndex(VectorSTL<Integer> handmap) {
|
public void changeHandleIndex(VectorSTL<Integer> handmap) {
|
||||||
space.changeHandleIndex(handmap);
|
space.changeHandleIndex(handmap);
|
||||||
size.changeHandleIndex(handmap);
|
size.changeHandleIndex(handmap);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,7 +17,6 @@ package ghidra.pcodeCPort.semantics;
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
import generic.stl.IteratorSTL;
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.translate.UnimplError;
|
import ghidra.pcodeCPort.translate.UnimplError;
|
||||||
|
|
||||||
// SLEIGH specific pcode generator
|
// SLEIGH specific pcode generator
|
||||||
|
@ -27,8 +25,6 @@ public abstract class PcodeBuilder {
|
||||||
private int labelbase;
|
private int labelbase;
|
||||||
private int labelcount;
|
private int labelcount;
|
||||||
|
|
||||||
protected ParserWalker walker;
|
|
||||||
|
|
||||||
protected abstract void dump(OpTpl op);
|
protected abstract void dump(OpTpl op);
|
||||||
|
|
||||||
public PcodeBuilder(int lbcnt) {
|
public PcodeBuilder(int lbcnt) {
|
||||||
|
@ -42,10 +38,6 @@ public abstract class PcodeBuilder {
|
||||||
return labelbase;
|
return labelbase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParserWalker getCurrentWalker() {
|
|
||||||
return walker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void appendBuild(OpTpl bld, int secnum);
|
public abstract void appendBuild(OpTpl bld, int secnum);
|
||||||
|
|
||||||
public abstract void appendCrossBuild(OpTpl bld, int secnum);
|
public abstract void appendCrossBuild(OpTpl bld, int secnum);
|
||||||
|
|
|
@ -21,8 +21,6 @@ import java.util.List;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl.v_field;
|
import ghidra.pcodeCPort.semantics.ConstTpl.v_field;
|
||||||
import ghidra.pcodeCPort.space.spacetype;
|
import ghidra.pcodeCPort.space.spacetype;
|
||||||
|
@ -129,17 +127,6 @@ public class VarnodeTpl {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDynamic(ParserWalker walker) {
|
|
||||||
if (offset.getType() != ConstTpl.const_type.handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Technically we should probably check all three
|
|
||||||
// ConstTpls for dynamic handles, but in all cases
|
|
||||||
// if there is any dynamic piece then the offset is
|
|
||||||
FixedHandle hand = walker.getFixedHandle(offset.getHandleIndex());
|
|
||||||
return (hand.offset_space != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int transfer(VectorSTL<HandleTpl> params) {
|
public int transfer(VectorSTL<HandleTpl> params) {
|
||||||
boolean doesOffsetPlus = false;
|
boolean doesOffsetPlus = false;
|
||||||
int handleIndex=0;
|
int handleIndex=0;
|
||||||
|
|
|
@ -289,6 +289,8 @@ public class SleighCompile extends SleighBase {
|
||||||
symtab.addSymbol(startsym);
|
symtab.addSymbol(startsym);
|
||||||
EndSymbol endsym = new EndSymbol(location, "inst_next", getConstantSpace());
|
EndSymbol endsym = new EndSymbol(location, "inst_next", getConstantSpace());
|
||||||
symtab.addSymbol(endsym);
|
symtab.addSymbol(endsym);
|
||||||
|
Next2Symbol next2sym = new Next2Symbol(location, "inst_next2", getConstantSpace());
|
||||||
|
symtab.addSymbol(next2sym);
|
||||||
EpsilonSymbol epsilon = new EpsilonSymbol(location, "epsilon", getConstantSpace());
|
EpsilonSymbol epsilon = new EpsilonSymbol(location, "epsilon", getConstantSpace());
|
||||||
symtab.addSymbol(epsilon);
|
symtab.addSymbol(epsilon);
|
||||||
}
|
}
|
||||||
|
@ -1280,7 +1282,8 @@ public class SleighCompile extends SleighBase {
|
||||||
VectorSTL<PatternValue> vallist = new VectorSTL<>();
|
VectorSTL<PatternValue> vallist = new VectorSTL<>();
|
||||||
pe.listValues(vallist);
|
pe.listValues(vallist);
|
||||||
for (int i = 0; i < vallist.size(); ++i) {
|
for (int i = 0; i < vallist.size(); ++i) {
|
||||||
if (vallist.get(i) instanceof EndInstructionValue) {
|
PatternValue v = vallist.get(i);
|
||||||
|
if (v instanceof EndInstructionValue || v instanceof Next2InstructionValue) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -32,6 +31,7 @@ class Yylval {
|
||||||
OperandSymbol operandsym;
|
OperandSymbol operandsym;
|
||||||
StartSymbol startsym;
|
StartSymbol startsym;
|
||||||
EndSymbol endsym;
|
EndSymbol endsym;
|
||||||
|
Next2Symbol next2sym;
|
||||||
SubtableSymbol subtablesym;
|
SubtableSymbol subtablesym;
|
||||||
MacroSymbol macrosym;
|
MacroSymbol macrosym;
|
||||||
LabelSymbol labelsym;
|
LabelSymbol labelsym;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class AndExpression extends BinaryExpression {
|
public class AndExpression extends BinaryExpression {
|
||||||
|
|
||||||
public AndExpression(Location location) {
|
public AndExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class AndExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval & rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,16 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class ConstantValue extends PatternValue {
|
public class ConstantValue extends PatternValue {
|
||||||
|
|
||||||
long val;
|
long val;
|
||||||
|
@ -39,11 +37,6 @@ public class ConstantValue extends PatternValue {
|
||||||
val = v;
|
val = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
||||||
return new TokenPattern(location);
|
return new TokenPattern(location);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,17 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
import ghidra.pcodeCPort.utils.Utils;
|
import ghidra.pcodeCPort.utils.Utils;
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
public class ContextField extends PatternValue {
|
public class ContextField extends PatternValue {
|
||||||
|
|
||||||
private int startbit, endbit;
|
private int startbit, endbit;
|
||||||
|
@ -80,19 +78,6 @@ public class ContextField extends PatternValue {
|
||||||
shift = 7 - (endbit % 8);
|
shift = 7 - (endbit % 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long res = ExpressUtils.getContextBytes(pos, startbyte, endbyte);
|
|
||||||
res >>>= shift;
|
|
||||||
if (signbit) {
|
|
||||||
res = Utils.zzz_sign_extend(res, endbit - startbit);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = Utils.zzz_zero_extend(res, endbit - startbit);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "cf:{" + startbit + "," + endbit + "," + startbyte + "," + endbyte + "," + shift +
|
return "cf:{" + startbit + "," + endbit + "," + startbyte + "," + endbyte + "," + shift +
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class DivExpression extends BinaryExpression {
|
public class DivExpression extends BinaryExpression {
|
||||||
|
|
||||||
public DivExpression(Location location) {
|
public DivExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class DivExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval / rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,26 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class EndInstructionValue extends PatternValue {
|
public class EndInstructionValue extends PatternValue {
|
||||||
|
|
||||||
public EndInstructionValue(Location location) {
|
public EndInstructionValue(Location location) {
|
||||||
super(location);
|
super(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
return (pos.getNaddr().getOffset() >>> pos.getNaddr().getSpace().getScale());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
||||||
return new TokenPattern(location);
|
return new TokenPattern(location);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,55 +16,9 @@
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.Utils;
|
|
||||||
|
|
||||||
public class ExpressUtils {
|
public class ExpressUtils {
|
||||||
|
|
||||||
// Build a long from the instruction bytes
|
|
||||||
static long getInstructionBytes(ParserWalker pos, int bytestart, int byteend, boolean bigendian) {
|
|
||||||
long res = 0;
|
|
||||||
|
|
||||||
int size = byteend - bytestart + 1;
|
|
||||||
int tmpsize = size;
|
|
||||||
while (tmpsize >= 4) {
|
|
||||||
int tmp = pos.getInstructionBytes(bytestart, 4);
|
|
||||||
res <<= 32;
|
|
||||||
res |= tmp;
|
|
||||||
bytestart += 4;
|
|
||||||
tmpsize -= 4;
|
|
||||||
}
|
|
||||||
if (tmpsize > 0) {
|
|
||||||
int tmp = pos.getInstructionBytes(bytestart, tmpsize);
|
|
||||||
res <<= 8 * tmpsize;
|
|
||||||
res |= tmp;
|
|
||||||
}
|
|
||||||
if (!bigendian) {
|
|
||||||
res = Utils.byte_swap(res, size);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build a intb from the context bytes
|
|
||||||
static long getContextBytes(ParserWalker pos, int bytestart, int byteend) {
|
|
||||||
long res = 0;
|
|
||||||
|
|
||||||
int size = byteend - bytestart + 1;
|
|
||||||
while (size >= 4) {
|
|
||||||
int tmp = pos.getContextBytes(bytestart, 4);
|
|
||||||
res <<= 32;
|
|
||||||
res |= tmp;
|
|
||||||
bytestart += 4;
|
|
||||||
size = byteend - bytestart + 1;
|
|
||||||
}
|
|
||||||
if (size > 0) {
|
|
||||||
int tmp = pos.getContextBytes(bytestart, size);
|
|
||||||
res <<= 8 * size;
|
|
||||||
res |= tmp;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean advance_combo(VectorSTL<Long> val, VectorSTL<Long> min, VectorSTL<Long> max) {
|
static boolean advance_combo(VectorSTL<Long> val, VectorSTL<Long> min, VectorSTL<Long> max) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < val.size()) {
|
while (i < val.size()) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class LeftShiftExpression extends BinaryExpression {
|
public class LeftShiftExpression extends BinaryExpression {
|
||||||
|
|
||||||
public LeftShiftExpression(Location location) {
|
public LeftShiftExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class LeftShiftExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval << rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class MinusExpression extends UnaryExpression {
|
public class MinusExpression extends UnaryExpression {
|
||||||
|
|
||||||
public MinusExpression(Location location) {
|
public MinusExpression(Location location) {
|
||||||
|
@ -33,12 +31,6 @@ public class MinusExpression extends UnaryExpression {
|
||||||
super(location, u);
|
super(location, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long val = getUnary().getValue(pos);
|
|
||||||
return -val;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long val = getUnary().getSubValue(replace, listpos);
|
long val = getUnary().getSubValue(replace, listpos);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class MultExpression extends BinaryExpression {
|
public class MultExpression extends BinaryExpression {
|
||||||
|
|
||||||
public MultExpression(Location location) {
|
public MultExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class MultExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval * rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
|
public class Next2InstructionValue extends PatternValue {
|
||||||
|
|
||||||
|
public Next2InstructionValue(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 saveXml(PrintStream s) {
|
||||||
|
s.append("<next2_exp/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(Element el, Translate trans) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class NotExpression extends UnaryExpression {
|
public class NotExpression extends UnaryExpression {
|
||||||
|
|
||||||
public NotExpression(Location location) {
|
public NotExpression(Location location) {
|
||||||
|
@ -33,12 +31,6 @@ public class NotExpression extends UnaryExpression {
|
||||||
super(location, u);
|
super(location, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long val = getUnary().getValue(pos);
|
|
||||||
return ~val;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long val = getUnary().getSubValue(replace, listpos);
|
long val = getUnary().getSubValue(replace, listpos);
|
||||||
|
|
|
@ -20,7 +20,7 @@ import java.io.PrintStream;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.*;
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.slghsymbol.*;
|
import ghidra.pcodeCPort.slghsymbol.*;
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
@ -79,28 +79,6 @@ public class OperandValue extends PatternValue {
|
||||||
throw new SleighError("Operand used in pattern expression", ct.location);
|
throw new SleighError("Operand used in pattern expression", ct.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of an operand when it is used in
|
|
||||||
// an expression.
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
OperandSymbol sym = ct.getOperand(index);
|
|
||||||
PatternExpression patexp = sym.getDefiningExpression();
|
|
||||||
if (patexp == null) {
|
|
||||||
TripleSymbol defsym = sym.getDefiningSymbol();
|
|
||||||
if (defsym != null) {
|
|
||||||
patexp = defsym.getPatternExpression();
|
|
||||||
}
|
|
||||||
if (patexp == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ConstructState tempstate = new ConstructState();
|
|
||||||
ParserWalker newwalker = new ParserWalker(pos.getParserContext());
|
|
||||||
newwalker.setOutOfBandState(ct, index, tempstate, pos);
|
|
||||||
long res = patexp.getValue(newwalker);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
OperandSymbol sym = ct.getOperand(index);
|
OperandSymbol sym = ct.getOperand(index);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class OrExpression extends BinaryExpression {
|
public class OrExpression extends BinaryExpression {
|
||||||
|
|
||||||
public OrExpression(Location location) {
|
public OrExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class OrExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval | rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,16 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public abstract class PatternExpression {
|
public abstract class PatternExpression {
|
||||||
public final Location location;
|
public final Location location;
|
||||||
|
|
||||||
|
@ -39,8 +37,6 @@ public abstract class PatternExpression {
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract long getValue(ParserWalker pos);
|
|
||||||
|
|
||||||
public abstract TokenPattern genMinPattern(VectorSTL<TokenPattern> ops);
|
public abstract TokenPattern genMinPattern(VectorSTL<TokenPattern> ops);
|
||||||
|
|
||||||
public abstract void listValues(VectorSTL<PatternValue> list);
|
public abstract void listValues(VectorSTL<PatternValue> list);
|
||||||
|
@ -91,6 +87,9 @@ public abstract class PatternExpression {
|
||||||
else if (nm.equals("end_exp")) {
|
else if (nm.equals("end_exp")) {
|
||||||
res = new EndInstructionValue(null);
|
res = new EndInstructionValue(null);
|
||||||
}
|
}
|
||||||
|
else if (nm.equals("next2_exp")) {
|
||||||
|
res = new Next2InstructionValue(null);
|
||||||
|
}
|
||||||
else if (nm.equals("plus_exp")) {
|
else if (nm.equals("plus_exp")) {
|
||||||
res = new PlusExpression(null);
|
res = new PlusExpression(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class PlusExpression extends BinaryExpression {
|
public class PlusExpression extends BinaryExpression {
|
||||||
|
|
||||||
public PlusExpression(Location location) {
|
public PlusExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class PlusExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval + rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class RightShiftExpression extends BinaryExpression {
|
public class RightShiftExpression extends BinaryExpression {
|
||||||
|
|
||||||
public RightShiftExpression(Location location) {
|
public RightShiftExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class RightShiftExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval >>> rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,26 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class StartInstructionValue extends PatternValue {
|
public class StartInstructionValue extends PatternValue {
|
||||||
|
|
||||||
public StartInstructionValue(Location location) {
|
public StartInstructionValue(Location location) {
|
||||||
super(location);
|
super(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
return (pos.getAddr().getOffset() >> pos.getAddr().getSpace().getScale());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
||||||
return new TokenPattern(location);
|
return new TokenPattern(location);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class SubExpression extends BinaryExpression {
|
public class SubExpression extends BinaryExpression {
|
||||||
|
|
||||||
public SubExpression(Location location) {
|
public SubExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class SubExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval - rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,18 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.context.Token;
|
import ghidra.pcodeCPort.context.Token;
|
||||||
import ghidra.pcodeCPort.translate.Translate;
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
import ghidra.pcodeCPort.utils.Utils;
|
import ghidra.pcodeCPort.utils.Utils;
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
public class TokenField extends PatternValue {
|
public class TokenField extends PatternValue {
|
||||||
|
|
||||||
private Token tok;
|
private Token tok;
|
||||||
|
@ -77,21 +75,6 @@ public class TokenField extends PatternValue {
|
||||||
shift = bitstart % 8;
|
shift = bitstart % 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) { // Construct value given specific
|
|
||||||
// instruction stream
|
|
||||||
long res = ExpressUtils.getInstructionBytes(pos, bytestart, byteend, bigendian);
|
|
||||||
|
|
||||||
res >>>= shift;
|
|
||||||
if (signbit) {
|
|
||||||
res = Utils.zzz_sign_extend(res, bitend - bitstart);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = Utils.zzz_zero_extend(res, bitend - bitstart);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TokenPattern genPattern(long val) { // Generate corresponding pattern if the
|
public TokenPattern genPattern(long val) { // Generate corresponding pattern if the
|
||||||
// value is forced to be val
|
// value is forced to be val
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpatexpress;
|
package ghidra.pcodeCPort.slghpatexpress;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.MutableInt;
|
import ghidra.pcodeCPort.utils.MutableInt;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class XorExpression extends BinaryExpression {
|
public class XorExpression extends BinaryExpression {
|
||||||
|
|
||||||
public XorExpression(Location location) {
|
public XorExpression(Location location) {
|
||||||
|
@ -33,13 +31,6 @@ public class XorExpression extends BinaryExpression {
|
||||||
super(location, l, r);
|
super(location, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue(ParserWalker pos) {
|
|
||||||
long leftval = getLeft().getValue(pos);
|
|
||||||
long rightval = getRight().getValue(pos);
|
|
||||||
return leftval ^ rightval;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
|
||||||
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpattern;
|
package ghidra.pcodeCPort.slghpattern;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -63,17 +60,6 @@ public class CombinePattern extends DisjointPattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMatch(ParserWalker pos) {
|
|
||||||
if (!instr.isMatch(pos)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!context.isMatch(pos)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean alwaysTrue() {
|
public boolean alwaysTrue() {
|
||||||
return (context.alwaysTrue() && instr.alwaysTrue());
|
return (context.alwaysTrue() && instr.alwaysTrue());
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpattern;
|
package ghidra.pcodeCPort.slghpattern;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -60,11 +57,6 @@ public class ContextPattern extends DisjointPattern {
|
||||||
public void shiftInstruction(int sa) {
|
public void shiftInstruction(int sa) {
|
||||||
} // do nothing
|
} // do nothing
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMatch(ParserWalker pos) {
|
|
||||||
return maskvalue.isContextMatch(pos, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean alwaysTrue() {
|
public boolean alwaysTrue() {
|
||||||
return maskvalue.alwaysTrue();
|
return maskvalue.alwaysTrue();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpattern;
|
package ghidra.pcodeCPort.slghpattern;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -70,11 +67,6 @@ public class InstructionPattern extends DisjointPattern {
|
||||||
maskvalue.shift(sa);
|
maskvalue.shift(sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMatch(ParserWalker pos) {
|
|
||||||
return maskvalue.isInstructionMatch(pos, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean alwaysTrue() {
|
public boolean alwaysTrue() {
|
||||||
return maskvalue.alwaysTrue();
|
return maskvalue.alwaysTrue();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,16 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpattern;
|
package ghidra.pcodeCPort.slghpattern;
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.IteratorSTL;
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
|
||||||
public class OrPattern extends Pattern {
|
public class OrPattern extends Pattern {
|
||||||
|
|
||||||
private VectorSTL<DisjointPattern> orlist = new VectorSTL<DisjointPattern>();
|
private VectorSTL<DisjointPattern> orlist = new VectorSTL<DisjointPattern>();
|
||||||
|
@ -71,16 +69,6 @@ public class OrPattern extends Pattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMatch(ParserWalker pos) {
|
|
||||||
for (int i = 0; i < orlist.size(); ++i) {
|
|
||||||
if (orlist.get(i).isMatch(pos)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This isn't quite right because different branches
|
// This isn't quite right because different branches
|
||||||
// may cover the entire gamut
|
// may cover the entire gamut
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghpattern;
|
package ghidra.pcodeCPort.slghpattern;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
@ -37,8 +34,6 @@ public abstract class Pattern {
|
||||||
|
|
||||||
public abstract Pattern commonSubPattern(Pattern b, int sa);
|
public abstract Pattern commonSubPattern(Pattern b, int sa);
|
||||||
|
|
||||||
public abstract boolean isMatch(ParserWalker pos); // Does this pattern match context
|
|
||||||
|
|
||||||
public abstract int numDisjoint();
|
public abstract int numDisjoint();
|
||||||
|
|
||||||
public abstract DisjointPattern getDisjoint(int i);
|
public abstract DisjointPattern getDisjoint(int i);
|
||||||
|
|
|
@ -23,7 +23,6 @@ import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
import generic.stl.IteratorSTL;
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.utils.Utils;
|
import ghidra.pcodeCPort.utils.Utils;
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
|
|
||||||
|
@ -364,36 +363,6 @@ public class PatternBlock {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstructionMatch(ParserWalker pos, int off) {
|
|
||||||
if (nonzerosize <= 0) {
|
|
||||||
return (nonzerosize == 0);
|
|
||||||
}
|
|
||||||
off += offset;
|
|
||||||
for (int i = 0; i < maskvec.size(); ++i) {
|
|
||||||
int data = pos.getInstructionBytes(off, 4);
|
|
||||||
if ((maskvec.get(i) & data) != valvec.get(i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
off += 4;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isContextMatch(ParserWalker pos, int off) {
|
|
||||||
if (nonzerosize <= 0) {
|
|
||||||
return (nonzerosize == 0);
|
|
||||||
}
|
|
||||||
off += offset;
|
|
||||||
for (int i = 0; i < maskvec.size(); ++i) {
|
|
||||||
int data = pos.getContextBytes(off, 4);
|
|
||||||
if ((maskvec.get(i) & data) != valvec.get(i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
off += 4;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<pat_block ");
|
s.append("<pat_block ");
|
||||||
s.append("offset=\"");
|
s.append("offset=\"");
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
import generic.stl.IteratorSTL;
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.*;
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
||||||
import ghidra.pcodeCPort.semantics.ConstructTpl;
|
import ghidra.pcodeCPort.semantics.ConstructTpl;
|
||||||
import ghidra.pcodeCPort.semantics.HandleTpl;
|
import ghidra.pcodeCPort.semantics.HandleTpl;
|
||||||
|
@ -129,13 +129,6 @@ public class Constructor {
|
||||||
return namedtempl.size();
|
return namedtempl.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyContext(ParserWalkerChange pos) {
|
|
||||||
IteratorSTL<ContextChange> iter = context.begin();
|
|
||||||
for (; !iter.isEnd(); iter.increment()) {
|
|
||||||
iter.get().apply(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markSubtableOperands(VectorSTL<Integer> check) {
|
public void markSubtableOperands(VectorSTL<Integer> check) {
|
||||||
// Adjust -check- so it has one entry for every operand, a 0 if it is a subtable, a 2 if it is not
|
// Adjust -check- so it has one entry for every operand, a 0 if it is a subtable, a 2 if it is not
|
||||||
check.resize(operands.size(), 0);
|
check.resize(operands.size(), 0);
|
||||||
|
@ -296,65 +289,6 @@ public class Constructor {
|
||||||
namedtempl.set(id, tpl);
|
namedtempl.set(id, tpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
IteratorSTL<String> piter;
|
|
||||||
for (piter = printpiece.begin(); !piter.isEnd(); piter.increment()) {
|
|
||||||
if (piter.get().charAt(0) == '\n') {
|
|
||||||
int index = piter.get().charAt(1) - 'A';
|
|
||||||
operands.get(index).print(s, pos);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.append(piter.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printMnemonic(PrintStream s, ParserWalker pos) {
|
|
||||||
if (flowthruindex != -1) {
|
|
||||||
TripleSymbol definingSymbol = operands.get(flowthruindex).getDefiningSymbol();
|
|
||||||
if (definingSymbol instanceof SubtableSymbol) {
|
|
||||||
pos.pushOperand(flowthruindex);
|
|
||||||
pos.getConstructor().printMnemonic(s, pos);
|
|
||||||
pos.popOperand();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int endind = (firstwhitespace == -1) ? printpiece.size() : firstwhitespace;
|
|
||||||
for (int i = 0; i < endind; ++i) {
|
|
||||||
if (printpiece.get(i).charAt(0) == '\n') {
|
|
||||||
int index = printpiece.get(i).charAt(1) - 'A';
|
|
||||||
operands.get(index).print(s, pos);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.append(printpiece.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printBody(PrintStream s, ParserWalker pos) {
|
|
||||||
if (flowthruindex != -1) {
|
|
||||||
TripleSymbol sym = operands.get(flowthruindex).getDefiningSymbol();
|
|
||||||
if (sym instanceof SubtableSymbol) {
|
|
||||||
pos.pushOperand(flowthruindex);
|
|
||||||
pos.getConstructor().printBody(s, pos);
|
|
||||||
pos.popOperand();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstwhitespace == -1) {
|
|
||||||
return; // Nothing to print after firstwhitespace
|
|
||||||
}
|
|
||||||
for (int i = firstwhitespace + 1; i < printpiece.size(); ++i) {
|
|
||||||
if (printpiece.get(i).charAt(0) == '\n') {
|
|
||||||
int index = printpiece.get(i).charAt(1) - 'A';
|
|
||||||
operands.get(index).print(s, pos);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.append(printpiece.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow for user to force extra space at end of printing
|
// Allow for user to force extra space at end of printing
|
||||||
public void removeTrailingSpace() {
|
public void removeTrailingSpace() {
|
||||||
if ((!printpiece.empty()) && (printpiece.back().equals(" "))) {
|
if ((!printpiece.empty()) && (printpiece.back().equals(" "))) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalkerChange;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
|
||||||
// Change to context command
|
// Change to context command
|
||||||
public abstract class ContextChange {
|
public abstract class ContextChange {
|
||||||
|
|
||||||
|
@ -35,8 +33,6 @@ public abstract class ContextChange {
|
||||||
|
|
||||||
public abstract void restoreXml(Element el, SleighBase trans);
|
public abstract void restoreXml(Element el, SleighBase trans);
|
||||||
|
|
||||||
public abstract void apply(ParserWalkerChange pos);
|
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,14 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalkerChange;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
|
||||||
import ghidra.pcodeCPort.utils.*;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
import ghidra.pcodeCPort.utils.*;
|
||||||
|
|
||||||
public class ContextCommit extends ContextChange {
|
public class ContextCommit extends ContextChange {
|
||||||
|
|
||||||
private TripleSymbol sym;
|
private TripleSymbol sym;
|
||||||
|
@ -49,12 +47,6 @@ public class ContextCommit extends ContextChange {
|
||||||
mask = m.get();
|
mask = m.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(ParserWalkerChange pos) {
|
|
||||||
pos.getParserContext().addCommit(sym, num, mask, flow, pos.getPoint());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<commit");
|
s.append("<commit");
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,18 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalkerChange;
|
|
||||||
import ghidra.pcodeCPort.context.SleighError;
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.*;
|
import ghidra.pcodeCPort.slghpatexpress.*;
|
||||||
import ghidra.pcodeCPort.utils.*;
|
import ghidra.pcodeCPort.utils.*;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
public class ContextOp extends ContextChange {
|
public class ContextOp extends ContextChange {
|
||||||
public final Location location;
|
public final Location location;
|
||||||
|
|
||||||
|
@ -58,13 +56,6 @@ public class ContextOp extends ContextChange {
|
||||||
patexp.layClaim();
|
patexp.layClaim();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(ParserWalkerChange pos) {
|
|
||||||
int val = (int) patexp.getValue(pos); // Get our value based on context
|
|
||||||
val <<= shift;
|
|
||||||
pos.getParserContext().setContextWord(num, val, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw an exception if the PatternExpression is not valid
|
// Throw an exception if the PatternExpression is not valid
|
||||||
@Override
|
@Override
|
||||||
public void validate() {
|
public void validate() {
|
||||||
|
|
|
@ -22,10 +22,8 @@ import java.util.List;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.*;
|
import generic.stl.*;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
import ghidra.pcodeCPort.slghpattern.DisjointPattern;
|
import ghidra.pcodeCPort.slghpattern.DisjointPattern;
|
||||||
import ghidra.pcodeCPort.translate.BadDataError;
|
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
|
|
||||||
public class DecisionNode {
|
public class DecisionNode {
|
||||||
|
@ -356,27 +354,6 @@ public class DecisionNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Constructor resolve(ParserWalker pos) {
|
|
||||||
if (bitsize == 0) { // The node is terminal
|
|
||||||
IteratorSTL<Pair<DisjointPattern, Constructor>> iter;
|
|
||||||
for (iter = list.begin(); !iter.isEnd(); iter.increment()) {
|
|
||||||
if (iter.get().first.isMatch(pos)) {
|
|
||||||
return iter.get().second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new BadDataError(pos.getAddr().getShortcut() + pos.getAddr().toString() +
|
|
||||||
": Unable to resolve constructor");
|
|
||||||
}
|
|
||||||
int val;
|
|
||||||
if (contextdecision) {
|
|
||||||
val = pos.getContextBits(startbit, bitsize);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val = pos.getInstructionBits(startbit, bitsize);
|
|
||||||
}
|
|
||||||
return children.get(val).resolve(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void saveXml(PrintStream s) {
|
void saveXml(PrintStream s) {
|
||||||
s.append("<decision");
|
s.append("<decision");
|
||||||
s.append(" number=\"");
|
s.append(" number=\"");
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
import java.io.PrintStream;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
@ -26,10 +27,6 @@ import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
public class EndSymbol extends SpecificSymbol {
|
public class EndSymbol extends SpecificSymbol {
|
||||||
private AddrSpace const_space;
|
private AddrSpace const_space;
|
||||||
private PatternExpression patexp;
|
private PatternExpression patexp;
|
||||||
|
@ -72,21 +69,6 @@ public class EndSymbol extends SpecificSymbol {
|
||||||
return new VarnodeTpl(location, spc, off, sz_zero);
|
return new VarnodeTpl(location, spc, off, sz_zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
hand.space = pos.getCurSpace();
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset = pos.getNaddr().getOffset(); // Get starting address of next instruction
|
|
||||||
hand.size = hand.space.getAddrSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
long val = pos.getNaddr().getOffset();
|
|
||||||
s.append("0x");
|
|
||||||
s.append(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<end_sym");
|
s.append("<end_sym");
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,18 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
import java.io.PrintStream;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
// Another name for zero pattern/value
|
// Another name for zero pattern/value
|
||||||
public class EpsilonSymbol extends PatternlessSymbol {
|
public class EpsilonSymbol extends PatternlessSymbol {
|
||||||
|
|
||||||
|
@ -47,19 +44,6 @@ public class EpsilonSymbol extends PatternlessSymbol {
|
||||||
return symbol_type.epsilon_symbol;
|
return symbol_type.epsilon_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
hand.space = const_space;
|
|
||||||
hand.offset_space = null; // Not a dynamic value
|
|
||||||
hand.offset_offset = 0;
|
|
||||||
hand.size = 0; // Cannot provide size
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
s.append('0');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VarnodeTpl getVarnode() {
|
public VarnodeTpl getVarnode() {
|
||||||
return new VarnodeTpl(location, new ConstTpl(const_space), new ConstTpl(
|
return new VarnodeTpl(location, new ConstTpl(const_space), new ConstTpl(
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import ghidra.pcodeCPort.address.Address;
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
|
@ -49,15 +44,6 @@ public class FlowDestSymbol extends SpecificSymbol {
|
||||||
return symbol_type.start_symbol;
|
return symbol_type.start_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
|
||||||
Address refAddr = walker.getFlowDestAddr();
|
|
||||||
hand.space = const_space;
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset = refAddr.getOffset();
|
|
||||||
hand.size = refAddr.getAddrSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VarnodeTpl getVarnode() {
|
public VarnodeTpl getVarnode() {
|
||||||
ConstTpl spc = new ConstTpl(const_space);
|
ConstTpl spc = new ConstTpl(const_space);
|
||||||
|
@ -66,10 +52,4 @@ public class FlowDestSymbol extends SpecificSymbol {
|
||||||
return new VarnodeTpl(location, spc, off, sz_zero);
|
return new VarnodeTpl(location, spc, off, sz_zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
long val = pos.getFlowDestAddr().getOffset();
|
|
||||||
s.append("0x");
|
|
||||||
s.print(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import ghidra.pcodeCPort.address.Address;
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
|
@ -50,15 +45,6 @@ public class FlowRefSymbol extends SpecificSymbol {
|
||||||
return symbol_type.start_symbol;
|
return symbol_type.start_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
|
||||||
Address refAddr = walker.getFlowRefAddr();
|
|
||||||
hand.space = const_space;
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset = refAddr.getOffset();
|
|
||||||
hand.size = refAddr.getAddrSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VarnodeTpl getVarnode() {
|
public VarnodeTpl getVarnode() {
|
||||||
ConstTpl spc = new ConstTpl(const_space);
|
ConstTpl spc = new ConstTpl(const_space);
|
||||||
|
@ -67,10 +53,4 @@ public class FlowRefSymbol extends SpecificSymbol {
|
||||||
return new VarnodeTpl(location, spc, off, sz_zero);
|
return new VarnodeTpl(location, spc, off, sz_zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
long val = pos.getFlowRefAddr().getOffset();
|
|
||||||
s.append("0x");
|
|
||||||
s.print(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,9 @@ import java.util.List;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
||||||
import ghidra.pcodeCPort.translate.BadDataError;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class NameSymbol extends ValueSymbol {
|
public class NameSymbol extends ValueSymbol {
|
||||||
|
@ -56,32 +54,11 @@ public class NameSymbol extends ValueSymbol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Constructor resolve(ParserWalker pos) {
|
|
||||||
if (!tableisfilled) {
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
if ((ind >= nametable.size()) || (ind < 0) || (nametable.get(ind).length() == 0)) {
|
|
||||||
throw new BadDataError(
|
|
||||||
"No corresponding entry in nametable <" + getName() + ">, index=" + ind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public symbol_type getType() {
|
public symbol_type getType() {
|
||||||
return symbol_type.name_symbol;
|
return symbol_type.name_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos)
|
|
||||||
|
|
||||||
{
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
// ind is already checked to be in range by the resolve routine
|
|
||||||
s.print(nametable.get(ind));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<name_sym");
|
s.append("<name_sym");
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* ###
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||||
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.Next2InstructionValue;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
|
import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
|
public class Next2Symbol extends SpecificSymbol {
|
||||||
|
private AddrSpace const_space;
|
||||||
|
private PatternExpression patexp;
|
||||||
|
|
||||||
|
public Next2Symbol(Location location) {
|
||||||
|
super(location);
|
||||||
|
patexp = null;
|
||||||
|
} // For use with restoreXml
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PatternExpression getPatternExpression() {
|
||||||
|
return patexp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public symbol_type getType() {
|
||||||
|
return symbol_type.next2_symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Next2Symbol(Location location, String nm, AddrSpace cspc) {
|
||||||
|
super(location, nm);
|
||||||
|
const_space = cspc;
|
||||||
|
patexp = new Next2InstructionValue(location);
|
||||||
|
patexp.layClaim();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
if (patexp != null) {
|
||||||
|
PatternExpression.release(patexp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return next instruction offset as a constant
|
||||||
|
@Override
|
||||||
|
public VarnodeTpl getVarnode() {
|
||||||
|
ConstTpl spc = new ConstTpl(const_space);
|
||||||
|
ConstTpl off = new ConstTpl(ConstTpl.const_type.j_next2);
|
||||||
|
ConstTpl sz_zero = new ConstTpl();
|
||||||
|
return new VarnodeTpl(location, spc, off, sz_zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveXml(PrintStream s) {
|
||||||
|
s.append("<next2_sym");
|
||||||
|
saveSleighSymbolXmlHeader(s);
|
||||||
|
s.println("/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveXmlHeader(PrintStream s) {
|
||||||
|
s.append("<next2_sym_head");
|
||||||
|
saveSleighSymbolXmlHeader(s);
|
||||||
|
s.println("/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreXml(Element el, SleighBase trans) {
|
||||||
|
const_space = trans.getConstantSpace();
|
||||||
|
patexp = new Next2InstructionValue(null);
|
||||||
|
patexp.layClaim();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.*;
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.OperandValue;
|
import ghidra.pcodeCPort.slghpatexpress.OperandValue;
|
||||||
|
@ -168,11 +168,6 @@ public class OperandSymbol extends SpecificSymbol {
|
||||||
return new VarnodeTpl(location, hand, false); // Possible dynamic handle
|
return new VarnodeTpl(location, hand, false); // Possible dynamic handle
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hnd, ParserWalker pos) {
|
|
||||||
hnd = pos.getFixedHandle(hand);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
if (triple != null) {
|
if (triple != null) {
|
||||||
|
@ -181,31 +176,6 @@ public class OperandSymbol extends SpecificSymbol {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
pos.pushOperand(getIndex());
|
|
||||||
if (triple != null) {
|
|
||||||
if (triple.getType() == symbol_type.subtable_symbol) {
|
|
||||||
pos.getConstructor().print(s, pos);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
triple.print(s, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
long val = defexp.getValue(pos);
|
|
||||||
if (val >= 0) {
|
|
||||||
s.append("0x");
|
|
||||||
s.append(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.append("-0x");
|
|
||||||
s.append(Long.toHexString(-val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos.popOperand();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collectLocalValues(ArrayList<Long> results) {
|
public void collectLocalValues(ArrayList<Long> results) {
|
||||||
if (triple != null) {
|
if (triple != null) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
import java.io.PrintStream;
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
@ -26,10 +27,6 @@ import ghidra.pcodeCPort.slghpatexpress.StartInstructionValue;
|
||||||
import ghidra.pcodeCPort.space.AddrSpace;
|
import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
public class StartSymbol extends SpecificSymbol {
|
public class StartSymbol extends SpecificSymbol {
|
||||||
private AddrSpace const_space;
|
private AddrSpace const_space;
|
||||||
private PatternExpression patexp;
|
private PatternExpression patexp;
|
||||||
|
@ -72,21 +69,6 @@ public class StartSymbol extends SpecificSymbol {
|
||||||
return new VarnodeTpl(location, spc, off, sz_zero);
|
return new VarnodeTpl(location, spc, off, sz_zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
hand.space = pos.getCurSpace();
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset = pos.getAddr().getOffset(); // Get starting address of instruction
|
|
||||||
hand.size = hand.space.getAddrSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
long val = pos.getAddr().getOffset();
|
|
||||||
s.append("0x");
|
|
||||||
s.print(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<start_sym");
|
s.append("<start_sym");
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
import generic.stl.IteratorSTL;
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.*;
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
import ghidra.pcodeCPort.slghpatexpress.TokenPattern;
|
import ghidra.pcodeCPort.slghpatexpress.TokenPattern;
|
||||||
|
@ -58,11 +58,6 @@ public class SubtableSymbol extends TripleSymbol {
|
||||||
construct.push_back(ct);
|
construct.push_back(ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Constructor resolve(ParserWalker pos) {
|
|
||||||
return decisiontree.resolve(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TokenPattern getPattern() {
|
public TokenPattern getPattern() {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
@ -80,21 +75,11 @@ public class SubtableSymbol extends TripleSymbol {
|
||||||
throw new SleighError("Cannot use subtable in expression", null);
|
throw new SleighError("Cannot use subtable in expression", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
throw new SleighError("Cannot use subtable in expression", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
throw new SleighError("Cannot use subtable in expression", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collectLocalValues(ArrayList<Long> results) {
|
public void collectLocalValues(ArrayList<Long> results) {
|
||||||
for (Constructor curConstruct : construct) {
|
for (Constructor curConstruct : construct) {
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
import generic.stl.IteratorSTL;
|
import generic.stl.IteratorSTL;
|
||||||
import generic.stl.VectorSTL;
|
import generic.stl.VectorSTL;
|
||||||
import ghidra.pcodeCPort.context.SleighError;
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
|
@ -22,12 +28,6 @@ import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
public class SymbolTable {
|
public class SymbolTable {
|
||||||
|
|
||||||
private VectorSTL<SleighSymbol> symbollist = new VectorSTL<SleighSymbol>();
|
private VectorSTL<SleighSymbol> symbollist = new VectorSTL<SleighSymbol>();
|
||||||
|
@ -300,6 +300,9 @@ public class SymbolTable {
|
||||||
else if (el.getName().equals("end_sym_head")) {
|
else if (el.getName().equals("end_sym_head")) {
|
||||||
sym = new EndSymbol(location);
|
sym = new EndSymbol(location);
|
||||||
}
|
}
|
||||||
|
else if (el.getName().equals("next2_sym_head")) {
|
||||||
|
sym = new Next2Symbol(location);
|
||||||
|
}
|
||||||
else if (el.getName().equals("subtable_sym_head")) {
|
else if (el.getName().equals("subtable_sym_head")) {
|
||||||
sym = new SubtableSymbol(location);
|
sym = new SubtableSymbol(location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
|
@ -36,20 +33,12 @@ public abstract class TripleSymbol extends SleighSymbol {
|
||||||
|
|
||||||
public abstract PatternExpression getPatternExpression();
|
public abstract PatternExpression getPatternExpression();
|
||||||
|
|
||||||
public abstract void getFixedHandle(FixedHandle hand, ParserWalker pos);
|
|
||||||
|
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return 0;
|
return 0;
|
||||||
} // Size out of context
|
} // Size out of context
|
||||||
|
|
||||||
public abstract void print(PrintStream s, ParserWalker pos);
|
|
||||||
|
|
||||||
public void collectLocalValues(ArrayList<Long> results) {
|
public void collectLocalValues(ArrayList<Long> results) {
|
||||||
// By default, assume symbol has no local exports
|
// By default, assume symbol has no local exports
|
||||||
}
|
}
|
||||||
|
|
||||||
public Constructor resolve(ParserWalker pos) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,22 +15,19 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
|
||||||
import ghidra.pcodeCPort.translate.BadDataError;
|
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
||||||
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class ValueMapSymbol extends ValueSymbol {
|
public class ValueMapSymbol extends ValueSymbol {
|
||||||
private VectorSTL<Long> valuetable = new VectorSTL<Long>();
|
private VectorSTL<Long> valuetable = new VectorSTL<Long>();
|
||||||
private boolean tableisfilled;
|
private boolean tableisfilled;
|
||||||
|
@ -63,41 +59,6 @@ public class ValueMapSymbol extends ValueSymbol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Constructor resolve(ParserWalker pos) {
|
|
||||||
if (!tableisfilled) {
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
if ((ind >= valuetable.size()) || (ind < 0) || (valuetable.get(ind) == 0xBADBEEF)) {
|
|
||||||
throw new BadDataError("No corresponding entry in nametable <" + getName() +
|
|
||||||
">, index=" + ind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
// The resolve routine has checked that -ind- must be a valid index
|
|
||||||
hand.space = pos.getConstSpace();
|
|
||||||
hand.offset_space = null; // Not a dynamic value
|
|
||||||
hand.offset_offset = valuetable.get(ind);
|
|
||||||
hand.size = 0; // Cannot provide size
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
// ind is already checked to be in range by the resolve routine
|
|
||||||
Long val = valuetable.get(ind);
|
|
||||||
if (val >= 0) {
|
|
||||||
s.append("0x").append(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.append("-0x").append(Long.toHexString(-val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<valuemap_sym");
|
s.append("<valuemap_sym");
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,18 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.context.FixedHandle;
|
|
||||||
import ghidra.pcodeCPort.context.ParserWalker;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class ValueSymbol extends FamilySymbol {
|
public class ValueSymbol extends FamilySymbol {
|
||||||
|
|
||||||
protected PatternValue patval;
|
protected PatternValue patval;
|
||||||
|
@ -65,27 +62,6 @@ public class ValueSymbol extends FamilySymbol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
hand.space = pos.getConstSpace();
|
|
||||||
hand.offset_space = null;
|
|
||||||
hand.offset_offset = patval.getValue(pos);
|
|
||||||
hand.size = 0; // Cannot provide size
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
long val = patval.getValue(pos);
|
|
||||||
if (val >= 0) {
|
|
||||||
s.append("0x");
|
|
||||||
s.append(Long.toHexString(val));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.append("-0x");
|
|
||||||
s.append(Long.toHexString(-val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<value_sym");
|
s.append("<value_sym");
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,23 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slghsymbol;
|
package ghidra.pcodeCPort.slghsymbol;
|
||||||
|
|
||||||
import generic.stl.VectorSTL;
|
|
||||||
import ghidra.pcodeCPort.context.*;
|
|
||||||
import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
|
||||||
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
|
||||||
import ghidra.pcodeCPort.translate.BadDataError;
|
|
||||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
|
||||||
import ghidra.sleigh.grammar.Location;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import generic.stl.VectorSTL;
|
||||||
|
import ghidra.pcodeCPort.context.SleighError;
|
||||||
|
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||||
|
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
||||||
|
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||||
|
import ghidra.sleigh.grammar.Location;
|
||||||
|
|
||||||
public class VarnodeListSymbol extends ValueSymbol {
|
public class VarnodeListSymbol extends ValueSymbol {
|
||||||
|
|
||||||
private VectorSTL<VarnodeSymbol> varnode_table = new VectorSTL<VarnodeSymbol>();
|
private VectorSTL<VarnodeSymbol> varnode_table = new VectorSTL<VarnodeSymbol>();
|
||||||
|
@ -67,32 +63,6 @@ public class VarnodeListSymbol extends ValueSymbol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Constructor resolve(ParserWalker walker) {
|
|
||||||
if (!tableisfilled) {
|
|
||||||
int ind = (int) patval.getValue(walker);
|
|
||||||
if ((ind < 0) || (ind >= varnode_table.size()) || (varnode_table.get(ind) == null)) {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
PrintStream s = new PrintStream(baos);
|
|
||||||
walker.getAddr().printRaw(s);
|
|
||||||
throw new BadDataError(walker.getAddr().getShortcut() + baos.toString() +
|
|
||||||
": No corresponding entry in varnode list");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getFixedHandle(FixedHandle hand, ParserWalker pos) {
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
// The resolve routine has checked that -ind- must be a valid index
|
|
||||||
VarnodeData fix = varnode_table.get(ind).getFixedVarnode();
|
|
||||||
hand.space = fix.space;
|
|
||||||
hand.offset_space = null; // Not a dynamic value
|
|
||||||
hand.offset_offset = fix.offset;
|
|
||||||
hand.size = fix.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
for (int i = 0; i < varnode_table.size(); ++i) {
|
for (int i = 0; i < varnode_table.size(); ++i) {
|
||||||
|
@ -104,15 +74,6 @@ public class VarnodeListSymbol extends ValueSymbol {
|
||||||
throw new SleighError("No register attached to: " + getName(), getLocation());
|
throw new SleighError("No register attached to: " + getName(), getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void print(PrintStream s, ParserWalker pos) {
|
|
||||||
int ind = (int) patval.getValue(pos);
|
|
||||||
if (ind >= varnode_table.size()) {
|
|
||||||
throw new SleighError("Value out of range for varnode table", getLocation());
|
|
||||||
}
|
|
||||||
s.append(varnode_table.get(ind).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml(PrintStream s) {
|
public void saveXml(PrintStream s) {
|
||||||
s.append("<varlist_sym");
|
s.append("<varlist_sym");
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue