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:
Ryan Kurtz 2022-08-25 01:19:02 -04:00
commit ca80be44ff
121 changed files with 4074 additions and 4553 deletions

View file

@ -105,14 +105,14 @@ public class DebuggerStateEditingPluginIntegrationTest extends AbstractGhidraHea
assertTrue(
helper.patchInstructionAction.isAddToPopup(listingProvider.getActionContext(null)));
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());
long snap = traceManager.getCurrent().getViewSnap();
assertTrue(DBTraceUtils.isScratch(snap));
byte[] bytes = new byte[2];
view.getMemory().getBytes(tb.addr(0x00400123), bytes);
assertArrayEquals(tb.arr(0x40, 1234), bytes);
assertArrayEquals(tb.arr(0x30, 0xd2), bytes);
}
@Test

View file

@ -86,8 +86,8 @@ public class DebuggerPcodeStepperProviderTest extends AbstractGhidraHeadedDebugg
Assembler asm = Assemblers.getAssembler(tb.trace.getFixedProgramView(0));
iit = asm.assemble(start,
"imm r0, #1234",
"imm r1, #2045"); // 11 bits unsigned
"imm r0, #0x3d2",
"imm r1, #911"); // 10 bits unsigned
}
imm1234 = iit.next();

View file

@ -246,7 +246,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
"pc = 0x00400000;",
"sp = 0x00110000;"),
List.of(
"imm r0, #1234")); // decimal
"imm r0, #911")); // decimal
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.trace, 0);
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
@ -261,7 +261,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
TraceSleighUtils.evaluate("sp", tb.trace, 1, thread, 0));
assertEquals(BigInteger.valueOf(0x00400002),
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
assertEquals(BigInteger.valueOf(1234),
assertEquals(BigInteger.valueOf(911),
TraceSleighUtils.evaluate("r0", tb.trace, 1, thread, 0));
}
}
@ -278,9 +278,9 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
"sp = 0x00110000;"),
List.of(
"brds 0x00400006",
"imm r0, #1234", // decimal
"imm r0, #2020",
"imm r1, #2021"));
"imm r0, #911", // decimal
"imm r0, #860",
"imm r1, #861"));
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.trace, 0);
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
@ -294,9 +294,9 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
assertEquals(BigInteger.valueOf(0x00400008),
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
assertEquals(BigInteger.valueOf(1234),
assertEquals(BigInteger.valueOf(911),
TraceSleighUtils.evaluate("r0", tb.trace, 1, thread, 0));
assertEquals(BigInteger.valueOf(2021),
assertEquals(BigInteger.valueOf(861),
TraceSleighUtils.evaluate("r1", tb.trace, 1, thread, 0));
}
}

View file

@ -176,6 +176,9 @@ public abstract class AbstractPcodeFormatter<T, A extends Appender<T>>
else if (offset.getType() == ConstTpl.J_NEXT) {
appender.appendLabel("inst_next");
}
else if (offset.getType() == ConstTpl.J_NEXT2) {
appender.appendLabel("inst_next2");
}
else {
formatAddress(appender, null, offset, size);
}

View file

@ -494,6 +494,27 @@ public class ToyProgramBuilder extends ProgramBuilder {
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)
* @param offset instruction address offset

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.plugin.core.assembler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
import org.junit.*;
@ -90,8 +90,8 @@ public class AssemblerPluginTest extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testActionPatchInstructionNoExisting() throws Exception {
Address address = space.getAddress(0x00400000);
Instruction ins = helper.patchInstructionAt(address, "", "imm r0, #1234");
assertEquals("imm r0,#0x4d2", ins.toString());
Instruction ins = helper.patchInstructionAt(address, "", "imm r0, #911");
assertEquals("imm r0,#0x38f", ins.toString());
}
@Test
@ -99,11 +99,11 @@ public class AssemblerPluginTest extends AbstractGhidraHeadedIntegrationTest {
Address address = space.getAddress(0x00400000);
Assembler asm = Assemblers.getAssembler(program);
try (ProgramTransaction trans = ProgramTransaction.open(program, "Assemble pre-existing")) {
asm.assemble(address, "imm r0,#0x4d2");
asm.assemble(address, "imm r0,#0x3d2");
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());
}

View file

@ -41,6 +41,7 @@ src/decompile/datatests/pointersub.xml||GHIDRA||||END|
src/decompile/datatests/promotecompare.xml||GHIDRA||||END|
src/decompile/datatests/readvolatile.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/threedim.xml||GHIDRA||||END|
src/decompile/datatests/twodim.xml||GHIDRA||||END|

View file

@ -17,11 +17,12 @@
#include "slghsymbol.hh"
#include "translate.hh"
ParserContext::ParserContext(ContextCache *ccache)
ParserContext::ParserContext(ContextCache *ccache,Translate *trans)
{
parsestate = 0;
parsestate = uninitialized;
contcache = ccache;
translate = trans;
if (ccache != (ContextCache *)0) {
contextsize = ccache->getDatabase()->getContextSize();
context = new uintm[ contextsize ];
@ -43,6 +44,18 @@ void ParserContext::initialize(int4 maxstate,int4 maxparam,AddrSpace *spc)
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
{ // Get bytes from the instruction stream into a intm

View file

@ -64,6 +64,7 @@ struct ContextSet { // Instructions for setting a global context value
class ParserWalker; // Forward declaration
class ParserWalkerChange;
class Translate;
class ParserContext {
friend class ParserWalker;
@ -75,6 +76,7 @@ public:
pcode = 2 // Instruction is parsed in preparation for generating p-code
};
private:
Translate *translate; // Instruction parser
int4 parsestate;
AddrSpace *const_space;
uint1 buf[16]; // Buffer of bytes in the instruction stream
@ -84,13 +86,14 @@ private:
vector<ContextSet> contextcommit;
Address addr; // Address of start of 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
vector<ConstructState> state; // Current resolved instruction
ConstructState *base_state;
int4 alloc; // Number of ConstructState's allocated
int4 delayslot; // delayslot depth
public:
ParserContext(ContextCache *ccache);
ParserContext(ContextCache *ccache,Translate *trans);
~ParserContext(void) { if (context != (uintm *)0) delete [] context; }
uint1 *getBuffer(void) { return buf; }
void initialize(int4 maxstate,int4 maxparam,AddrSpace *spc);
@ -98,7 +101,7 @@ public:
void setParserState(int4 st) { parsestate = st; }
void deallocateState(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 setCalladdr(const Address &ad) { calladdr = ad; }
void addCommit(TripleSymbol *sym,int4 num,uintm mask,bool flow,ConstructState *point);
@ -106,6 +109,7 @@ public:
void applyCommits(void);
const Address &getAddr(void) const { return addr; }
const Address &getNaddr(void) const { return naddr; }
const Address &getN2addr(void) const;
const Address &getDestAddr(void) const { return calladdr; }
const Address &getRefAddr(void) const { return calladdr; }
AddrSpace *getCurSpace(void) const { return addr.getSpace(); }
@ -147,6 +151,7 @@ public:
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 &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 &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(); }

View file

@ -791,7 +791,7 @@ void Funcdata::doLiveInject(InjectPayload *payload,const Address &addr,BlockBasi
emitter.setFuncdata(this);
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;
list<PcodeOp *>::const_iterator deaditer = obank.endDead();

View file

@ -333,7 +333,7 @@ void PcodeInjectLibrarySleigh::parseInject(InjectPayload *payload)
throw LowlevelError("Registering pcode snippet before language is instantiated");
}
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());
}
PcodeSnippet compiler(slgh);

View file

@ -69,6 +69,7 @@ public:
/// concrete Varnodes. This class contains the context dependent data to resolve:
/// - inst_start -- the address where the injection occurs
/// - 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_ref -- Target of reference on injected instruction
/// - \<input> -- Input Varnode of the injection referenced by name

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@
LabelSymbol *labelsym;
StartSymbol *startsym;
EndSymbol *endsym;
Next2Symbol *next2sym;
OperandSymbol *operandsym;
VarnodeSymbol *varsym;
SpecificSymbol *specsym;
@ -76,6 +77,7 @@
%token <operandsym> OPERANDSYM
%token <startsym> STARTSYM
%token <endsym> ENDSYM
%token <next2sym> NEXT2SYM
%token <labelsym> LABELSYM
%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; }
| 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; }
| 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; }
@ -221,6 +224,7 @@ specificsymbol: VARSYM { $$ = $1; }
| OPERANDSYM { $$ = $1; }
| STARTSYM { $$ = $1; }
| ENDSYM { $$ = $1; }
| NEXT2SYM { $$ = $1; }
;
paramlist: /* EMPTY */ { $$ = new vector<ExprTree *>; }
| expr { $$ = new vector<ExprTree *>; $$->push_back($1); }
@ -749,6 +753,9 @@ int4 PcodeSnippet::lex(void)
case SleighSymbol::end_symbol:
yylval.endsym = (EndSymbol *)sym;
return ENDSYM;
case SleighSymbol::next2_symbol:
yylval.next2sym = (Next2Symbol *)sym;
return NEXT2SYM;
case SleighSymbol::label_symbol:
yylval.labelsym = (LabelSymbol *)sym;
return LABELSYM;

View file

@ -121,6 +121,8 @@ uintb ConstTpl::fix(const ParserWalker &walker) const
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_next2:
return walker.getN2addr().getOffset(); // Fill in next2 address placeholder with real address
case j_flowref:
return walker.getRefAddr().getOffset();
case j_flowref_size:
@ -349,6 +351,9 @@ void ConstTpl::saveXml(ostream &s) const
case j_next:
s << "next\"/>";
break;
case j_next2:
s << "next2\"/>";
break;
case j_curspace:
s << "curspace\"/>";
break;
@ -404,6 +409,9 @@ void ConstTpl::restoreXml(const Element *el,const AddrSpaceManager *manage)
else if (typestring=="next") {
type = j_next;
}
else if (typestring=="next2") {
type = j_next2;
}
else if (typestring=="curspace") {
type = j_curspace;
}

View file

@ -30,9 +30,9 @@ class Translate; // Forward declaration
class HandleTpl; // Forward declaration
class ConstTpl {
public:
enum const_type { real=0, handle=1, j_start=2, j_next=3, j_curspace=4,
j_curspace_size=5, spaceid=6, j_relative=7,
j_flowref=8, j_flowref_size=9, j_flowdest=10, j_flowdest_size=11 };
enum const_type { real=0, handle=1, j_start=2, j_next=3, j_next2=4, j_curspace=5,
j_curspace_size=6, spaceid=7, j_relative=8,
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 };
private:
const_type type;

View file

@ -444,7 +444,7 @@ void DisassemblyCache::initialize(int4 min,int4 hashsize)
nextfree = 0;
hashtable = new ParserContext *[hashsize];
for(int4 i=0;i<minimumreuse;++i) {
ParserContext *pos = new ParserContext(contextcache);
ParserContext *pos = new ParserContext(contextcache,translate);
pos->initialize(75,20,constspace);
list[i] = pos;
}
@ -462,13 +462,15 @@ void DisassemblyCache::free(void)
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 cspace is the constant address space used for minting constant Varnodes
/// \param cachesize is the number of distinct ParserContext objects in this cache
/// \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;
constspace = cspace;
initialize(cachesize,windowsize); // Set default settings for the cache
@ -559,7 +561,7 @@ void Sleigh::initialize(DocumentStorage &store)
parser_cachesize = 8;
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

View file

@ -103,6 +103,7 @@ public:
/// 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.
class DisassemblyCache {
Translate *translate; ///< The Translate object that owns this cache
ContextCache *contextcache; ///< Cached values from the ContextDatabase
AddrSpace *constspace; ///< The constant address space
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 free(void); ///< Free the hash-table of ParserContexts
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
ParserContext *getParserContext(const Address &addr); ///< Get the parser for a particular Address
};

View file

@ -1789,7 +1789,7 @@ SleighCompile::SleighCompile(void)
}
/// 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
void SleighCompile::predefinedSymbols(void)
@ -1813,6 +1813,8 @@ void SleighCompile::predefinedSymbols(void)
symtab.addSymbol(startsym);
EndSymbol *endsym = new EndSymbol("inst_next",getConstantSpace());
symtab.addSymbol(endsym);
Next2Symbol *next2sym = new Next2Symbol("inst_next2",getConstantSpace());
symtab.addSymbol(next2sym);
EpsilonSymbol *epsilon = new EpsilonSymbol("epsilon",getConstantSpace());
symtab.addSymbol(epsilon);
pcode.setConstantSpace(getConstantSpace());
@ -2907,20 +2909,23 @@ ConstructTpl *SleighCompile::setResultStarVarnode(ConstructTpl *ct,StarQuality *
/// 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
/// 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
/// So we check to make sure the value expression doesn't use this symbol.
/// Because we are in the middle of parsing, the \b inst_next and \b inst_next2 values have not
/// 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 sym is the given context variable affected by the operation
/// \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)
{
vector<const PatternValue *> 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)
return false;
if (dynamic_cast<const Next2InstructionValue *>(vallist[i]) != (const Next2InstructionValue *)0)
return false;
}
// Otherwise we generate a "temporary" change to context instruction (ContextOp)
ContextField *field = (ContextField *)sym->getPatternValue();
ContextOp *op = new ContextOp(field->getStartBit(),field->getEndBit(),pe);

File diff suppressed because it is too large Load diff

View file

@ -45,8 +45,8 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_SRC_DECOMPILE_CPP_SLGHPARSE_HH_INCLUDED
# define YY_YY_SRC_DECOMPILE_CPP_SLGHPARSE_HH_INCLUDED
#ifndef YY_YY_SLGHPARSE_HH_INCLUDED
# define YY_YY_SLGHPARSE_HH_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
@ -168,9 +168,10 @@ extern int yydebug;
OPERANDSYM = 363,
STARTSYM = 364,
ENDSYM = 365,
MACROSYM = 366,
LABELSYM = 367,
SUBTABLESYM = 368
NEXT2SYM = 366,
MACROSYM = 367,
LABELSYM = 368,
SUBTABLESYM = 369
};
#endif
@ -179,7 +180,7 @@ extern int yydebug;
union YYSTYPE
{
#line 29 "src/decompile/cpp/slghparse.y" /* yacc.c:1909 */
#line 29 "slghparse.y" /* yacc.c:1909 */
char ch;
uintb *i;
@ -212,6 +213,7 @@ union YYSTYPE
SubtableSymbol *subtablesym;
StartSymbol *startsym;
EndSymbol *endsym;
Next2Symbol *next2sym;
OperandSymbol *operandsym;
VarnodeListSymbol *varlistsym;
VarnodeSymbol *varsym;
@ -223,7 +225,7 @@ union YYSTYPE
FamilySymbol *famsym;
SpecificSymbol *specsym;
#line 212 "src/decompile/cpp/slghparse.hh" /* yacc.c:1909 */
#line 214 "slghparse.hh" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
@ -236,4 +238,4 @@ extern YYSTYPE yylval;
int yyparse (void);
#endif /* !YY_YY_SRC_DECOMPILE_CPP_SLGHPARSE_HH_INCLUDED */
#endif /* !YY_YY_SLGHPARSE_HH_INCLUDED */

View file

@ -58,6 +58,7 @@
SubtableSymbol *subtablesym;
StartSymbol *startsym;
EndSymbol *endsym;
Next2Symbol *next2sym;
OperandSymbol *operandsym;
VarnodeListSymbol *varlistsym;
VarnodeSymbol *varsym;
@ -121,6 +122,7 @@
%token <operandsym> OPERANDSYM
%token <startsym> STARTSYM
%token <endsym> ENDSYM
%token <next2sym> NEXT2SYM
%token <macrosym> MACROSYM
%token <labelsym> LABELSYM
%token <subtablesym> SUBTABLESYM
@ -331,7 +333,7 @@ contextblock: { $$ = (vector<ContextChange *> *)0; }
| '[' contextlist ']' { $$ = $2; }
;
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 '(' specificsymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
| 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; }
| 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; }
| 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(); }
@ -499,6 +502,7 @@ specificsymbol: VARSYM { $$ = $1; }
| OPERANDSYM { $$ = $1; }
| STARTSYM { $$ = $1; }
| ENDSYM { $$ = $1; }
| NEXT2SYM { $$ = $1; }
;
charstring: CHAR { $$ = new string; (*$$) += $1; }
| charstring CHAR { $$ = $1; (*$$) += $2; }
@ -573,6 +577,7 @@ anysymbol: SPACESYM { $$ = $1; }
| OPERANDSYM { $$ = $1; }
| STARTSYM { $$ = $1; }
| ENDSYM { $$ = $1; }
| NEXT2SYM { $$ = $1; }
| BITSYM { $$ = $1; }
;
%%

View file

@ -165,6 +165,19 @@ public:
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 OperandSymbol;
class OperandValue : public PatternValue {

File diff suppressed because it is too large Load diff

View file

@ -429,6 +429,9 @@ int4 find_symbol(void) {
case SleighSymbol::end_symbol:
yylval.endsym = (EndSymbol *)sym;
return ENDSYM;
case SleighSymbol::next2_symbol:
yylval.next2sym = (Next2Symbol *)sym;
return NEXT2SYM;
case SleighSymbol::subtable_symbol:
yylval.subtablesym = (SubtableSymbol *)sym;
return SUBTABLESYM;

View file

@ -252,6 +252,8 @@ void SymbolTable::restoreSymbolHeader(const Element *el)
sym = new StartSymbol();
else if (el->getName() == "end_sym_head")
sym = new EndSymbol();
else if (el->getName() == "next2_sym_head")
sym = new Next2Symbol();
else if (el->getName() == "subtable_sym_head")
sym = new SubtableSymbol();
else if (el->getName() == "flowdest_sym_head")
@ -1254,6 +1256,70 @@ void EndSymbol::restoreXml(const Element *el,SleighBase *trans)
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)
{

View file

@ -25,7 +25,7 @@ class SleighSymbol {
public:
enum symbol_type { space_symbol, token_symbol, userop_symbol, value_symbol, valuemap_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,
dummy_symbol };
private:
@ -391,6 +391,23 @@ public:
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 {
AddrSpace *const_space;
public:

View file

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

View file

@ -506,8 +506,8 @@ parameters in the actual p-code operation, or an exception will be thrown during
As with a <code>&lt;callfixup&gt;</code>, the <code>&lt;body&gt;</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
via their <code>&lt;input&gt;</code> or <code>&lt;output&gt;</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>CALLOTHER</code>.
<code>inst_start</code>, <code>inst_next</code> and <code>inst_next2</code> as addresses describing the instruction
containing the <code>CALLOTHER</code>.
</para>
<example>
<programlisting>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<article>
<article id="pcoderef_title">
<info>
<title>P-Code Reference Manual</title>
<releaseinfo>Last updated September 5, 2019</releaseinfo>
@ -184,7 +184,7 @@ longer match their <emphasis>raw p-code</emphasis> form.
<para>
The core concepts of p-code are:
</para>
<sect2>
<sect2 id="pcoderef_address_space">
<title>Address Space</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="pcoderef_varnode">
<title>Varnode</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="pcoderef_pcode_operation">
<title>P-code Operation</title>
<para>
A <emphasis role="bold">p-code operation</emphasis> is the analog of a

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<article>
<article id="sleigh_title">
<info>
<title>SLEIGH</title>
<subtitle>A Language for Rapid Processor Specification</subtitle>
<pubdate>Originally published December 16, 2005</pubdate>
<releaseinfo>Last updated October 28, 2020</releaseinfo>
<releaseinfo>Last updated August 24, 2022</releaseinfo>
</info>
<simplesect>
<simplesect id="sleigh_history">
<info>
<title>History</title>
</info>
@ -36,7 +36,7 @@
</para>
</simplesect>
<simplesect>
<simplesect id="sleigh_overview">
<info>
<title>Overview</title>
</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.
</para>
</simplesect>
<sect1>
<sect1 id="sleigh_introduction">
<title>Introduction to P-Code</title>
<para>
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
respectively.
</para>
<sect2>
<sect2 id="sleigh_address_spaces">
<title>Address Spaces</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_operations">
<title>Operations</title>
<para>
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
by the compiler.
</para>
<sect2>
<sect2 id="sleigh_comments">
<title>Comments</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_identifiers">
<title>Identifiers</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_strings">
<title>Strings</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_integers">
<title>Integers</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_white_space">
<title>White Space</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_preprocessor_macros">
<title>Preprocessor Macros</title>
<para>
SLEIGH allows simple (unparameterized) macro definitions and
@ -449,7 +449,7 @@ definition of a macro from that point on in the file.
</informalexample>
</para>
</sect2>
<sect2>
<sect2 id="sleigh_conditional_compilation">
<title>Conditional Compilation</title>
<para>
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>
and <emphasis role="bold">@endif</emphasis>.
</para>
<sect3>
<sect3 id="sleigh_ifdef">
<title>@ifdef and @ifndef</title>
<para>
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).
</para>
</sect3>
<sect3>
<sect3 id="sleigh_if">
<title>@if</title>
<para>
The <emphasis role="bold">@if</emphasis> directive is followed by a
@ -519,7 +519,7 @@ is defined.
</informalexample>
</para>
</sect3>
<sect3>
<sect3 id="sleigh_else">
<title>@else and @elif</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_alignment_definition">
<title>Alignment Definition</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_space_definitions">
<title>Space Definitions</title>
<para>
The definition of an address space looks like
@ -752,7 +752,7 @@ define register offset=0 size=1
</informalexample>
</para>
</sect2>
<sect2>
<sect2 id="sleigh_bitrange_registers">
<title>Bit Range Registers</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_userdefined_operations">
<title>User-Defined Operations</title>
<para>
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
the predefined identifier <emphasis>instruction</emphasis>.
</para>
<sect2>
<sect2 id="sleigh_notes_namespaces">
<title>Notes on Namespaces</title>
<para>
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>Offset of the address of the next instruction.</td>
</tr>
<tr>
<td><code>inst_next2</code></td>
<td>Offset of the address of the instruction after the next instruction.</td>
</tr>
<tr>
<td><code>epsilon</code></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
either the address of the instruction or the address of the next
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>
identifiers are address spaces. The <emphasis>epsilon</emphasis>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_fields_family">
<title>Fields as Family Symbols</title>
<para>
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]
</para>
</sect2>
<sect2>
<sect2 id="sleigh_alternate_meanings">
<title>Attaching Alternate Meanings to Fields</title>
<para>
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
interpretations must be built up out of tables.
</para>
<sect3>
<sect3 id="sleigh_attaching_registers">
<title>Attaching Registers</title>
<para>
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.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_attaching_integers">
<title>Attaching Other Integers</title>
<para>
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 _]
</para>
</sect3>
<sect3>
<sect3 id="sleigh_attaching_names">
<title>Attaching Names</title>
<para>
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
multiple constructors into a single table are addressed in <xref linkend="sleigh_tables"/>.
</para>
<sect2>
<sect2 id="sleigh_sections_constructor">
<title>The Five Sections of a Constructor</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_table_header">
<title>The Table Header</title>
<para>
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.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_caret">
<title>The '^' character</title>
<para>
The ^ character in the display section is used to separate
@ -1505,7 +1510,7 @@ constructors <emphasis>pattern</emphasis>, the subset of possible
instruction encodings that the designer wants
to <emphasis>match</emphasis> the constructor being defined.
</para>
<sect3>
<sect3 id="sleigh_constraints">
<title>Constraints</title>
<para>
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.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_defining_operands">
<title>Defining Operands and Invoking Subtables</title>
<para>
The principle way of defining a constructor operand, left undefined
@ -1622,7 +1627,7 @@ grammars start symbol. So this link from local to global is simply a
statement of the grouping of old symbols into the new constructor.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_variable_length">
<title>Variable Length Instructions</title>
<para>
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
designer control over how tokens fit together.
</para>
<sect4>
<sect4 id="sleigh_semicolon">
<title>The ';' Operator</title>
<para>
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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_ellipsis">
<title>The '...' Operator</title>
<para>
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
dont quite match the assembly.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_empty_patterns">
<title>Empty Patterns</title>
<para>
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.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_advanced_constraints">
<title>Advanced Constraints</title>
<para>
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
varnode is <emphasis>r1</emphasis>.
</para>
<sect3>
<sect3 id="sleigh_expressions">
<title>Expressions</title>
<para>
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
within expressions to affect this order.
</para>
<sect4>
<sect4 id="sleigh_arithmetic_logical">
<title>Arithmetic, Logical and Boolean Operators</title>
<para>
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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_extension">
<title>Extension</title>
<para>
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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_truncation">
<title>Truncation</title>
<para>
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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_managed_code">
<title>Managed Code Operations</title>
<para>
SLEIGH provides basic support for instructions where encoding and context
@ -2432,7 +2437,7 @@ define pcodeop arctan;
</para>
</sect4>
</sect3>
<sect3>
<sect3 id="sleigh_statements">
<title>Statements</title>
<para>
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.
</para></warning>
</sect4>
<sect4>
<sect4 id="sleigh_storage_statements">
<title>Storage Statements</title>
<para>
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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_exports">
<title>Exports</title>
<para>
The semantic section doesnt 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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_dynamic_references">
<title>Dynamic References</title>
<para>
The only other operator allowed as part of
@ -2640,7 +2645,7 @@ addressing mode implementations from instruction semantics at higher
levels.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_branching_statements">
<title>Branching Statements</title>
<para>
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.
</para>
</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">
<title>Bit Range Assignments</title>
<para>
@ -2991,7 +3016,7 @@ each followed by a variation which corrects the error.
</informalexample>
</para>
</sect3>
<sect3>
<sect3 id="sleigh_unimplemented_semantics">
<title>Unimplemented Semantics</title>
<para>
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.
</para>
</sect3>
<sect3>
<sect3 id="sleigh_specific_symbol_trees">
<title>Specific Symbol Trees</title>
<para>
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
and p-code for these encodings by walking the trees.
</para>
<sect4>
<sect4 id="sleigh_disassembly_trees">
<title>Disassembly Trees</title>
<para>
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.
</para>
</sect4>
<sect4>
<sect4 id="sleigh_pcode_trees">
<title>P-code Trees</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_build_directives">
<title>Build Directives</title>
<para>
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.
</para>
</sect2>
<sect2>
<sect2 id="sleigh_delayslot_directives">
<title>Delay Slot Directives</title>
<para>
For processors with a pipe-lined architecture, multiple instructions
@ -3439,7 +3464,8 @@ by the condition.
<para>
Because the <emphasis role="bold">delayslot</emphasis> directive
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
following conventions for interpreting
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
disassembly action, the <emphasis>inst_next</emphasis> symbol refers
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>
</sect2>
</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
whose encodings are otherwise the same.
</para>
<sect2>
<sect2 id="sleigh_context_basic">
<title>Basic Use of Context Variables</title>
<para>
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 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=0x200 size=4 [ statusreg ]; # define context bits (if defined, size must be multiple of 4-bytes)
define token instr(16)
op=(10,15) rreg1=(7,9) sreg1=(7,9) imm=(0,6)

View file

@ -349,9 +349,10 @@ specific_symbol[String purpose] returns [SpecificSymbol symbol]
: ^(OP_IDENTIFIER s=.) {
SleighSymbol sym = pcode.findSymbol($s.getText());
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
&& sym.getType() != symbol_type.end_symbol
&& sym.getType() != symbol_type.next2_symbol
&& sym.getType() != symbol_type.operand_symbol
&& sym.getType() != symbol_type.epsilon_symbol
&& sym.getType() != symbol_type.varnode_symbol) {
@ -839,7 +840,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr]
: ^(OP_IDENTIFIER s=.) {
SleighSymbol sym = sc.findSymbol($s.getText());
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) {
OperandSymbol os = (OperandSymbol) sym;
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();
} else if(sym.getType() == symbol_type.start_symbol
|| sym.getType() == symbol_type.end_symbol
|| sym.getType() == symbol_type.next2_symbol
|| sym.getType() == symbol_type.epsilon_symbol
|| sym.getType() == symbol_type.varnode_symbol) {
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");
}
} 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 {
@ -877,9 +879,10 @@ pattern_symbol2[String purpose] returns [PatternExpression expr]
: ^(OP_IDENTIFIER s=.) {
SleighSymbol sym = sc.findSymbol($s.getText());
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
|| sym.getType() == symbol_type.end_symbol
|| sym.getType() == symbol_type.next2_symbol
|| sym.getType() == symbol_type.operand_symbol
|| sym.getType() == symbol_type.epsilon_symbol
|| sym.getType() == symbol_type.varnode_symbol) {
@ -893,7 +896,7 @@ pattern_symbol2[String purpose] returns [PatternExpression expr]
FamilySymbol z = (FamilySymbol) sym;
$expr = z.getPatternValue();
} 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 {
@ -922,7 +925,7 @@ cstatement[VectorSTL<ContextChange> r]
} else if(sym.getType() == symbol_type.context_symbol) {
ContextSymbol t = (ContextSymbol) sym;
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) {
OperandSymbol t = (OperandSymbol) sym;
@ -950,6 +953,7 @@ cstatement[VectorSTL<ContextChange> r]
|| sym.getType() == symbol_type.varnodelist_symbol
|| sym.getType() == symbol_type.start_symbol
|| sym.getType() == symbol_type.end_symbol
|| sym.getType() == symbol_type.next2_symbol
|| sym.getType() == symbol_type.operand_symbol
|| sym.getType() == symbol_type.epsilon_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());
} else if(sym.getType() != symbol_type.start_symbol
&& sym.getType() != symbol_type.end_symbol
&& sym.getType() != symbol_type.next2_symbol
&& sym.getType() != symbol_type.operand_symbol
&& sym.getType() != symbol_type.epsilon_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 {
VarnodeTpl v = ((SpecificSymbol) sym).getVarnode();
e.setOutput(find(t), v);
@ -1309,7 +1314,9 @@ jump_symbol[String purpose] returns [VarnodeTpl value]
SleighSymbol sym = pcode.findSymbol($s.getText());
if (sym == null) {
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;
$value = new VarnodeTpl(find($s), new ConstTpl(ConstTpl.const_type.j_curspace),
ss.getVarnode().getOffset(),
@ -1489,6 +1496,7 @@ expr_apply returns [Object value]
}
} else if(sym.getType() == symbol_type.start_symbol
|| sym.getType() == symbol_type.end_symbol
|| sym.getType() == symbol_type.next2_symbol
|| sym.getType() == symbol_type.operand_symbol
|| sym.getType() == symbol_type.epsilon_symbol
|| sym.getType() == symbol_type.varnode_symbol) {

View file

@ -573,6 +573,10 @@ public class SleighAssemblerBuilder implements AssemblerBuilder {
else if (sym instanceof EndSymbol) {
// 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) {
// Ignore. We don't do pcode.
}

View file

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

View file

@ -53,6 +53,7 @@ public class RecursiveDescentSolver {
new ContextFieldSolver().register(this);
new DivExpressionSolver().register(this);
new EndInstructionValueSolver().register(this);
new Next2InstructionValueSolver().register(this);
new LeftShiftExpressionSolver().register(this);
new MinusExpressionSolver().register(this);
new MultExpressionSolver().register(this);

View file

@ -78,6 +78,9 @@ public abstract class AbstractExpressionMatcher<T extends PatternExpression>
if (a instanceof EndInstructionValue) {
return true;
}
if (a instanceof Next2InstructionValue) {
return true;
}
if (a instanceof StartInstructionValue) {
return true;
}

View file

@ -54,6 +54,7 @@ public class AssemblyTreeResolver {
public static final String INST_START = "inst_start";
public static final String INST_NEXT = "inst_next";
public static final String INST_NEXT2 = "inst_next2";
protected final SleighLanguage lang;
protected final Address at;
@ -195,6 +196,8 @@ public class AssemblyTreeResolver {
return rc;
}
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);
AssemblyResolution ar = rc.backfill(SOLVER, vals);
DBG.println("Backfilled final: " + ar);

View file

@ -210,6 +210,12 @@ public class ParserWalker {
return context.getNaddr();
}
public Address getN2addr() {
if (cross_context != null)
return cross_context.getN2addr();
return context.getN2addr();
}
public AddressSpace getCurSpace() {
return context.getCurSpace();
}

View file

@ -246,7 +246,7 @@ public abstract class PcodeEmit {
if (opcode == PcodeOp.BRANCH) {
int offsetType = inputs[0].getOffset().getType();
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
offsetType == ConstTpl.J_NEXT) {
offsetType == ConstTpl.J_NEXT || offsetType == ConstTpl.J_NEXT2) {
return false;
}
OpTpl callopt = new OpTpl(PcodeOp.CALL, null, inputs);
@ -269,7 +269,7 @@ public abstract class PcodeEmit {
else if (opcode == PcodeOp.CBRANCH) {
int offsetType = inputs[0].getOffset().getType();
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
offsetType == ConstTpl.J_NEXT) {
offsetType == ConstTpl.J_NEXT || offsetType == ConstTpl.J_NEXT2) {
return false;
}
@ -326,7 +326,7 @@ public abstract class PcodeEmit {
if (opcode == PcodeOp.BRANCH || opcode == PcodeOp.CALL) {
int offsetType = inputs[0].getOffset().getType();
if (offsetType == ConstTpl.J_RELATIVE || offsetType == ConstTpl.J_START ||
offsetType == ConstTpl.J_NEXT) {
offsetType == ConstTpl.J_NEXT || offsetType == ConstTpl.J_NEXT2) {
return false;
}

View file

@ -89,7 +89,6 @@ public class SleighInstructionPrototype implements InstructionPrototype {
private final static Address[] emptyFlow = new Address[0];
private ContextCache contextCache;
// private InstructionContext instructionContextCache;
private int length;
private ConstructState rootState;
private ConstructState mnemonicState; // state for print mnemonic
@ -236,6 +235,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
if (destType == ConstTpl.J_NEXT) {
flags = BRANCH_TO_END;
}
else if (destType == ConstTpl.J_NEXT2) {
flags = JUMPOUT;
}
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) {
flags = JUMPOUT;
}
@ -674,6 +676,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
Address addr = getHandleAddr(hand, parsecontext.getAddr().getAddressSpace());
res.add(addr);
}
else if (rec.op.getInput()[0].getOffset().getType() == ConstTpl.J_NEXT2) {
res.add(parsecontext.getN2addr());
}
}
}
}

View file

@ -21,8 +21,7 @@ import ghidra.app.plugin.processors.sleigh.symbol.OperandSymbol;
import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.mem.*;
/**
*
@ -33,8 +32,9 @@ import ghidra.program.model.mem.MemoryAccessException;
public class SleighParserContext implements ParserContext {
private MemBuffer memBuffer;
private Address addr; // Address of start of instruction
private Address nextInstrAddr; // Address of next instruction
private Address addr; // Address of start of instruction (inst_start)
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 destAddr; // corresponds to inst_dest for call-fixup use
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 nAddr = address to which 'inst_next' resolves
* @param rAddr = special address associated with original call
@ -172,22 +173,99 @@ public class SleighParserContext implements ParserContext {
return handle;
}
/**
* get address of current instruction
* @return address of current instruction
*/
public Address getAddr() {
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() {
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() {
return addr.getAddressSpace();
}
/**
* Get constant address space
* @return constant address space
*/
public AddressSpace getConstSpace() {
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() {
return memBuffer;
}
@ -251,6 +329,44 @@ public class SleighParserContext implements ParserContext {
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
* @param bytestart is the index of the first byte to fetch

View file

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

View file

@ -51,6 +51,8 @@ public abstract class PatternExpression {
res = new StartInstructionValue();
else if (nm.equals("end_exp"))
res = new EndInstructionValue();
else if (nm.equals("next2_exp"))
res = new Next2InstructionValue();
else if (nm.equals("plus_exp"))
res = new PlusExpression();
else if (nm.equals("sub_exp"))

View file

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

View file

@ -19,6 +19,8 @@
*/
package ghidra.app.plugin.processors.sleigh.symbol;
import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.SleighException;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.lang.UnknownInstructionException;
@ -26,8 +28,6 @@ import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
import java.util.ArrayList;
/**
*
*
@ -152,6 +152,8 @@ public class SymbolTable {
sym = new StartSymbol();
else if (el.getName().equals("end_sym_head"))
sym = new EndSymbol();
else if (el.getName().equals("next2_sym_head"))
sym = new Next2Symbol();
else if (el.getName().equals("subtable_sym_head"))
sym = new SubtableSymbol();
else

View file

@ -39,14 +39,15 @@ public class ConstTpl {
public static final int HANDLE = 1;
public static final int J_START = 2;
public static final int J_NEXT = 3;
public static final int J_CURSPACE = 4;
public static final int J_CURSPACE_SIZE = 5;
public static final int SPACEID = 6;
public static final int J_RELATIVE = 7;
public static final int J_FLOWREF = 8;
public static final int J_FLOWREF_SIZE = 9;
public static final int J_FLOWDEST = 10;
public static final int J_FLOWDEST_SIZE = 11;
public static final int J_NEXT2 = 4;
public static final int J_CURSPACE = 5;
public static final int J_CURSPACE_SIZE = 6;
public static final int SPACEID = 7;
public static final int J_RELATIVE = 8;
public static final int J_FLOWREF = 9;
public static final int J_FLOWREF_SIZE = 10;
public static final int J_FLOWDEST = 11;
public static final int J_FLOWDEST_SIZE = 12;
public static final int V_SPACE = 0;
public static final int V_OFFSET = 1;
@ -143,6 +144,8 @@ public class ConstTpl {
return walker.getAddr().getOffset();
case J_NEXT:
return walker.getNaddr().getOffset();
case J_NEXT2:
return walker.getN2addr().getOffset();
case J_FLOWREF:
return walker.getFlowRefAddr().getOffset();
case J_FLOWREF_SIZE:
@ -315,6 +318,9 @@ public class ConstTpl {
else if (typestr.equals("next")) {
type = J_NEXT;
}
else if (typestr.equals("next2")) {
type = J_NEXT2;
}
else if (typestr.equals("curspace")) {
type = J_CURSPACE;
}
@ -379,6 +385,8 @@ public class ConstTpl {
return "[flowref_size]";
case J_NEXT:
return "[next]";
case J_NEXT2:
return "[next2]";
case J_START:
return "[start]";
case J_RELATIVE:

View file

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

View file

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

View file

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

View file

@ -20,13 +20,10 @@ import java.io.PrintStream;
import org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.FixedHandle;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.error.LowlevelError;
import ghidra.pcodeCPort.space.AddrSpace;
import ghidra.pcodeCPort.space.spacetype;
import ghidra.pcodeCPort.translate.Translate;
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
import ghidra.pcodeCPort.utils.XmlUtils;
public class ConstTpl {
@ -41,6 +38,7 @@ public class ConstTpl {
handle,
j_start,
j_next,
j_next2,
j_curspace,
j_curspace_size,
spaceid,
@ -198,138 +196,6 @@ public class ConstTpl {
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) {
type = other.type;
spaceid = other.spaceid;
@ -434,6 +300,9 @@ public class ConstTpl {
case j_next:
s.append("next\"/>");
break;
case j_next2:
s.append("next2\"/>");
break;
case j_curspace:
s.append("curspace\"/>");
break;
@ -485,6 +354,9 @@ public class ConstTpl {
else if (typestring.equals("next")) {
type = const_type.j_next;
}
else if (typestring.equals("next2")) {
type = const_type.j_next2;
}
else if (typestring.equals("curspace")) {
type = const_type.j_curspace;
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,15 @@
*/
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.util.List;
import org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.space.AddrSpace;
import ghidra.pcodeCPort.translate.Translate;
public class HandleTpl {
private ConstTpl space;
@ -114,33 +110,6 @@ public class HandleTpl {
// 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) {
space.changeHandleIndex(handmap);
size.changeHandleIndex(handmap);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,7 +17,6 @@ package ghidra.pcodeCPort.semantics;
import generic.stl.IteratorSTL;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.translate.UnimplError;
// SLEIGH specific pcode generator
@ -27,8 +25,6 @@ public abstract class PcodeBuilder {
private int labelbase;
private int labelcount;
protected ParserWalker walker;
protected abstract void dump(OpTpl op);
public PcodeBuilder(int lbcnt) {
@ -42,10 +38,6 @@ public abstract class PcodeBuilder {
return labelbase;
}
public ParserWalker getCurrentWalker() {
return walker;
}
public abstract void appendBuild(OpTpl bld, int secnum);
public abstract void appendCrossBuild(OpTpl bld, int secnum);

View file

@ -21,8 +21,6 @@ import java.util.List;
import org.jdom.Element;
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.v_field;
import ghidra.pcodeCPort.space.spacetype;
@ -129,17 +127,6 @@ public class VarnodeTpl {
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) {
boolean doesOffsetPlus = false;
int handleIndex=0;

View file

@ -289,6 +289,8 @@ public class SleighCompile extends SleighBase {
symtab.addSymbol(startsym);
EndSymbol endsym = new EndSymbol(location, "inst_next", getConstantSpace());
symtab.addSymbol(endsym);
Next2Symbol next2sym = new Next2Symbol(location, "inst_next2", getConstantSpace());
symtab.addSymbol(next2sym);
EpsilonSymbol epsilon = new EpsilonSymbol(location, "epsilon", getConstantSpace());
symtab.addSymbol(epsilon);
}
@ -1280,7 +1282,8 @@ public class SleighCompile extends SleighBase {
VectorSTL<PatternValue> vallist = new VectorSTL<>();
pe.listValues(vallist);
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;
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,6 +31,7 @@ class Yylval {
OperandSymbol operandsym;
StartSymbol startsym;
EndSymbol endsym;
Next2Symbol next2sym;
SubtableSymbol subtablesym;
MacroSymbol macrosym;
LabelSymbol labelsym;

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class AndExpression extends BinaryExpression {
public AndExpression(Location location) {
@ -33,13 +31,6 @@ public class AndExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval & rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,16 +15,15 @@
*/
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 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 {
long val;
@ -39,11 +37,6 @@ public class ConstantValue extends PatternValue {
val = v;
}
@Override
public long getValue(ParserWalker pos) {
return val;
}
@Override
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
return new TokenPattern(location);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,17 +15,16 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.translate.Translate;
import ghidra.pcodeCPort.utils.Utils;
import ghidra.pcodeCPort.utils.XmlUtils;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import org.jdom.Element;
public class ContextField extends PatternValue {
private int startbit, endbit;
@ -80,19 +78,6 @@ public class ContextField extends PatternValue {
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
public String toString() {
return "cf:{" + startbit + "," + endbit + "," + startbyte + "," + endbyte + "," + shift +

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class DivExpression extends BinaryExpression {
public DivExpression(Location location) {
@ -33,13 +31,6 @@ public class DivExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval / rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,26 +15,20 @@
*/
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 org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.translate.Translate;
import ghidra.sleigh.grammar.Location;
public class EndInstructionValue extends PatternValue {
public EndInstructionValue(Location location) {
super(location);
}
@Override
public long getValue(ParserWalker pos) {
return (pos.getNaddr().getOffset() >>> pos.getNaddr().getSpace().getScale());
}
@Override
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
return new TokenPattern(location);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,55 +16,9 @@
package ghidra.pcodeCPort.slghpatexpress;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.Utils;
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) {
int i = 0;
while (i < val.size()) {

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class LeftShiftExpression extends BinaryExpression {
public LeftShiftExpression(Location location) {
@ -33,13 +31,6 @@ public class LeftShiftExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval << rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class MinusExpression extends UnaryExpression {
public MinusExpression(Location location) {
@ -33,12 +31,6 @@ public class MinusExpression extends UnaryExpression {
super(location, u);
}
@Override
public long getValue(ParserWalker pos) {
long val = getUnary().getValue(pos);
return -val;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long val = getUnary().getSubValue(replace, listpos);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class MultExpression extends BinaryExpression {
public MultExpression(Location location) {
@ -33,13 +31,6 @@ public class MultExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval * rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

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

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class NotExpression extends UnaryExpression {
public NotExpression(Location location) {
@ -33,12 +31,6 @@ public class NotExpression extends UnaryExpression {
super(location, u);
}
@Override
public long getValue(ParserWalker pos) {
long val = getUnary().getValue(pos);
return ~val;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long val = getUnary().getSubValue(replace, listpos);

View file

@ -20,7 +20,7 @@ import java.io.PrintStream;
import org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.*;
import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.slghsymbol.*;
import ghidra.pcodeCPort.translate.Translate;
@ -79,28 +79,6 @@ public class OperandValue extends PatternValue {
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
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
OperandSymbol sym = ct.getOperand(index);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class OrExpression extends BinaryExpression {
public OrExpression(Location location) {
@ -33,13 +31,6 @@ public class OrExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval | rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,16 +15,15 @@
*/
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 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 final Location location;
@ -39,8 +37,6 @@ public abstract class PatternExpression {
refcount = 0;
}
public abstract long getValue(ParserWalker pos);
public abstract TokenPattern genMinPattern(VectorSTL<TokenPattern> ops);
public abstract void listValues(VectorSTL<PatternValue> list);
@ -91,6 +87,9 @@ public abstract class PatternExpression {
else if (nm.equals("end_exp")) {
res = new EndInstructionValue(null);
}
else if (nm.equals("next2_exp")) {
res = new Next2InstructionValue(null);
}
else if (nm.equals("plus_exp")) {
res = new PlusExpression(null);
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class PlusExpression extends BinaryExpression {
public PlusExpression(Location location) {
@ -33,13 +31,6 @@ public class PlusExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval + rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class RightShiftExpression extends BinaryExpression {
public RightShiftExpression(Location location) {
@ -33,13 +31,6 @@ public class RightShiftExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval >>> rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,26 +15,20 @@
*/
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 org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.translate.Translate;
import ghidra.sleigh.grammar.Location;
public class StartInstructionValue extends PatternValue {
public StartInstructionValue(Location location) {
super(location);
}
@Override
public long getValue(ParserWalker pos) {
return (pos.getAddr().getOffset() >> pos.getAddr().getSpace().getScale());
}
@Override
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
return new TokenPattern(location);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class SubExpression extends BinaryExpression {
public SubExpression(Location location) {
@ -33,13 +31,6 @@ public class SubExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval - rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.context.Token;
import ghidra.pcodeCPort.translate.Translate;
import ghidra.pcodeCPort.utils.Utils;
import ghidra.pcodeCPort.utils.XmlUtils;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import org.jdom.Element;
public class TokenField extends PatternValue {
private Token tok;
@ -77,21 +75,6 @@ public class TokenField extends PatternValue {
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
public TokenPattern genPattern(long val) { // Generate corresponding pattern if the
// value is forced to be val

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghpatexpress;
import java.io.PrintStream;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.MutableInt;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
public class XorExpression extends BinaryExpression {
public XorExpression(Location location) {
@ -33,13 +31,6 @@ public class XorExpression extends BinaryExpression {
super(location, l, r);
}
@Override
public long getValue(ParserWalker pos) {
long leftval = getLeft().getValue(pos);
long rightval = getRight().getValue(pos);
return leftval ^ rightval;
}
@Override
public long getSubValue(VectorSTL<Long> replace, MutableInt listpos) {
long leftval = getLeft().getSubValue(replace, listpos); // Must be left first

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,6 @@
*/
package ghidra.pcodeCPort.slghpattern;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
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
public boolean alwaysTrue() {
return (context.alwaysTrue() && instr.alwaysTrue());

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,6 @@
*/
package ghidra.pcodeCPort.slghpattern;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
import java.util.List;
@ -60,11 +57,6 @@ public class ContextPattern extends DisjointPattern {
public void shiftInstruction(int sa) {
} // do nothing
@Override
public boolean isMatch(ParserWalker pos) {
return maskvalue.isContextMatch(pos, 0);
}
@Override
public boolean alwaysTrue() {
return maskvalue.alwaysTrue();

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,6 @@
*/
package ghidra.pcodeCPort.slghpattern;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
import java.util.List;
@ -70,11 +67,6 @@ public class InstructionPattern extends DisjointPattern {
maskvalue.shift(sa);
}
@Override
public boolean isMatch(ParserWalker pos) {
return maskvalue.isInstructionMatch(pos, 0);
}
@Override
public boolean alwaysTrue() {
return maskvalue.alwaysTrue();

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,16 +15,15 @@
*/
package ghidra.pcodeCPort.slghpattern;
import generic.stl.IteratorSTL;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
import generic.stl.IteratorSTL;
import generic.stl.VectorSTL;
public class OrPattern extends Pattern {
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
// may cover the entire gamut
@Override

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,6 @@
*/
package ghidra.pcodeCPort.slghpattern;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
import org.jdom.Element;
@ -37,8 +34,6 @@ public abstract class Pattern {
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 DisjointPattern getDisjoint(int i);

View file

@ -23,7 +23,6 @@ import org.jdom.Element;
import generic.stl.IteratorSTL;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.utils.Utils;
import ghidra.pcodeCPort.utils.XmlUtils;
@ -364,36 +363,6 @@ public class PatternBlock {
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) {
s.append("<pat_block ");
s.append("offset=\"");

View file

@ -22,7 +22,7 @@ import org.jdom.Element;
import generic.stl.IteratorSTL;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.*;
import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
import ghidra.pcodeCPort.semantics.ConstructTpl;
import ghidra.pcodeCPort.semantics.HandleTpl;
@ -129,13 +129,6 @@ public class Constructor {
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) {
// 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);
@ -296,65 +289,6 @@ public class Constructor {
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
public void removeTrailingSpace() {
if ((!printpiece.empty()) && (printpiece.back().equals(" "))) {

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,12 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import ghidra.pcodeCPort.context.ParserWalkerChange;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import java.io.PrintStream;
import org.jdom.Element;
import ghidra.pcodeCPort.sleighbase.SleighBase;
// Change to context command
public abstract class ContextChange {
@ -35,8 +33,6 @@ public abstract class ContextChange {
public abstract void restoreXml(Element el, SleighBase trans);
public abstract void apply(ParserWalkerChange pos);
public void dispose() {
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,14 +15,13 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import ghidra.pcodeCPort.context.ParserWalkerChange;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.utils.*;
import java.io.PrintStream;
import org.jdom.Element;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.utils.*;
public class ContextCommit extends ContextChange {
private TripleSymbol sym;
@ -49,12 +47,6 @@ public class ContextCommit extends ContextChange {
mask = m.get();
}
@Override
public void apply(ParserWalkerChange pos) {
pos.getParserContext().addCommit(sym, num, mask, flow, pos.getPoint());
}
@Override
public void saveXml(PrintStream s) {
s.append("<commit");

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import java.io.PrintStream;
import org.jdom.Element;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.ParserWalkerChange;
import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.slghpatexpress.*;
import ghidra.pcodeCPort.utils.*;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import org.jdom.Element;
public class ContextOp extends ContextChange {
public final Location location;
@ -58,13 +56,6 @@ public class ContextOp extends ContextChange {
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
@Override
public void validate() {

View file

@ -22,10 +22,8 @@ import java.util.List;
import org.jdom.Element;
import generic.stl.*;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.error.LowlevelError;
import ghidra.pcodeCPort.slghpattern.DisjointPattern;
import ghidra.pcodeCPort.translate.BadDataError;
import ghidra.pcodeCPort.utils.XmlUtils;
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) {
s.append("<decision");
s.append(" number=\"");

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,10 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import ghidra.pcodeCPort.context.FixedHandle;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
import org.jdom.Element;
import ghidra.pcodeCPort.semantics.ConstTpl;
import ghidra.pcodeCPort.semantics.VarnodeTpl;
import ghidra.pcodeCPort.sleighbase.SleighBase;
@ -26,10 +27,6 @@ import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
import ghidra.pcodeCPort.space.AddrSpace;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import org.jdom.Element;
public class EndSymbol extends SpecificSymbol {
private AddrSpace const_space;
private PatternExpression patexp;
@ -72,21 +69,6 @@ public class EndSymbol extends SpecificSymbol {
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
public void saveXml(PrintStream s) {
s.append("<end_sym");

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,16 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import ghidra.pcodeCPort.context.FixedHandle;
import ghidra.pcodeCPort.context.ParserWalker;
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.space.AddrSpace;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import org.jdom.Element;
// Another name for zero pattern/value
public class EpsilonSymbol extends PatternlessSymbol {
@ -47,19 +44,6 @@ public class EpsilonSymbol extends PatternlessSymbol {
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
public VarnodeTpl getVarnode() {
return new VarnodeTpl(location, new ConstTpl(const_space), new ConstTpl(

View file

@ -15,11 +15,6 @@
*/
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.VarnodeTpl;
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
@ -49,15 +44,6 @@ public class FlowDestSymbol extends SpecificSymbol {
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
public VarnodeTpl getVarnode() {
ConstTpl spc = new ConstTpl(const_space);
@ -66,10 +52,4 @@ public class FlowDestSymbol extends SpecificSymbol {
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));
}
}

View file

@ -15,11 +15,6 @@
*/
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.VarnodeTpl;
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
@ -50,15 +45,6 @@ public class FlowRefSymbol extends SpecificSymbol {
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
public VarnodeTpl getVarnode() {
ConstTpl spc = new ConstTpl(const_space);
@ -67,10 +53,4 @@ public class FlowRefSymbol extends SpecificSymbol {
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));
}
}

View file

@ -22,11 +22,9 @@ import java.util.List;
import org.jdom.Element;
import generic.stl.VectorSTL;
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.sleigh.grammar.Location;
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
public symbol_type getType() {
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
public void saveXml(PrintStream s) {
s.append("<name_sym");

View file

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

View file

@ -21,7 +21,7 @@ import java.util.List;
import org.jdom.Element;
import ghidra.pcodeCPort.context.*;
import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.semantics.VarnodeTpl;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.slghpatexpress.OperandValue;
@ -168,11 +168,6 @@ public class OperandSymbol extends SpecificSymbol {
return new VarnodeTpl(location, hand, false); // Possible dynamic handle
}
@Override
public void getFixedHandle(FixedHandle hnd, ParserWalker pos) {
hnd = pos.getFixedHandle(hand);
}
@Override
public int getSize() {
if (triple != null) {
@ -181,31 +176,6 @@ public class OperandSymbol extends SpecificSymbol {
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
public void collectLocalValues(ArrayList<Long> results) {
if (triple != null) {

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +15,10 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import ghidra.pcodeCPort.context.FixedHandle;
import ghidra.pcodeCPort.context.ParserWalker;
import java.io.PrintStream;
import org.jdom.Element;
import ghidra.pcodeCPort.semantics.ConstTpl;
import ghidra.pcodeCPort.semantics.VarnodeTpl;
import ghidra.pcodeCPort.sleighbase.SleighBase;
@ -26,10 +27,6 @@ import ghidra.pcodeCPort.slghpatexpress.StartInstructionValue;
import ghidra.pcodeCPort.space.AddrSpace;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import org.jdom.Element;
public class StartSymbol extends SpecificSymbol {
private AddrSpace const_space;
private PatternExpression patexp;
@ -72,21 +69,6 @@ public class StartSymbol extends SpecificSymbol {
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
public void saveXml(PrintStream s) {
s.append("<start_sym");

View file

@ -22,7 +22,7 @@ import org.jdom.Element;
import generic.stl.IteratorSTL;
import generic.stl.VectorSTL;
import ghidra.pcodeCPort.context.*;
import ghidra.pcodeCPort.context.SleighError;
import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
import ghidra.pcodeCPort.slghpatexpress.TokenPattern;
@ -58,11 +58,6 @@ public class SubtableSymbol extends TripleSymbol {
construct.push_back(ct);
}
@Override
public Constructor resolve(ParserWalker pos) {
return decisiontree.resolve(pos);
}
public TokenPattern getPattern() {
return pattern;
}
@ -80,21 +75,11 @@ public class SubtableSymbol extends TripleSymbol {
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
public int getSize() {
return -1;
}
@Override
public void print(PrintStream s, ParserWalker pos) {
throw new SleighError("Cannot use subtable in expression", null);
}
@Override
public void collectLocalValues(ArrayList<Long> results) {
for (Constructor curConstruct : construct) {

View file

@ -15,6 +15,12 @@
*/
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.VectorSTL;
import ghidra.pcodeCPort.context.SleighError;
@ -22,12 +28,6 @@ import ghidra.pcodeCPort.sleighbase.SleighBase;
import ghidra.pcodeCPort.utils.XmlUtils;
import ghidra.sleigh.grammar.Location;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
public class SymbolTable {
private VectorSTL<SleighSymbol> symbollist = new VectorSTL<SleighSymbol>();
@ -300,6 +300,9 @@ public class SymbolTable {
else if (el.getName().equals("end_sym_head")) {
sym = new EndSymbol(location);
}
else if (el.getName().equals("next2_sym_head")) {
sym = new Next2Symbol(location);
}
else if (el.getName().equals("subtable_sym_head")) {
sym = new SubtableSymbol(location);
}

View file

@ -15,11 +15,8 @@
*/
package ghidra.pcodeCPort.slghsymbol;
import java.io.PrintStream;
import java.util.ArrayList;
import ghidra.pcodeCPort.context.FixedHandle;
import ghidra.pcodeCPort.context.ParserWalker;
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
import ghidra.sleigh.grammar.Location;
@ -36,20 +33,12 @@ public abstract class TripleSymbol extends SleighSymbol {
public abstract PatternExpression getPatternExpression();
public abstract void getFixedHandle(FixedHandle hand, ParserWalker pos);
public int getSize() {
return 0;
} // Size out of context
public abstract void print(PrintStream s, ParserWalker pos);
public void collectLocalValues(ArrayList<Long> results) {
// By default, assume symbol has no local exports
}
public Constructor resolve(ParserWalker pos) {
return null;
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,22 +15,19 @@
*/
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.util.Iterator;
import java.util.List;
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 {
private VectorSTL<Long> valuetable = new VectorSTL<Long>();
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
public void saveXml(PrintStream s) {
s.append("<valuemap_sym");

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,16 @@
*/
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.util.List;
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 {
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
public void saveXml(PrintStream s) {
s.append("<value_sym");

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,23 +15,20 @@
*/
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.util.Iterator;
import java.util.List;
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 {
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
public int getSize() {
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());
}
@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
public void saveXml(PrintStream s) {
s.append("<varlist_sym");

Some files were not shown because too many files have changed in this diff Show more