mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 23:17:03 +08:00
Merge remote-tracking branch 'origin/GP-1583_BitrangeDynamic' (Closes
#3716)
This commit is contained in:
+3
-12
@@ -18,7 +18,6 @@ package ghidra.trace.util;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.UniqueAddressFactory;
|
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.Instruction;
|
import ghidra.program.model.listing.Instruction;
|
||||||
import ghidra.program.model.listing.InstructionPcodeOverride;
|
import ghidra.program.model.listing.InstructionPcodeOverride;
|
||||||
@@ -137,13 +136,8 @@ public interface InstructionAdapterFromPrototype extends Instruction {
|
|||||||
@Override
|
@Override
|
||||||
default RefType getOperandRefType(int opIndex) {
|
default RefType getOperandRefType(int opIndex) {
|
||||||
InstructionPrototype prototype = getPrototype();
|
InstructionPrototype prototype = getPrototype();
|
||||||
Language language = prototype.getLanguage();
|
|
||||||
InstructionPcodeOverride override = new InstructionPcodeOverride(this);
|
InstructionPcodeOverride override = new InstructionPcodeOverride(this);
|
||||||
// TODO: addressFactory may need to be from program/trace (so it has cSpec)
|
return prototype.getOperandRefType(opIndex, getInstructionContext(), override);
|
||||||
UniqueAddressFactory uniqueFactory =
|
|
||||||
new UniqueAddressFactory(language.getAddressFactory(), language);
|
|
||||||
return prototype.getOperandRefType(opIndex, getInstructionContext(), override,
|
|
||||||
uniqueFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -159,14 +153,11 @@ public interface InstructionAdapterFromPrototype extends Instruction {
|
|||||||
@Override
|
@Override
|
||||||
default PcodeOp[] getPcode(boolean includeOverrides) {
|
default PcodeOp[] getPcode(boolean includeOverrides) {
|
||||||
if (!includeOverrides) {
|
if (!includeOverrides) {
|
||||||
return getPrototype().getPcode(getInstructionContext(), null, null);
|
return getPrototype().getPcode(getInstructionContext(), null);
|
||||||
}
|
}
|
||||||
InstructionPrototype prototype = getPrototype();
|
InstructionPrototype prototype = getPrototype();
|
||||||
Language language = prototype.getLanguage();
|
|
||||||
InstructionPcodeOverride override = new InstructionPcodeOverride(this);
|
InstructionPcodeOverride override = new InstructionPcodeOverride(this);
|
||||||
UniqueAddressFactory uniqueFactory =
|
return prototype.getPcode(getInstructionContext(), override);
|
||||||
new UniqueAddressFactory(language.getAddressFactory(), language);
|
|
||||||
return prototype.getPcode(getInstructionContext(), override, uniqueFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+5
-51
@@ -18,54 +18,27 @@ package ghidra.pcode.exec;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jdom.JDOMException;
|
|
||||||
import org.xml.sax.*;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.*;
|
import ghidra.app.plugin.processors.sleigh.*;
|
||||||
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
|
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
|
||||||
import ghidra.pcodeCPort.slgh_compile.PcodeParser;
|
|
||||||
import ghidra.pcodeCPort.slghsymbol.UserOpSymbol;
|
import ghidra.pcodeCPort.slghsymbol.UserOpSymbol;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.lang.UnknownInstructionException;
|
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.xml.XmlPullParser;
|
|
||||||
import ghidra.xml.XmlPullParserFactory;
|
|
||||||
|
|
||||||
public class SleighProgramCompiler {
|
public class SleighProgramCompiler {
|
||||||
private static final String EXPRESSION_SOURCE_NAME = "expression";
|
private static final String EXPRESSION_SOURCE_NAME = "expression";
|
||||||
|
|
||||||
public static PcodeParser createParser(SleighLanguage language) {
|
public static PcodeParser createParser(SleighLanguage language) {
|
||||||
String translatorTag =
|
return new PcodeParser(language, UniqueLayout.INJECT.getOffset(language));
|
||||||
language.buildTranslatorTag(language.getAddressFactory(), language.getUniqueBase(),
|
|
||||||
language.getSymbolTable());
|
|
||||||
try {
|
|
||||||
return new PcodeParser(translatorTag);
|
|
||||||
}
|
|
||||||
catch (JDOMException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConstructTpl compileTemplate(Language language, PcodeParser parser,
|
public static ConstructTpl compileTemplate(Language language, PcodeParser parser,
|
||||||
String sourceName, String text) {
|
String sourceName, String text) {
|
||||||
try {
|
ConstructTpl template =
|
||||||
// This is quite the conversion, no?
|
Objects.requireNonNull(parser.compilePcode(text, EXPRESSION_SOURCE_NAME, 1));
|
||||||
String templateXml =
|
return template;
|
||||||
PcodeParser.stringifyTemplate(
|
|
||||||
Objects.requireNonNull(parser.compilePcode(text, EXPRESSION_SOURCE_NAME, 1)));
|
|
||||||
MyErrorHandler eh = new MyErrorHandler();
|
|
||||||
XmlPullParser xmlParser =
|
|
||||||
XmlPullParserFactory.create(templateXml, EXPRESSION_SOURCE_NAME, eh, false);
|
|
||||||
ConstructTpl template = new ConstructTpl();
|
|
||||||
template.restoreXml(xmlParser, language.getAddressFactory());
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
catch (SAXException | UnknownInstructionException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PcodeOp> buildOps(Language language, ConstructTpl template)
|
public static List<PcodeOp> buildOps(Language language, ConstructTpl template)
|
||||||
@@ -125,23 +98,4 @@ public class SleighProgramCompiler {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MyErrorHandler implements ErrorHandler {
|
|
||||||
SAXParseException exc;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void warning(SAXParseException e) throws SAXException {
|
|
||||||
Msg.warn(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void error(SAXParseException e) throws SAXException {
|
|
||||||
exc = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fatalError(SAXParseException e) throws SAXException {
|
|
||||||
exc = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Uses overriding references and the symbolic propogator to resolve system calls
|
//Uses overriding references and the symbolic propogator to resolve system calls
|
||||||
//@category Analysis
|
//@category Analysis
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -31,8 +33,8 @@ import ghidra.app.util.opinion.ElfLoader;
|
|||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
@@ -127,8 +129,9 @@ public class ResolveX86orX64LinuxSyscallsScript extends GhidraScript {
|
|||||||
" to run this script");
|
" to run this script");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Address startAddr = currentProgram.getAddressFactory().getAddressSpace(
|
Address startAddr = currentProgram.getAddressFactory()
|
||||||
BasicCompilerSpec.OTHER_SPACE_NAME).getAddress(0x0L);
|
.getAddressSpace(SpaceNames.OTHER_SPACE_NAME)
|
||||||
|
.getAddress(0x0L);
|
||||||
AddUninitializedMemoryBlockCmd cmd = new AddUninitializedMemoryBlockCmd(
|
AddUninitializedMemoryBlockCmd cmd = new AddUninitializedMemoryBlockCmd(
|
||||||
SYSCALL_SPACE_NAME, null, this.getClass().getName(), startAddr,
|
SYSCALL_SPACE_NAME, null, this.getClass().getName(), startAddr,
|
||||||
SYSCALL_SPACE_LENGTH, true, true, true, false, true);
|
SYSCALL_SPACE_LENGTH, true, true, true, false, true);
|
||||||
@@ -188,8 +191,9 @@ public class ResolveX86orX64LinuxSyscallsScript extends GhidraScript {
|
|||||||
callee.setNoReturn(true);
|
callee.setNoReturn(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference ref = currentProgram.getReferenceManager().addMemoryReference(callSite,
|
Reference ref = currentProgram.getReferenceManager()
|
||||||
callTarget, overrideType, SourceType.USER_DEFINED, Reference.MNEMONIC);
|
.addMemoryReference(callSite, callTarget, overrideType, SourceType.USER_DEFINED,
|
||||||
|
Reference.MNEMONIC);
|
||||||
//overriding references must be primary to be active
|
//overriding references must be primary to be active
|
||||||
currentProgram.getReferenceManager().setPrimary(ref, true);
|
currentProgram.getReferenceManager().setPrimary(ref, true);
|
||||||
}
|
}
|
||||||
@@ -320,8 +324,10 @@ public class ResolveX86orX64LinuxSyscallsScript extends GhidraScript {
|
|||||||
for (PcodeOp op : inst.getPcode()) {
|
for (PcodeOp op : inst.getPcode()) {
|
||||||
if (op.getOpcode() == PcodeOp.CALLOTHER) {
|
if (op.getOpcode() == PcodeOp.CALLOTHER) {
|
||||||
int index = (int) op.getInput(0).getOffset();
|
int index = (int) op.getInput(0).getOffset();
|
||||||
if (inst.getProgram().getLanguage().getUserDefinedOpName(index).equals(
|
if (inst.getProgram()
|
||||||
SYSCALL_X64_CALLOTHER)) {
|
.getLanguage()
|
||||||
|
.getUserDefinedOpName(index)
|
||||||
|
.equals(SYSCALL_X64_CALLOTHER)) {
|
||||||
retVal = true;
|
retVal = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -644,9 +644,9 @@ void Architecture::restoreFromSpec(DocumentStorage &store)
|
|||||||
translate = newtrans;
|
translate = newtrans;
|
||||||
modifySpaces(newtrans); // Give architecture chance to modify spaces, before copying
|
modifySpaces(newtrans); // Give architecture chance to modify spaces, before copying
|
||||||
copySpaces(newtrans);
|
copySpaces(newtrans);
|
||||||
insertSpace( new FspecSpace(this,translate,"fspec",numSpaces()));
|
insertSpace( new FspecSpace(this,translate,numSpaces()));
|
||||||
insertSpace( new IopSpace(this,translate,"iop",numSpaces()));
|
insertSpace( new IopSpace(this,translate,numSpaces()));
|
||||||
insertSpace( new JoinSpace(this,translate,"join",numSpaces()));
|
insertSpace( new JoinSpace(this,translate,numSpaces()));
|
||||||
userops.initialize(this);
|
userops.initialize(this);
|
||||||
if (translate->getAlignment() <= 8)
|
if (translate->getAlignment() <= 8)
|
||||||
min_funcsymbol_size = translate->getAlignment();
|
min_funcsymbol_size = translate->getAlignment();
|
||||||
@@ -843,7 +843,7 @@ void Architecture::addOtherSpace(void)
|
|||||||
|
|
||||||
{
|
{
|
||||||
Scope *scope = symboltab->getGlobalScope();
|
Scope *scope = symboltab->getGlobalScope();
|
||||||
AddrSpace *otherSpace = getSpaceByName("OTHER");
|
AddrSpace *otherSpace = getSpaceByName(OtherSpace::NAME);
|
||||||
symboltab->addRange(scope,otherSpace,0,otherSpace->getHighest());
|
symboltab->addRange(scope,otherSpace,0,otherSpace->getHighest());
|
||||||
if (otherSpace->isOverlayBase()) {
|
if (otherSpace->isOverlayBase()) {
|
||||||
int4 num = numSpaces();
|
int4 num = numSpaces();
|
||||||
|
|||||||
@@ -1702,16 +1702,17 @@ int4 ParamActive::getNumUsed(void) const
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string FspecSpace::NAME = "fspec";
|
||||||
|
|
||||||
/// Constructor for the \b fspec space.
|
/// Constructor for the \b fspec space.
|
||||||
/// There is only one such space, and it is considered
|
/// There is only one such space, and it is considered
|
||||||
/// internal to the model, i.e. the Translate engine should never
|
/// internal to the model, i.e. the Translate engine should never
|
||||||
/// generate addresses in this space.
|
/// generate addresses in this space.
|
||||||
/// \param m is the associated address space manager
|
/// \param m is the associated address space manager
|
||||||
/// \param t is the associated processor translator
|
/// \param t is the associated processor translator
|
||||||
/// \param nm is the name of the space (always \b fspec)
|
|
||||||
/// \param ind is the index associated with the space
|
/// \param ind is the index associated with the space
|
||||||
FspecSpace::FspecSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind)
|
FspecSpace::FspecSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
|
||||||
: AddrSpace(m,t,IPTR_FSPEC,nm,sizeof(void *),1,ind,0,1)
|
: AddrSpace(m,t,IPTR_FSPEC,NAME,sizeof(void *),1,ind,0,1)
|
||||||
{
|
{
|
||||||
clearFlags(heritaged|does_deadcode|big_endian);
|
clearFlags(heritaged|does_deadcode|big_endian);
|
||||||
if (HOST_ENDIAN==1) // Endianness always set by host
|
if (HOST_ENDIAN==1) // Endianness always set by host
|
||||||
|
|||||||
@@ -286,12 +286,13 @@ public:
|
|||||||
/// value of the pointer
|
/// value of the pointer
|
||||||
class FspecSpace : public AddrSpace {
|
class FspecSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
FspecSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind); ///< Constructor
|
FspecSpace(AddrSpaceManager *m,const Translate *t,int4 ind); ///< Constructor
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset) const;
|
virtual void saveXmlAttributes(ostream &s,uintb offset) const;
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const;
|
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const;
|
||||||
virtual void printRaw(ostream &s,uintb offset) const;
|
virtual void printRaw(ostream &s,uintb offset) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void restoreXml(const Element *el);
|
||||||
|
static const string NAME; ///< Reserved name for the fspec space
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Basic elements of a parameter: address, data-type, properties
|
/// \brief Basic elements of a parameter: address, data-type, properties
|
||||||
|
|||||||
@@ -24,9 +24,7 @@
|
|||||||
Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,FunctionSymbol *sym,int4 sz)
|
Funcdata::Funcdata(const string &nm,Scope *scope,const Address &addr,FunctionSymbol *sym,int4 sz)
|
||||||
: baseaddr(addr),
|
: baseaddr(addr),
|
||||||
funcp(),
|
funcp(),
|
||||||
vbank(scope->getArch(),
|
vbank(scope->getArch()),
|
||||||
scope->getArch()->getUniqueSpace(),
|
|
||||||
0x10000000), // Unique space which is reused per function starts here
|
|
||||||
heritage(this),
|
heritage(this),
|
||||||
covermerge(*this)
|
covermerge(*this)
|
||||||
|
|
||||||
|
|||||||
@@ -278,8 +278,8 @@ void InjectPayloadDynamic::inject(InjectContext &context,PcodeEmit &emit) const
|
|||||||
emit.restoreXmlOp(*iter,glb->translate);
|
emit.restoreXmlOp(*iter,glb->translate);
|
||||||
}
|
}
|
||||||
|
|
||||||
PcodeInjectLibrarySleigh::PcodeInjectLibrarySleigh(Architecture *g,uintb tmpbase)
|
PcodeInjectLibrarySleigh::PcodeInjectLibrarySleigh(Architecture *g)
|
||||||
: PcodeInjectLibrary(g,tmpbase)
|
: PcodeInjectLibrary(g,g->translate->getUniqueStart(Translate::INJECT))
|
||||||
{
|
{
|
||||||
slgh = (const SleighBase *)g->translate;
|
slgh = (const SleighBase *)g->translate;
|
||||||
contextCache.glb = g;
|
contextCache.glb = g;
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ protected:
|
|||||||
virtual int4 allocateInject(const string &sourceName,const string &name,int4 type);
|
virtual int4 allocateInject(const string &sourceName,const string &name,int4 type);
|
||||||
virtual void registerInject(int4 injectid);
|
virtual void registerInject(int4 injectid);
|
||||||
public:
|
public:
|
||||||
PcodeInjectLibrarySleigh(Architecture *g,uintb tmpbase);
|
PcodeInjectLibrarySleigh(Architecture *g);
|
||||||
virtual void restoreDebug(const Element *el);
|
virtual void restoreDebug(const Element *el);
|
||||||
virtual int4 manualCallFixup(const string &name,const string &snippetstring);
|
virtual int4 manualCallFixup(const string &name,const string &snippetstring);
|
||||||
virtual int4 manualCallOtherFixup(const string &name,const string &outname,const vector<string> &inname,
|
virtual int4 manualCallOtherFixup(const string &name,const string &outname,const vector<string> &inname,
|
||||||
|
|||||||
@@ -16,16 +16,17 @@
|
|||||||
#include "op.hh"
|
#include "op.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
|
const string IopSpace::NAME = "iop";
|
||||||
|
|
||||||
/// Constructor for the \b iop space.
|
/// Constructor for the \b iop space.
|
||||||
/// There is only one such space, and it is considered internal
|
/// There is only one such space, and it is considered internal
|
||||||
/// to the model, i.e. the Translate engine should never generate
|
/// to the model, i.e. the Translate engine should never generate
|
||||||
/// addresses in this space.
|
/// addresses in this space.
|
||||||
/// \param m is the associated address space manager
|
/// \param m is the associated address space manager
|
||||||
/// \param t is the associated processor translator
|
/// \param t is the associated processor translator
|
||||||
/// \param nm is the name of the space (always \b iop)
|
|
||||||
/// \param ind is the associated index
|
/// \param ind is the associated index
|
||||||
IopSpace::IopSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind)
|
IopSpace::IopSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
|
||||||
: AddrSpace(m,t,IPTR_IOP,nm,sizeof(void *),1,ind,0,1)
|
: AddrSpace(m,t,IPTR_IOP,NAME,sizeof(void *),1,ind,0,1)
|
||||||
{
|
{
|
||||||
clearFlags(heritaged|does_deadcode|big_endian);
|
clearFlags(heritaged|does_deadcode|big_endian);
|
||||||
if (HOST_ENDIAN==1) // Endianness always set to host
|
if (HOST_ENDIAN==1) // Endianness always set to host
|
||||||
|
|||||||
@@ -31,12 +31,13 @@
|
|||||||
/// within the \b fspec space.
|
/// within the \b fspec space.
|
||||||
class IopSpace : public AddrSpace {
|
class IopSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
IopSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind);
|
IopSpace(AddrSpaceManager *m,const Translate *t,int4 ind);
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset) const { s << " space=\"iop\""; }
|
virtual void saveXmlAttributes(ostream &s,uintb offset) const { s << " space=\"iop\""; }
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const { s << " space=\"iop\""; }
|
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const { s << " space=\"iop\""; }
|
||||||
virtual void printRaw(ostream &s,uintb offset) const;
|
virtual void printRaw(ostream &s,uintb offset) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void restoreXml(const Element *el);
|
||||||
|
static const string NAME; ///< Reserved name for the iop space
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Lowest level operation of the \b p-code language
|
/// \brief Lowest level operation of the \b p-code language
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class PcodeCompile {
|
|||||||
AddrSpace *uniqspace;
|
AddrSpace *uniqspace;
|
||||||
uint4 local_labelcount; // Number of labels in current constructor
|
uint4 local_labelcount; // Number of labels in current constructor
|
||||||
bool enforceLocalKey; // Force slaspec to use 'local' keyword when defining temporary varnodes
|
bool enforceLocalKey; // Force slaspec to use 'local' keyword when defining temporary varnodes
|
||||||
virtual uintb allocateTemp(void)=0;
|
virtual uint4 allocateTemp(void)=0;
|
||||||
virtual void addSymbol(SleighSymbol *sym)=0;
|
virtual void addSymbol(SleighSymbol *sym)=0;
|
||||||
public:
|
public:
|
||||||
PcodeCompile(void) { defaultspace=(AddrSpace *)0; constantspace=(AddrSpace *)0;
|
PcodeCompile(void) { defaultspace=(AddrSpace *)0; constantspace=(AddrSpace *)0;
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public:
|
|||||||
class PcodeInjectLibrary {
|
class PcodeInjectLibrary {
|
||||||
protected:
|
protected:
|
||||||
Architecture *glb; ///< The Architecture to which the injection payloads apply
|
Architecture *glb; ///< The Architecture to which the injection payloads apply
|
||||||
uintb tempbase; ///< Offset within \e unique space for allocating temporaries within a payload
|
uint4 tempbase; ///< Offset within \e unique space for allocating temporaries within a payload
|
||||||
vector<InjectPayload *> injection; ///< Registered injections
|
vector<InjectPayload *> injection; ///< Registered injections
|
||||||
map<string,int4> callFixupMap; ///< Map of registered call-fixup names to injection id
|
map<string,int4> callFixupMap; ///< Map of registered call-fixup names to injection id
|
||||||
map<string,int4> callOtherFixupMap; ///< Map of registered callother-fixup names to injection id
|
map<string,int4> callOtherFixupMap; ///< Map of registered callother-fixup names to injection id
|
||||||
@@ -195,9 +195,9 @@ protected:
|
|||||||
/// \param injectid is the id of the InjectPayload to finalize
|
/// \param injectid is the id of the InjectPayload to finalize
|
||||||
virtual void registerInject(int4 injectid)=0;
|
virtual void registerInject(int4 injectid)=0;
|
||||||
public:
|
public:
|
||||||
PcodeInjectLibrary(Architecture *g,uintb tmpbase) { glb = g; tempbase = tmpbase; } ///< Constructor
|
PcodeInjectLibrary(Architecture *g,uint4 tmpbase) { glb = g; tempbase = tmpbase; } ///< Constructor
|
||||||
virtual ~PcodeInjectLibrary(void); ///< Destructor
|
virtual ~PcodeInjectLibrary(void); ///< Destructor
|
||||||
uintb getUniqueBase(void) const { return tempbase; } ///< Get the (current) offset for building temporary registers
|
uint4 getUniqueBase(void) const { return tempbase; } ///< Get the (current) offset for building temporary registers
|
||||||
int4 getPayloadId(int4 type,const string &nm) const; ///< Map name and type to the payload id
|
int4 getPayloadId(int4 type,const string &nm) const; ///< Map name and type to the payload id
|
||||||
InjectPayload *getPayload(int4 id) const { return injection[id]; } ///< Get the InjectPayload by id
|
InjectPayload *getPayload(int4 id) const { return injection[id]; } ///< Get the InjectPayload by id
|
||||||
string getCallFixupName(int4 injectid) const; ///< Get the call-fixup name associated with an id
|
string getCallFixupName(int4 injectid) const; ///< Get the call-fixup name associated with an id
|
||||||
|
|||||||
@@ -3236,10 +3236,10 @@ void PcodeLexer::initialize(istream *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uintb PcodeSnippet::allocateTemp(void)
|
uint4 PcodeSnippet::allocateTemp(void)
|
||||||
|
|
||||||
{ // Allocate a variable in the unique space and return the offset
|
{ // Allocate a variable in the unique space and return the offset
|
||||||
uintb res = tempbase;
|
uint4 res = tempbase;
|
||||||
tempbase += 16;
|
tempbase += 16;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,11 +71,11 @@ class PcodeSnippet : public PcodeCompile {
|
|||||||
PcodeLexer lexer;
|
PcodeLexer lexer;
|
||||||
const SleighBase *sleigh; // Language from which we get symbols
|
const SleighBase *sleigh; // Language from which we get symbols
|
||||||
SymbolTree tree; // Symbols in the local scope of the snippet (temporaries)
|
SymbolTree tree; // Symbols in the local scope of the snippet (temporaries)
|
||||||
uintb tempbase;
|
uint4 tempbase;
|
||||||
int4 errorcount;
|
int4 errorcount;
|
||||||
string firsterror;
|
string firsterror;
|
||||||
ConstructTpl *result;
|
ConstructTpl *result;
|
||||||
virtual uintb allocateTemp(void);
|
virtual uint4 allocateTemp(void);
|
||||||
virtual void addSymbol(SleighSymbol *sym);
|
virtual void addSymbol(SleighSymbol *sym);
|
||||||
public:
|
public:
|
||||||
PcodeSnippet(const SleighBase *slgh);
|
PcodeSnippet(const SleighBase *slgh);
|
||||||
@@ -87,8 +87,8 @@ public:
|
|||||||
virtual void reportWarning(const Location *loc, const string &msg) {}
|
virtual void reportWarning(const Location *loc, const string &msg) {}
|
||||||
bool hasErrors(void) const { return (errorcount != 0); }
|
bool hasErrors(void) const { return (errorcount != 0); }
|
||||||
const string getErrorMessage(void) const { return firsterror; }
|
const string getErrorMessage(void) const { return firsterror; }
|
||||||
void setUniqueBase(uintb val) { tempbase = val; }
|
void setUniqueBase(uint4 val) { tempbase = val; }
|
||||||
uintb getUniqueBase(void) const { return tempbase; }
|
uint4 getUniqueBase(void) const { return tempbase; }
|
||||||
void clear(void);
|
void clear(void);
|
||||||
int lex(void);
|
int lex(void);
|
||||||
bool parseStream(istream& s);
|
bool parseStream(istream& s);
|
||||||
|
|||||||
@@ -186,6 +186,30 @@ AddrSpace *SleighBuilder::generatePointer(const VarnodeTpl *vntpl,VarnodeData &v
|
|||||||
return hand.space;
|
return hand.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SleighBuilder::generatePointerAdd(PcodeData *op,const VarnodeTpl *vntpl)
|
||||||
|
|
||||||
|
{
|
||||||
|
uintb offsetPlus = vntpl->getOffset().getReal() & 0xffff;
|
||||||
|
if (offsetPlus == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PcodeData *nextop = cache->allocateInstruction();
|
||||||
|
nextop->opc = op->opc;
|
||||||
|
nextop->invar = op->invar;
|
||||||
|
nextop->isize = op->isize;
|
||||||
|
nextop->outvar = op->outvar;
|
||||||
|
op->isize = 2;
|
||||||
|
op->opc = CPUI_INT_ADD;
|
||||||
|
VarnodeData *newparams = op->invar = cache->allocateVarnodes(2);
|
||||||
|
newparams[0] = nextop->invar[1];
|
||||||
|
newparams[1].space = const_space; // Add in V_OFFSET_PLUS
|
||||||
|
newparams[1].offset = offsetPlus;
|
||||||
|
newparams[1].size = newparams[0].size;
|
||||||
|
op->outvar = nextop->invar + 1; // Output of ADD is input to original op
|
||||||
|
op->outvar->space = uniq_space; // Result of INT_ADD in special runtime temp
|
||||||
|
op->outvar->offset = uniq_space->getTrans()->getUniqueStart(Translate::RUNTIME_BITRANGE_EA);
|
||||||
|
}
|
||||||
|
|
||||||
void SleighBuilder::dump(OpTpl *op)
|
void SleighBuilder::dump(OpTpl *op)
|
||||||
|
|
||||||
{ // Dump on op through low-level dump interface
|
{ // Dump on op through low-level dump interface
|
||||||
@@ -211,6 +235,8 @@ void SleighBuilder::dump(OpTpl *op)
|
|||||||
loadvars[0].space = const_space;
|
loadvars[0].space = const_space;
|
||||||
loadvars[0].offset = (uintb)(uintp)spc;
|
loadvars[0].offset = (uintb)(uintp)spc;
|
||||||
loadvars[0].size = sizeof(spc);
|
loadvars[0].size = sizeof(spc);
|
||||||
|
if (vn->getOffset().getSelect() == ConstTpl::v_offset_plus)
|
||||||
|
generatePointerAdd(load_op, vn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
generateLocation(vn,invars[i]);
|
generateLocation(vn,invars[i]);
|
||||||
@@ -238,6 +264,8 @@ void SleighBuilder::dump(OpTpl *op)
|
|||||||
storevars[0].space = const_space;
|
storevars[0].space = const_space;
|
||||||
storevars[0].offset = (uintb)(uintp)spc; // space in which to store
|
storevars[0].offset = (uintb)(uintp)spc; // space in which to store
|
||||||
storevars[0].size = sizeof(spc);
|
storevars[0].size = sizeof(spc);
|
||||||
|
if (outvn->getOffset().getSelect() == ConstTpl::v_offset_plus)
|
||||||
|
generatePointerAdd(store_op,outvn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
thisop->outvar = cache->allocateVarnodes(1);
|
thisop->outvar = cache->allocateVarnodes(1);
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class SleighBuilder : public PcodeBuilder {
|
|||||||
void buildEmpty(Constructor *ct,int4 secnum);
|
void buildEmpty(Constructor *ct,int4 secnum);
|
||||||
void generateLocation(const VarnodeTpl *vntpl,VarnodeData &vn);
|
void generateLocation(const VarnodeTpl *vntpl,VarnodeData &vn);
|
||||||
AddrSpace *generatePointer(const VarnodeTpl *vntpl,VarnodeData &vn);
|
AddrSpace *generatePointer(const VarnodeTpl *vntpl,VarnodeData &vn);
|
||||||
|
void generatePointerAdd(PcodeData *op,const VarnodeTpl *vntpl);
|
||||||
void setUniqueOffset(const Address &addr); ///< Set uniquifying bits for the current instruction
|
void setUniqueOffset(const Address &addr); ///< Set uniquifying bits for the current instruction
|
||||||
public:
|
public:
|
||||||
SleighBuilder(ParserWalker *w,DisassemblyCache *dcache,PcodeCacher *pc,AddrSpace *cspc,AddrSpace *uspc,uint4 umask);
|
SleighBuilder(ParserWalker *w,DisassemblyCache *dcache,PcodeCacher *pc,AddrSpace *cspc,AddrSpace *uspc,uint4 umask);
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ PcodeInjectLibrary *SleighArchitecture::buildPcodeInjectLibrary(void)
|
|||||||
{ // Build the pcode injector based on sleigh
|
{ // Build the pcode injector based on sleigh
|
||||||
PcodeInjectLibrary *res;
|
PcodeInjectLibrary *res;
|
||||||
|
|
||||||
res = new PcodeInjectLibrarySleigh(this,translate->getUniqueBase());
|
res = new PcodeInjectLibrarySleigh(this);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
const int4 SleighBase::SLA_FORMAT_VERSION = 3;
|
const int4 SleighBase::SLA_FORMAT_VERSION = 3;
|
||||||
|
|
||||||
const uintb SleighBase::MAX_UNIQUE_SIZE = 128;
|
const uint4 SleighBase::MAX_UNIQUE_SIZE = 128;
|
||||||
|
|
||||||
int4 SourceFileIndexer::index(const string filename){
|
int4 SourceFileIndexer::index(const string filename){
|
||||||
auto it = fileToIndex.find(filename);
|
auto it = fileToIndex.find(filename);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ protected:
|
|||||||
void reregisterContext(void); ///< Reregister context fields for a new executable
|
void reregisterContext(void); ///< Reregister context fields for a new executable
|
||||||
void restoreXml(const Element *el); ///< Read a SLEIGH specification from XML
|
void restoreXml(const Element *el); ///< Read a SLEIGH specification from XML
|
||||||
public:
|
public:
|
||||||
static const uintb MAX_UNIQUE_SIZE; ///< Maximum size of a varnode in the unique space (should match value in SleighBase.java)
|
static const uint4 MAX_UNIQUE_SIZE; ///< Maximum size of a varnode in the unique space (should match value in SleighBase.java)
|
||||||
SleighBase(void); ///< Construct an uninitialized translator
|
SleighBase(void); ///< Construct an uninitialized translator
|
||||||
bool isInitialized(void) const { return (root != (SubtableSymbol *)0); } ///< Return \b true if \b this is initialized
|
bool isInitialized(void) const { return (root != (SubtableSymbol *)0); } ///< Return \b true if \b this is initialized
|
||||||
virtual ~SleighBase(void) {} ///< Destructor
|
virtual ~SleighBase(void) {} ///< Destructor
|
||||||
|
|||||||
@@ -1739,7 +1739,7 @@ void MacroBuilder::setLabel(OpTpl *op)
|
|||||||
outvec.push_back(clone);
|
outvec.push_back(clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintb SleighPcode::allocateTemp(void)
|
uint4 SleighPcode::allocateTemp(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
return compiler->getUniqueAddr();
|
return compiler->getUniqueAddr();
|
||||||
@@ -1799,14 +1799,14 @@ void SleighCompile::predefinedSymbols(void)
|
|||||||
// Some predefined symbols
|
// Some predefined symbols
|
||||||
root = new SubtableSymbol("instruction"); // Base constructors
|
root = new SubtableSymbol("instruction"); // Base constructors
|
||||||
symtab.addSymbol(root);
|
symtab.addSymbol(root);
|
||||||
insertSpace(new ConstantSpace(this,this,"const",AddrSpace::constant_space_index));
|
insertSpace(new ConstantSpace(this,this));
|
||||||
SpaceSymbol *spacesym = new SpaceSymbol(getConstantSpace()); // Constant space
|
SpaceSymbol *spacesym = new SpaceSymbol(getConstantSpace()); // Constant space
|
||||||
symtab.addSymbol(spacesym);
|
symtab.addSymbol(spacesym);
|
||||||
OtherSpace *otherSpace = new OtherSpace(this,this,"OTHER",AddrSpace::other_space_index);
|
OtherSpace *otherSpace = new OtherSpace(this,this,OtherSpace::INDEX);
|
||||||
insertSpace(otherSpace);
|
insertSpace(otherSpace);
|
||||||
spacesym = new SpaceSymbol(otherSpace);
|
spacesym = new SpaceSymbol(otherSpace);
|
||||||
symtab.addSymbol(spacesym);
|
symtab.addSymbol(spacesym);
|
||||||
insertSpace(new UniqueSpace(this,this,"unique",numSpaces(),0));
|
insertSpace(new UniqueSpace(this,this,numSpaces(),0));
|
||||||
spacesym = new SpaceSymbol(getUniqueSpace()); // Temporary register space
|
spacesym = new SpaceSymbol(getUniqueSpace()); // Temporary register space
|
||||||
symtab.addSymbol(spacesym);
|
symtab.addSymbol(spacesym);
|
||||||
StartSymbol *startsym = new StartSymbol("inst_start",getConstantSpace());
|
StartSymbol *startsym = new StartSymbol("inst_start",getConstantSpace());
|
||||||
@@ -2271,10 +2271,10 @@ void SleighCompile::reportWarning(const string &msg)
|
|||||||
/// this method does not make an assumption about the size of the requested temporary Varnode.
|
/// this method does not make an assumption about the size of the requested temporary Varnode.
|
||||||
/// It reserves a fixed amount of space and returns its starting offset.
|
/// It reserves a fixed amount of space and returns its starting offset.
|
||||||
/// \return the starting offset of the new temporary register
|
/// \return the starting offset of the new temporary register
|
||||||
uintb SleighCompile::getUniqueAddr(void)
|
uint4 SleighCompile::getUniqueAddr(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
uintb base = getUniqueBase();
|
uint4 base = getUniqueBase();
|
||||||
setUniqueBase(base + SleighBase::MAX_UNIQUE_SIZE);
|
setUniqueBase(base + SleighBase::MAX_UNIQUE_SIZE);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
@@ -3422,7 +3422,7 @@ void SleighCompile::checkUniqueAllocation(void)
|
|||||||
if (i>=tables.size()) break;
|
if (i>=tables.size()) break;
|
||||||
sym = tables[i];
|
sym = tables[i];
|
||||||
}
|
}
|
||||||
uintm ubase = getUniqueBase(); // We have to adjust the unique base
|
uint4 ubase = getUniqueBase(); // We have to adjust the unique base
|
||||||
ubase <<= sa;
|
ubase <<= sa;
|
||||||
setUniqueBase(ubase);
|
setUniqueBase(ubase);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ public:
|
|||||||
/// parser.
|
/// parser.
|
||||||
class SleighPcode : public PcodeCompile {
|
class SleighPcode : public PcodeCompile {
|
||||||
SleighCompile *compiler; ///< The main SLEIGH parser
|
SleighCompile *compiler; ///< The main SLEIGH parser
|
||||||
virtual uintb allocateTemp(void);
|
virtual uint4 allocateTemp(void);
|
||||||
virtual const Location *getLocation(SleighSymbol *sym) const;
|
virtual const Location *getLocation(SleighSymbol *sym) const;
|
||||||
virtual void reportError(const Location* loc, const string &msg);
|
virtual void reportError(const Location* loc, const string &msg);
|
||||||
virtual void reportWarning(const Location* loc, const string &msg);
|
virtual void reportWarning(const Location* loc, const string &msg);
|
||||||
@@ -332,7 +332,7 @@ public:
|
|||||||
void reportWarning(const Location *loc, const string &msg); ///< Issue a warning message with a source location
|
void reportWarning(const Location *loc, const string &msg); ///< Issue a warning message with a source location
|
||||||
int4 numErrors(void) const { return errors; } ///< Return the current number of fatal errors
|
int4 numErrors(void) const { return errors; } ///< Return the current number of fatal errors
|
||||||
|
|
||||||
uintb getUniqueAddr(void); ///< Get the next available temporary register offset
|
uint4 getUniqueAddr(void); ///< Get the next available temporary register offset
|
||||||
|
|
||||||
/// \brief Set whether unnecessary truncation and extension operators generate warnings individually
|
/// \brief Set whether unnecessary truncation and extension operators generate warnings individually
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -350,16 +350,17 @@ void AddrSpace::restoreXml(const Element *el)
|
|||||||
calcScaleMask();
|
calcScaleMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string ConstantSpace::NAME = "const";
|
||||||
|
|
||||||
|
const int4 ConstantSpace::INDEX = 0;
|
||||||
|
|
||||||
/// This constructs the unique constant space
|
/// This constructs the unique constant space
|
||||||
/// By convention, the name is always "const" and the index
|
/// By convention, the name is always "const" and the index
|
||||||
/// is always 0.
|
/// is always 0.
|
||||||
/// \param m is the associated address space manager
|
/// \param m is the associated address space manager
|
||||||
/// \param t is the associated processor translator
|
/// \param t is the associated processor translator
|
||||||
/// \param nm is the name
|
ConstantSpace::ConstantSpace(AddrSpaceManager *m,const Translate *t)
|
||||||
/// \param ind is the integer identifier
|
: AddrSpace(m,t,IPTR_CONSTANT,NAME,sizeof(uintb),1,INDEX,0,0)
|
||||||
ConstantSpace::ConstantSpace(AddrSpaceManager *m,const Translate *t,
|
|
||||||
const string &nm,int4 ind)
|
|
||||||
: AddrSpace(m,t,IPTR_CONSTANT,nm,sizeof(uintb),1,ind,0,0)
|
|
||||||
{
|
{
|
||||||
clearFlags(heritaged|does_deadcode|big_endian);
|
clearFlags(heritaged|does_deadcode|big_endian);
|
||||||
if (HOST_ENDIAN==1) // Endianness always matches host
|
if (HOST_ENDIAN==1) // Endianness always matches host
|
||||||
@@ -390,16 +391,18 @@ void ConstantSpace::restoreXml(const Element *el)
|
|||||||
throw LowlevelError("Should never restore the constant space from XML");
|
throw LowlevelError("Should never restore the constant space from XML");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string OtherSpace::NAME = "OTHER";
|
||||||
|
|
||||||
|
const int4 OtherSpace::INDEX = 1;
|
||||||
|
|
||||||
/// Construct the \b other space, which is automatically constructed
|
/// Construct the \b other space, which is automatically constructed
|
||||||
/// by the compiler, and is only constructed once. The name should
|
/// by the compiler, and is only constructed once. The name should
|
||||||
/// always by \b OTHER.
|
/// always by \b OTHER.
|
||||||
/// \param m is the associated address space manager
|
/// \param m is the associated address space manager
|
||||||
/// \param t is the associated processor translator
|
/// \param t is the associated processor translator
|
||||||
/// \param nm is the name of the space
|
|
||||||
/// \param ind is the integer identifier
|
/// \param ind is the integer identifier
|
||||||
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t,
|
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
|
||||||
const string &nm,int4 ind)
|
: AddrSpace(m,t,IPTR_PROCESSOR,NAME,sizeof(uintb),1,INDEX,0,0)
|
||||||
: AddrSpace(m,t,IPTR_PROCESSOR,nm,sizeof(uintb),1,ind,0,0)
|
|
||||||
{
|
{
|
||||||
clearFlags(heritaged|does_deadcode);
|
clearFlags(heritaged|does_deadcode);
|
||||||
setFlags(is_otherspace);
|
setFlags(is_otherspace);
|
||||||
@@ -426,17 +429,19 @@ void OtherSpace::saveXml(ostream &s) const
|
|||||||
s << "/>\n";
|
s << "/>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string UniqueSpace::NAME = "unique";
|
||||||
|
|
||||||
|
const uint4 UniqueSpace::SIZE = 4;
|
||||||
|
|
||||||
/// This is the constructor for the \b unique space, which is
|
/// This is the constructor for the \b unique space, which is
|
||||||
/// automatically constructed by the analysis engine, and
|
/// automatically constructed by the analysis engine, and
|
||||||
/// constructed only once. The name should always be \b unique.
|
/// constructed only once. The name should always be \b unique.
|
||||||
/// \param m is the associated address space manager
|
/// \param m is the associated address space manager
|
||||||
/// \param t is the associated processor translator
|
/// \param t is the associated processor translator
|
||||||
/// \param nm is the name of the space
|
|
||||||
/// \param ind is the integer identifier
|
/// \param ind is the integer identifier
|
||||||
/// \param fl are attribute flags (currently unused)
|
/// \param fl are attribute flags (currently unused)
|
||||||
UniqueSpace::UniqueSpace(AddrSpaceManager *m,const Translate *t,const string &nm,
|
UniqueSpace::UniqueSpace(AddrSpaceManager *m,const Translate *t,int4 ind,uint4 fl)
|
||||||
int4 ind,uint4 fl)
|
: AddrSpace(m,t,IPTR_INTERNAL,NAME,SIZE,1,ind,fl,0)
|
||||||
: AddrSpace(m,t,IPTR_INTERNAL,nm,sizeof(uintm),1,ind,fl,0)
|
|
||||||
{
|
{
|
||||||
setFlags(hasphysical);
|
setFlags(hasphysical);
|
||||||
}
|
}
|
||||||
@@ -455,14 +460,15 @@ void UniqueSpace::saveXml(ostream &s) const
|
|||||||
s << "/>\n";
|
s << "/>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string JoinSpace::NAME = "join";
|
||||||
|
|
||||||
/// This is the constructor for the \b join space, which is automatically constructed by the
|
/// This is the constructor for the \b join space, which is automatically constructed by the
|
||||||
/// analysis engine, and constructed only once. The name should always be \b join.
|
/// analysis engine, and constructed only once. The name should always be \b join.
|
||||||
/// \param m is the associated address space manager
|
/// \param m is the associated address space manager
|
||||||
/// \param t is the associated processor translator
|
/// \param t is the associated processor translator
|
||||||
/// \param nm is the name of the space
|
|
||||||
/// \param ind is the integer identifier
|
/// \param ind is the integer identifier
|
||||||
JoinSpace::JoinSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind)
|
JoinSpace::JoinSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
|
||||||
: AddrSpace(m,t,IPTR_JOIN,nm,sizeof(uintm),1,ind,0,0)
|
: AddrSpace(m,t,IPTR_JOIN,NAME,sizeof(uintm),1,ind,0,0)
|
||||||
{
|
{
|
||||||
// This is a virtual space
|
// This is a virtual space
|
||||||
// setFlags(hasphysical);
|
// setFlags(hasphysical);
|
||||||
|
|||||||
@@ -86,10 +86,6 @@ public:
|
|||||||
is_otherspace = 512, ///< Quick check for the OtherSpace derived class
|
is_otherspace = 512, ///< Quick check for the OtherSpace derived class
|
||||||
has_nearpointers = 0x400 ///< Does there exist near pointers into this space
|
has_nearpointers = 0x400 ///< Does there exist near pointers into this space
|
||||||
};
|
};
|
||||||
enum {
|
|
||||||
constant_space_index = 0, ///< Reserved index for the constant space
|
|
||||||
other_space_index = 1 ///< Reserved index for the other space
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
|
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
|
||||||
AddrSpaceManager *manage; ///< Manager for processor using this space
|
AddrSpaceManager *manage; ///< Manager for processor using this space
|
||||||
@@ -178,19 +174,23 @@ public:
|
|||||||
/// by the offset field of an Address.
|
/// by the offset field of an Address.
|
||||||
class ConstantSpace : public AddrSpace {
|
class ConstantSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
ConstantSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind); ///< Only constructor
|
ConstantSpace(AddrSpaceManager *m,const Translate *t); ///< Only constructor
|
||||||
virtual void printRaw(ostream &s,uintb offset) const;
|
virtual void printRaw(ostream &s,uintb offset) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void restoreXml(const Element *el);
|
||||||
|
static const string NAME; // Reserved name for the address space
|
||||||
|
static const int4 INDEX; // Reserved index for constant space
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Special AddrSpace for special/user-defined address spaces
|
/// \brief Special AddrSpace for special/user-defined address spaces
|
||||||
class OtherSpace : public AddrSpace {
|
class OtherSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
OtherSpace(AddrSpaceManager *m, const Translate *t, const string &nm, int4 ind); ///< Constructor
|
OtherSpace(AddrSpaceManager *m, const Translate *t, int4 ind); ///< Constructor
|
||||||
OtherSpace(AddrSpaceManager *m, const Translate *t); ///< For use with restoreXml
|
OtherSpace(AddrSpaceManager *m, const Translate *t); ///< For use with restoreXml
|
||||||
virtual void printRaw(ostream &s, uintb offset) const;
|
virtual void printRaw(ostream &s, uintb offset) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
|
static const string NAME; // Reserved name for the address space
|
||||||
|
static const int4 INDEX; // Reserved index for the other space
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief The pool of temporary storage registers
|
/// \brief The pool of temporary storage registers
|
||||||
@@ -204,9 +204,11 @@ public:
|
|||||||
/// \b unique.
|
/// \b unique.
|
||||||
class UniqueSpace : public AddrSpace {
|
class UniqueSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
UniqueSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,uint4 fl); ///< Constructor
|
UniqueSpace(AddrSpaceManager *m,const Translate *t,int4 ind,uint4 fl); ///< Constructor
|
||||||
UniqueSpace(AddrSpaceManager *m,const Translate *t); ///< For use with restoreXml
|
UniqueSpace(AddrSpaceManager *m,const Translate *t); ///< For use with restoreXml
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
|
static const string NAME; ///< Reserved name for the unique space
|
||||||
|
static const uint4 SIZE; ///< Fixed size (in bytes) for unique space offsets
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief The pool of logically joined variables
|
/// \brief The pool of logically joined variables
|
||||||
@@ -219,7 +221,7 @@ public:
|
|||||||
/// have an absolute meaning, the database may vary what offset is assigned to what set of pieces.
|
/// have an absolute meaning, the database may vary what offset is assigned to what set of pieces.
|
||||||
class JoinSpace : public AddrSpace {
|
class JoinSpace : public AddrSpace {
|
||||||
public:
|
public:
|
||||||
JoinSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind);
|
JoinSpace(AddrSpaceManager *m,const Translate *t,int4 ind);
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset) const;
|
virtual void saveXmlAttributes(ostream &s,uintb offset) const;
|
||||||
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const;
|
virtual void saveXmlAttributes(ostream &s,uintb offset,int4 size) const;
|
||||||
virtual uintb restoreXmlAttributes(const Element *el,uint4 &size) const;
|
virtual uintb restoreXmlAttributes(const Element *el,uint4 &size) const;
|
||||||
@@ -227,6 +229,7 @@ public:
|
|||||||
virtual uintb read(const string &s,int4 &size) const;
|
virtual uintb read(const string &s,int4 &size) const;
|
||||||
virtual void saveXml(ostream &s) const;
|
virtual void saveXml(ostream &s) const;
|
||||||
virtual void restoreXml(const Element *el);
|
virtual void restoreXml(const Element *el);
|
||||||
|
static const string NAME; ///< Reserved name for the join space
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief An overlay space.
|
/// \brief An overlay space.
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
|
|||||||
|
|
||||||
{
|
{
|
||||||
// The first space should always be the constant space
|
// The first space should always be the constant space
|
||||||
insertSpace(new ConstantSpace(this,trans,"const",AddrSpace::constant_space_index));
|
insertSpace(new ConstantSpace(this,trans));
|
||||||
|
|
||||||
string defname(el->getAttributeValue("defaultspace"));
|
string defname(el->getAttributeValue("defaultspace"));
|
||||||
const List &list(el->getChildren());
|
const List &list(el->getChildren());
|
||||||
@@ -302,14 +302,14 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
|
|||||||
bool duplicateId = false;
|
bool duplicateId = false;
|
||||||
switch(spc->getType()) {
|
switch(spc->getType()) {
|
||||||
case IPTR_CONSTANT:
|
case IPTR_CONSTANT:
|
||||||
if (spc->getName() != "const")
|
if (spc->getName() != ConstantSpace::NAME)
|
||||||
nameTypeMismatch = true;
|
nameTypeMismatch = true;
|
||||||
if (spc->index != AddrSpace::constant_space_index)
|
if (spc->index != ConstantSpace::INDEX)
|
||||||
throw LowlevelError("const space must be assigned index 0");
|
throw LowlevelError("const space must be assigned index 0");
|
||||||
constantspace = spc;
|
constantspace = spc;
|
||||||
break;
|
break;
|
||||||
case IPTR_INTERNAL:
|
case IPTR_INTERNAL:
|
||||||
if (spc->getName() != "unique")
|
if (spc->getName() != UniqueSpace::NAME)
|
||||||
nameTypeMismatch = true;
|
nameTypeMismatch = true;
|
||||||
if (uniqspace != (AddrSpace *)0)
|
if (uniqspace != (AddrSpace *)0)
|
||||||
duplicateName = true;
|
duplicateName = true;
|
||||||
@@ -323,7 +323,7 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
|
|||||||
fspecspace = spc;
|
fspecspace = spc;
|
||||||
break;
|
break;
|
||||||
case IPTR_JOIN:
|
case IPTR_JOIN:
|
||||||
if (spc->getName() != "join")
|
if (spc->getName() != JoinSpace::NAME)
|
||||||
nameTypeMismatch = true;
|
nameTypeMismatch = true;
|
||||||
if (joinspace != (AddrSpace *)0)
|
if (joinspace != (AddrSpace *)0)
|
||||||
duplicateName = true;
|
duplicateName = true;
|
||||||
@@ -349,7 +349,7 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
|
|||||||
ospc->getBaseSpace()->setFlags(AddrSpace::overlaybase); // Mark the base as being overlayed
|
ospc->getBaseSpace()->setFlags(AddrSpace::overlaybase); // Mark the base as being overlayed
|
||||||
}
|
}
|
||||||
else if (spc->isOtherSpace()) {
|
else if (spc->isOtherSpace()) {
|
||||||
if (spc->index != AddrSpace::other_space_index)
|
if (spc->index != OtherSpace::INDEX)
|
||||||
throw LowlevelError("OTHER space must be assigned index 1");
|
throw LowlevelError("OTHER space must be assigned index 1");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -292,21 +292,32 @@ public:
|
|||||||
/// with the processor. In particular, it knows about all the
|
/// with the processor. In particular, it knows about all the
|
||||||
/// address spaces, registers, and spacebases for the processor.
|
/// address spaces, registers, and spacebases for the processor.
|
||||||
class Translate : public AddrSpaceManager {
|
class Translate : public AddrSpaceManager {
|
||||||
|
public:
|
||||||
|
/// Tagged addresses in the \e unique address space
|
||||||
|
enum UniqueLayout {
|
||||||
|
RUNTIME_BOOLEAN_INVERT=0, ///< Location of the runtime temporary for boolean inversion
|
||||||
|
RUNTIME_RETURN_LOCATION=0x80, ///< Location of the runtime temporary storing the return value
|
||||||
|
RUNTIME_BITRANGE_EA=0x100, ///< Location of the runtime temporary for storing an effective address
|
||||||
|
INJECT=0x200, ///< Range of temporaries for use in compiling p-code snippets
|
||||||
|
ANALYSIS=0x10000000 ///< Range of temporaries for use during decompiler analysis
|
||||||
|
};
|
||||||
|
private:
|
||||||
bool target_isbigendian; ///< \b true if the general endianness of the process is big endian
|
bool target_isbigendian; ///< \b true if the general endianness of the process is big endian
|
||||||
uintm unique_base; ///< Starting offset into unique space
|
uint4 unique_base; ///< Starting offset into unique space
|
||||||
protected:
|
protected:
|
||||||
int4 alignment; ///< Byte modulo on which instructions are aligned
|
int4 alignment; ///< Byte modulo on which instructions are aligned
|
||||||
vector<FloatFormat> floatformats; ///< Floating point formats utilized by the processor
|
vector<FloatFormat> floatformats; ///< Floating point formats utilized by the processor
|
||||||
|
|
||||||
void setBigEndian(bool val); ///< Set general endianness to \b big if val is \b true
|
void setBigEndian(bool val); ///< Set general endianness to \b big if val is \b true
|
||||||
void setUniqueBase(uintm val); ///< Set the base offset for new temporary registers
|
void setUniqueBase(uint4 val); ///< Set the base offset for new temporary registers
|
||||||
public:
|
public:
|
||||||
Translate(void); ///< Constructor for the translator
|
Translate(void); ///< Constructor for the translator
|
||||||
void setDefaultFloatFormats(void); ///< If no explicit float formats, set up default formats
|
void setDefaultFloatFormats(void); ///< If no explicit float formats, set up default formats
|
||||||
bool isBigEndian(void) const; ///< Is the processor big endian?
|
bool isBigEndian(void) const; ///< Is the processor big endian?
|
||||||
const FloatFormat *getFloatFormat(int4 size) const; ///< Get format for a particular floating point encoding
|
const FloatFormat *getFloatFormat(int4 size) const; ///< Get format for a particular floating point encoding
|
||||||
int4 getAlignment(void) const; ///< Get the instruction alignment for the processor
|
int4 getAlignment(void) const; ///< Get the instruction alignment for the processor
|
||||||
uintm getUniqueBase(void) const; ///< Get the base offset for new temporary registers
|
uint4 getUniqueBase(void) const; ///< Get the base offset for new temporary registers
|
||||||
|
uint4 getUniqueStart(UniqueLayout layout) const; ///< Get a tagged address within the \e unique space
|
||||||
|
|
||||||
/// \brief Initialize the translator given XML configuration documents
|
/// \brief Initialize the translator given XML configuration documents
|
||||||
///
|
///
|
||||||
@@ -551,7 +562,7 @@ inline void Translate::setBigEndian(bool val) {
|
|||||||
/// for the pcode engine, and sets the base offset where registers
|
/// for the pcode engine, and sets the base offset where registers
|
||||||
/// created by the simplification process can start being allocated.
|
/// created by the simplification process can start being allocated.
|
||||||
/// \param val is the boundary offset
|
/// \param val is the boundary offset
|
||||||
inline void Translate::setUniqueBase(uintm val) {
|
inline void Translate::setUniqueBase(uint4 val) {
|
||||||
if (val>unique_base) unique_base = val;
|
if (val>unique_base) unique_base = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,14 +584,19 @@ inline int4 Translate::getAlignment(void) const {
|
|||||||
return alignment;
|
return alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This routine gets the base offset, within the \e unique
|
/// Return the first offset within the \e unique space after the range statically reserved by Translate.
|
||||||
/// temporary register space, where new registers can be
|
/// This is generally the starting offset where dynamic temporary registers can start to be allocated.
|
||||||
/// allocated for the simplification process. Locations before
|
|
||||||
/// this offset are reserved registers needed by the pcode
|
|
||||||
/// translation engine.
|
|
||||||
/// \return the first allocatable offset
|
/// \return the first allocatable offset
|
||||||
inline uintm Translate::getUniqueBase(void) const {
|
inline uint4 Translate::getUniqueBase(void) const {
|
||||||
return unique_base;
|
return unique_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Regions of the \e unique space are reserved for specific uses. We select the start of a specific
|
||||||
|
/// region based on the given tag.
|
||||||
|
/// \param layout is the given tag
|
||||||
|
/// \return the absolute offset into the \e unique space
|
||||||
|
inline uint4 Translate::getUniqueStart(UniqueLayout layout) const {
|
||||||
|
return (layout != ANALYSIS) ? layout + unique_base : layout;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -852,17 +852,15 @@ void Varnode::printRaw(ostream &s,const Varnode *vn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \param m is the underlying address space manager
|
/// \param m is the underlying address space manager
|
||||||
/// \param uspace is the \e unique space
|
VarnodeBank::VarnodeBank(AddrSpaceManager *m)
|
||||||
/// \param ubase is the base offset for allocating temporaries
|
|
||||||
VarnodeBank::VarnodeBank(AddrSpaceManager *m,AddrSpace *uspace,uintm ubase)
|
|
||||||
: searchvn(0,Address(Address::m_minimal),(Datatype *)0)
|
: searchvn(0,Address(Address::m_minimal),(Datatype *)0)
|
||||||
|
|
||||||
{
|
{
|
||||||
manage = m;
|
manage = m;
|
||||||
searchvn.flags = Varnode::input; // searchvn is always an input varnode of size 0
|
searchvn.flags = Varnode::input; // searchvn is always an input varnode of size 0
|
||||||
uniq_space = uspace;
|
uniq_space = m->getUniqueSpace();
|
||||||
uniqbase = ubase;
|
uniqbase = uniq_space->getTrans()->getUniqueStart(Translate::ANALYSIS);
|
||||||
uniqid = ubase;
|
uniqid = uniqbase;
|
||||||
create_index = 0;
|
create_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ class VarnodeBank {
|
|||||||
mutable Varnode searchvn; ///< Template varnode for searching trees
|
mutable Varnode searchvn; ///< Template varnode for searching trees
|
||||||
Varnode *xref(Varnode *vn); ///< Insert a Varnode into the sorted lists
|
Varnode *xref(Varnode *vn); ///< Insert a Varnode into the sorted lists
|
||||||
public:
|
public:
|
||||||
VarnodeBank(AddrSpaceManager *m,AddrSpace *uspace,uintm ubase); ///< Construct the container
|
VarnodeBank(AddrSpaceManager *m); ///< Construct the container
|
||||||
void clear(void); ///< Clear out all Varnodes and reset counters
|
void clear(void); ///< Clear out all Varnodes and reset counters
|
||||||
~VarnodeBank(void) { clear(); } ///< Destructor
|
~VarnodeBank(void) { clear(); } ///< Destructor
|
||||||
int4 numVarnodes(void) const { return loc_tree.size(); } ///< Get number of Varnodes \b this contains
|
int4 numVarnodes(void) const { return loc_tree.size(); } ///< Get number of Varnodes \b this contains
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.io.*;
|
|||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
|
import ghidra.app.plugin.processors.sleigh.UniqueLayout;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
import ghidra.program.model.address.AddressFactory;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
@@ -212,9 +213,7 @@ public class DecompInterface {
|
|||||||
DecompileProcessFactory.release(decompProcess);
|
DecompileProcessFactory.release(decompProcess);
|
||||||
decompProcess = DecompileProcessFactory.get();
|
decompProcess = DecompileProcessFactory.get();
|
||||||
}
|
}
|
||||||
// use static uniqueBase since we don't know how many dynamically generated
|
long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage);
|
||||||
// variables Ghidra may add to the language/compile-spec uniqueBase
|
|
||||||
long uniqueBase = 0x10000000;
|
|
||||||
String tspec =
|
String tspec =
|
||||||
pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null);
|
pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null);
|
||||||
String coretypes = dtmanage.buildCoreTypes();
|
String coretypes = dtmanage.buildCoreTypes();
|
||||||
|
|||||||
+1
-4
@@ -67,7 +67,6 @@ public class DecompileCallback {
|
|||||||
private DecompileDebug debug;
|
private DecompileDebug debug;
|
||||||
private Program program;
|
private Program program;
|
||||||
private Listing listing;
|
private Listing listing;
|
||||||
private UniqueAddressFactory uniqueFactory;
|
|
||||||
private Function cachedFunction;
|
private Function cachedFunction;
|
||||||
private AddressSet undefinedBody;
|
private AddressSet undefinedBody;
|
||||||
private Address funcEntry;
|
private Address funcEntry;
|
||||||
@@ -88,7 +87,6 @@ public class DecompileCallback {
|
|||||||
PcodeDataTypeManager dt) {
|
PcodeDataTypeManager dt) {
|
||||||
program = prog;
|
program = prog;
|
||||||
pcodelanguage = language;
|
pcodelanguage = language;
|
||||||
uniqueFactory = new UniqueAddressFactory(prog.getAddressFactory(), language);
|
|
||||||
pcodecompilerspec = compilerSpec;
|
pcodecompilerspec = compilerSpec;
|
||||||
listing = program.getListing();
|
listing = program.getListing();
|
||||||
addrfactory = program.getAddressFactory();
|
addrfactory = program.getAddressFactory();
|
||||||
@@ -138,7 +136,6 @@ public class DecompileCallback {
|
|||||||
if (pseudoDisassembler != null) {
|
if (pseudoDisassembler != null) {
|
||||||
pseudoDisassembler.resetDisassemblerContext();
|
pseudoDisassembler.resetDisassemblerContext();
|
||||||
}
|
}
|
||||||
uniqueFactory.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -294,7 +291,7 @@ public class DecompileCallback {
|
|||||||
|
|
||||||
PackedBytes pcode = instr.getPrototype()
|
PackedBytes pcode = instr.getPrototype()
|
||||||
.getPcodePacked(instr.getInstructionContext(),
|
.getPcodePacked(instr.getInstructionContext(),
|
||||||
new InstructionPcodeOverride(instr), uniqueFactory);
|
new InstructionPcodeOverride(instr));
|
||||||
|
|
||||||
return pcode;
|
return pcode;
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-44
@@ -49,10 +49,10 @@ public abstract class PcodeEmit {
|
|||||||
private Address defaultFallAddress;
|
private Address defaultFallAddress;
|
||||||
private Address fallOverride;
|
private Address fallOverride;
|
||||||
private int fallOffset;
|
private int fallOffset;
|
||||||
private UniqueAddressFactory uniqueFactory;
|
private SleighLanguage language;
|
||||||
|
private AddressFactory addressFactory;
|
||||||
private VarnodeData outcache;
|
private VarnodeData outcache;
|
||||||
protected VarnodeData[] incache;
|
protected VarnodeData[] incache;
|
||||||
private VarnodeData[] dyncache;
|
|
||||||
protected ArrayList<Integer> labeldef = null;
|
protected ArrayList<Integer> labeldef = null;
|
||||||
protected int numOps = 0; // Number of PcodeOps generated so far
|
protected int numOps = 0; // Number of PcodeOps generated so far
|
||||||
private int labelbase = 0;
|
private int labelbase = 0;
|
||||||
@@ -76,10 +76,9 @@ public abstract class PcodeEmit {
|
|||||||
* @param ictx is the InstructionContext interface to resolve requests for context
|
* @param ictx is the InstructionContext interface to resolve requests for context
|
||||||
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
||||||
* @param override required if pcode overrides are to be utilized
|
* @param override required if pcode overrides are to be utilized
|
||||||
* @param uniqueFactory required when override specified or if overlay normalization is required
|
|
||||||
*/
|
*/
|
||||||
public PcodeEmit(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
public PcodeEmit(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
||||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
PcodeOverride override) {
|
||||||
this.walker = walk;
|
this.walker = walk;
|
||||||
this.parsercontext = walk.getParserContext();
|
this.parsercontext = walk.getParserContext();
|
||||||
this.instcontext = ictx;
|
this.instcontext = ictx;
|
||||||
@@ -88,30 +87,27 @@ public abstract class PcodeEmit {
|
|||||||
AddressSpace myspace = startAddress.getAddressSpace();
|
AddressSpace myspace = startAddress.getAddressSpace();
|
||||||
if (myspace.isOverlaySpace()) {
|
if (myspace.isOverlaySpace()) {
|
||||||
overlayspace = myspace;
|
overlayspace = myspace;
|
||||||
startAddress = ((OverlayAddressSpace) myspace).getOverlayedSpace().getAddress(
|
startAddress = ((OverlayAddressSpace) myspace).getOverlayedSpace()
|
||||||
startAddress.getOffset());
|
.getAddress(startAddress.getOffset());
|
||||||
}
|
}
|
||||||
this.fallOffset = fallOffset;
|
this.fallOffset = fallOffset;
|
||||||
this.uniqueFactory = uniqueFactory;
|
|
||||||
this.override = override;
|
this.override = override;
|
||||||
SleighInstructionPrototype sleighproto = parsercontext.getPrototype();
|
SleighInstructionPrototype sleighproto = parsercontext.getPrototype();
|
||||||
if (sleighproto != null) {
|
if (sleighproto != null) {
|
||||||
SleighLanguage sleighlang = (SleighLanguage) sleighproto.getLanguage();
|
language = (SleighLanguage) sleighproto.getLanguage();
|
||||||
uniq_space = sleighlang.getAddressFactory().getUniqueSpace();
|
addressFactory = language.getAddressFactory();
|
||||||
uniquemask = sleighlang.getUniqueAllocationMask();
|
uniq_space = addressFactory.getUniqueSpace();
|
||||||
|
uniquemask = language.getUniqueAllocationMask();
|
||||||
uniqueoffset = (startAddress.getOffset() & uniquemask) << 4;
|
uniqueoffset = (startAddress.getOffset() & uniquemask) << 4;
|
||||||
}
|
}
|
||||||
else { // This can happen for CallFixup snippets, but these don't need their temporary vars patched up
|
else { // This can happen for CallFixup snippets, but these don't need their temporary vars patched up
|
||||||
|
language = null;
|
||||||
uniq_space = null;
|
uniq_space = null;
|
||||||
uniquemask = 0;
|
uniquemask = 0;
|
||||||
uniqueoffset = 0;
|
uniqueoffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (override != null) {
|
if (override != null) {
|
||||||
if (uniqueFactory == null) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"uniqueFactory required when override is specified");
|
|
||||||
}
|
|
||||||
flowOverride = override.getFlowOverride();
|
flowOverride = override.getFlowOverride();
|
||||||
if (flowOverride == FlowOverride.NONE) {
|
if (flowOverride == FlowOverride.NONE) {
|
||||||
flowOverride = null;
|
flowOverride = null;
|
||||||
@@ -131,7 +127,6 @@ public abstract class PcodeEmit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
incache = new VarnodeData[8]; // Maximum number of inputs
|
incache = new VarnodeData[8]; // Maximum number of inputs
|
||||||
dyncache = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUniqueOffset(Address addr) {
|
private void setUniqueOffset(Address addr) {
|
||||||
@@ -159,7 +154,7 @@ public abstract class PcodeEmit {
|
|||||||
*/
|
*/
|
||||||
private void setLabel(OpTpl op) {
|
private void setLabel(OpTpl op) {
|
||||||
if (labeldef == null) {
|
if (labeldef == null) {
|
||||||
labeldef = new ArrayList<Integer>();
|
labeldef = new ArrayList<>();
|
||||||
}
|
}
|
||||||
int labelindex = (int) op.getInput()[0].getOffset().getReal() + labelbase;
|
int labelindex = (int) op.getInput()[0].getOffset().getReal() + labelbase;
|
||||||
while (labeldef.size() <= labelindex) {
|
while (labeldef.size() <= labelindex) {
|
||||||
@@ -282,9 +277,11 @@ public abstract class PcodeEmit {
|
|||||||
// CALL <dest>
|
// CALL <dest>
|
||||||
// <label>
|
// <label>
|
||||||
|
|
||||||
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
|
VarnodeTpl tmp =
|
||||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
new VarnodeTpl(new ConstTpl(uniq_space),
|
||||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()), inputs[1].getSize());
|
new ConstTpl(ConstTpl.REAL,
|
||||||
|
UniqueLayout.RUNTIME_BOOLEAN_INVERT.getOffset(language)),
|
||||||
|
inputs[1].getSize());
|
||||||
int labelIndex = labelcount++;
|
int labelIndex = labelcount++;
|
||||||
VarnodeTpl label = new VarnodeTpl(new ConstTpl(const_space),
|
VarnodeTpl label = new VarnodeTpl(new ConstTpl(const_space),
|
||||||
new ConstTpl(ConstTpl.J_RELATIVE, labelIndex), new ConstTpl(ConstTpl.REAL, 8));
|
new ConstTpl(ConstTpl.J_RELATIVE, labelIndex), new ConstTpl(ConstTpl.REAL, 8));
|
||||||
@@ -338,9 +335,9 @@ public abstract class PcodeEmit {
|
|||||||
// tmp = COPY &<dest>
|
// tmp = COPY &<dest>
|
||||||
// RETURN tmp
|
// RETURN tmp
|
||||||
|
|
||||||
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
|
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(uniq_space),
|
||||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
new ConstTpl(ConstTpl.REAL,
|
||||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()),
|
UniqueLayout.RUNTIME_RETURN_LOCATION.getOffset(language)),
|
||||||
new ConstTpl(ConstTpl.REAL, ptrSize));
|
new ConstTpl(ConstTpl.REAL, ptrSize));
|
||||||
|
|
||||||
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
|
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
|
||||||
@@ -379,13 +376,15 @@ public abstract class PcodeEmit {
|
|||||||
// RETURN <dest>
|
// RETURN <dest>
|
||||||
// <label>
|
// <label>
|
||||||
|
|
||||||
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
|
VarnodeTpl tmp =
|
||||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
new VarnodeTpl(new ConstTpl(uniq_space),
|
||||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()), inputs[1].getSize());
|
new ConstTpl(ConstTpl.REAL,
|
||||||
|
UniqueLayout.RUNTIME_BOOLEAN_INVERT.getOffset(language)),
|
||||||
|
inputs[1].getSize());
|
||||||
|
|
||||||
tmpAddr = uniqueFactory.getNextUniqueAddress();
|
VarnodeTpl tmp2 = new VarnodeTpl(new ConstTpl(uniq_space),
|
||||||
VarnodeTpl tmp2 = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
new ConstTpl(ConstTpl.REAL,
|
||||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()),
|
UniqueLayout.RUNTIME_RETURN_LOCATION.getOffset(language)),
|
||||||
new ConstTpl(ConstTpl.REAL, ptrSize));
|
new ConstTpl(ConstTpl.REAL, ptrSize));
|
||||||
|
|
||||||
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
|
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
|
||||||
@@ -478,8 +477,37 @@ public abstract class PcodeEmit {
|
|||||||
return hand.space;
|
return hand.space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust the dynamic pointer to account for a V_OFFSET_PLUS in the given VarnodeTpl.
|
||||||
|
* We are passed in an existing array (dyncache) of VarnodeData for input/output.
|
||||||
|
* We assume the location of the base pointer is in dyncache[1]
|
||||||
|
* @param dyncache is the existing array
|
||||||
|
* @param vn is the V_OFFSET_PLUS VarnodeTpl to adjust for
|
||||||
|
*/
|
||||||
|
private void generatePointerAdd(VarnodeData[] dyncache, VarnodeTpl vn) {
|
||||||
|
long offsetPlus = vn.getOffset().getReal() & 0xffff;
|
||||||
|
if (offsetPlus == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VarnodeData tmpData = dyncache[0]; // Swap dyncache[1] with dyncache[0]
|
||||||
|
dyncache[0] = dyncache[1];
|
||||||
|
dyncache[1] = tmpData;
|
||||||
|
dyncache[1].space = const_space; // Put V_OFFSET_PLUS constant in dyncache[1]
|
||||||
|
dyncache[1].offset = offsetPlus;
|
||||||
|
dyncache[1].size = dyncache[0].size;
|
||||||
|
dyncache[2].space = uniq_space; // Result of INT_ADD in special runtime temp
|
||||||
|
dyncache[2].offset = UniqueLayout.RUNTIME_BITRANGE_EA.getOffset(language);
|
||||||
|
dyncache[2].size = dyncache[0].size;
|
||||||
|
dump(startAddress, PcodeOp.INT_ADD, dyncache, 2, dyncache[2]);
|
||||||
|
numOps += 1;
|
||||||
|
tmpData = dyncache[2];
|
||||||
|
dyncache[2] = dyncache[1];
|
||||||
|
dyncache[1] = tmpData;
|
||||||
|
}
|
||||||
|
|
||||||
private void dump(OpTpl opt) {
|
private void dump(OpTpl opt) {
|
||||||
|
|
||||||
|
VarnodeData[] dyncache = null;
|
||||||
VarnodeTpl vn, outvn;
|
VarnodeTpl vn, outvn;
|
||||||
int isize = opt.getInput().length;
|
int isize = opt.getInput().length;
|
||||||
|
|
||||||
@@ -493,13 +521,16 @@ public abstract class PcodeEmit {
|
|||||||
dyncache[1] = new VarnodeData();
|
dyncache[1] = new VarnodeData();
|
||||||
dyncache[2] = new VarnodeData();
|
dyncache[2] = new VarnodeData();
|
||||||
generateLocation(vn, incache[i]); // Temporary storage
|
generateLocation(vn, incache[i]); // Temporary storage
|
||||||
dyncache[2].space = incache[i].space;
|
|
||||||
dyncache[2].offset = incache[i].offset;
|
|
||||||
dyncache[2].size = incache[i].size;
|
|
||||||
AddressSpace spc = generatePointer(vn, dyncache[1]);
|
AddressSpace spc = generatePointer(vn, dyncache[1]);
|
||||||
|
if (vn.getOffset().getSelect() == ConstTpl.V_OFFSET_PLUS) {
|
||||||
|
generatePointerAdd(dyncache, vn);
|
||||||
|
}
|
||||||
dyncache[0].space = const_space;
|
dyncache[0].space = const_space;
|
||||||
dyncache[0].offset = spc.getSpaceID();
|
dyncache[0].offset = spc.getSpaceID();
|
||||||
dyncache[0].size = 4; // Size of spaceid
|
dyncache[0].size = 4; // Size of spaceid
|
||||||
|
dyncache[2].space = incache[i].space;
|
||||||
|
dyncache[2].offset = incache[i].offset;
|
||||||
|
dyncache[2].size = incache[i].size;
|
||||||
dump(startAddress, PcodeOp.LOAD, dyncache, 2, dyncache[2]);
|
dump(startAddress, PcodeOp.LOAD, dyncache, 2, dyncache[2]);
|
||||||
numOps += 1;
|
numOps += 1;
|
||||||
}
|
}
|
||||||
@@ -524,13 +555,16 @@ public abstract class PcodeEmit {
|
|||||||
generateLocation(outvn, outcache); // Temporary storage
|
generateLocation(outvn, outcache); // Temporary storage
|
||||||
dump(startAddress, opt.getOpcode(), incache, isize, outcache);
|
dump(startAddress, opt.getOpcode(), incache, isize, outcache);
|
||||||
numOps += 1;
|
numOps += 1;
|
||||||
dyncache[2].space = outcache.space;
|
|
||||||
dyncache[2].offset = outcache.offset;
|
|
||||||
dyncache[2].size = outcache.size;
|
|
||||||
AddressSpace spc = generatePointer(outvn, dyncache[1]);
|
AddressSpace spc = generatePointer(outvn, dyncache[1]);
|
||||||
|
if (outvn.getOffset().getSelect() == ConstTpl.V_OFFSET_PLUS) {
|
||||||
|
generatePointerAdd(dyncache, outvn);
|
||||||
|
}
|
||||||
dyncache[0].space = const_space;
|
dyncache[0].space = const_space;
|
||||||
dyncache[0].offset = spc.getSpaceID();
|
dyncache[0].offset = spc.getSpaceID();
|
||||||
dyncache[0].size = 4; // Size of spaceid;
|
dyncache[0].size = 4; // Size of spaceid;
|
||||||
|
dyncache[2].space = outcache.space;
|
||||||
|
dyncache[2].offset = outcache.offset;
|
||||||
|
dyncache[2].size = outcache.size;
|
||||||
dump(startAddress, PcodeOp.STORE, dyncache, 3, null);
|
dump(startAddress, PcodeOp.STORE, dyncache, 3, null);
|
||||||
numOps += 1;
|
numOps += 1;
|
||||||
}
|
}
|
||||||
@@ -576,8 +610,8 @@ public abstract class PcodeEmit {
|
|||||||
/**
|
/**
|
||||||
* Insert the p-code of instruction(s) in the delay slot at this point in the p-code generation for the current instruction
|
* Insert the p-code of instruction(s) in the delay slot at this point in the p-code generation for the current instruction
|
||||||
* @param op is the DELAYSLOT directive
|
* @param op is the DELAYSLOT directive
|
||||||
* @throws UnknownInstructionException
|
* @throws UnknownInstructionException for problems finding the delay slot Instruction
|
||||||
* @throws MemoryAccessException
|
* @throws MemoryAccessException for problems resolving details of the delay slot Instruction
|
||||||
*/
|
*/
|
||||||
private void delaySlot(OpTpl op) throws UnknownInstructionException, MemoryAccessException {
|
private void delaySlot(OpTpl op) throws UnknownInstructionException, MemoryAccessException {
|
||||||
|
|
||||||
@@ -620,8 +654,8 @@ public abstract class PcodeEmit {
|
|||||||
* Inject the p-code for a different instruction at this point in the p-code generation for current instruction
|
* Inject the p-code for a different instruction at this point in the p-code generation for current instruction
|
||||||
* @param bld is the CROSSBUILD directive containing the section number and address parameters
|
* @param bld is the CROSSBUILD directive containing the section number and address parameters
|
||||||
* @param secnum is the section number of the section containing the CROSSBUILD directive
|
* @param secnum is the section number of the section containing the CROSSBUILD directive
|
||||||
* @throws UnknownInstructionException
|
* @throws UnknownInstructionException for problems finding the referenced Instruction
|
||||||
* @throws MemoryAccessException
|
* @throws MemoryAccessException for problems resolving details of the referenced Instruction
|
||||||
*/
|
*/
|
||||||
private void appendCrossBuild(OpTpl bld, int secnum)
|
private void appendCrossBuild(OpTpl bld, int secnum)
|
||||||
throws UnknownInstructionException, MemoryAccessException {
|
throws UnknownInstructionException, MemoryAccessException {
|
||||||
@@ -703,8 +737,8 @@ public abstract class PcodeEmit {
|
|||||||
* Build a named p-code section of a constructor that contains only implied BUILD directives
|
* Build a named p-code section of a constructor that contains only implied BUILD directives
|
||||||
* @param ct Constructor to build section for
|
* @param ct Constructor to build section for
|
||||||
* @param secnum index of the section to be built
|
* @param secnum index of the section to be built
|
||||||
* @throws MemoryAccessException
|
* @throws MemoryAccessException for problems resolving details of the underlying Instruction
|
||||||
* @throws UnknownInstructionException
|
* @throws UnknownInstructionException for problems finding the underlying Instruction
|
||||||
*/
|
*/
|
||||||
private void buildEmpty(Constructor ct, int secnum)
|
private void buildEmpty(Constructor ct, int secnum)
|
||||||
throws UnknownInstructionException, MemoryAccessException {
|
throws UnknownInstructionException, MemoryAccessException {
|
||||||
@@ -730,12 +764,9 @@ public abstract class PcodeEmit {
|
|||||||
|
|
||||||
void checkOverlays(int opcode, VarnodeData[] in, int isize, VarnodeData out) {
|
void checkOverlays(int opcode, VarnodeData[] in, int isize, VarnodeData out) {
|
||||||
if (overlayspace != null) {
|
if (overlayspace != null) {
|
||||||
if (uniqueFactory == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) {
|
if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) {
|
||||||
int spaceId = (int) in[0].offset;
|
int spaceId = (int) in[0].offset;
|
||||||
AddressSpace space = uniqueFactory.getAddressFactory().getAddressSpace(spaceId);
|
AddressSpace space = addressFactory.getAddressSpace(spaceId);
|
||||||
if (space.isOverlaySpace()) {
|
if (space.isOverlaySpace()) {
|
||||||
space = ((OverlayAddressSpace) space).getOverlayedSpace();
|
space = ((OverlayAddressSpace) space).getOverlayedSpace();
|
||||||
in[0].offset = space.getSpaceID();
|
in[0].offset = space.getSpaceID();
|
||||||
|
|||||||
+9
-10
@@ -17,7 +17,8 @@ package ghidra.app.plugin.processors.sleigh;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.lang.InstructionContext;
|
import ghidra.program.model.lang.InstructionContext;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||||||
* @param walk state of the ParserContext from which to generate p-code
|
* @param walk state of the ParserContext from which to generate p-code
|
||||||
*/
|
*/
|
||||||
public PcodeEmitObjects(ParserWalker walk) { // For use with emitting precompiled p-code templates
|
public PcodeEmitObjects(ParserWalker walk) { // For use with emitting precompiled p-code templates
|
||||||
this(walk, null, 0, null, null);
|
this(walk, null, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +43,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||||||
* of instruction including delay-sloted instructions)
|
* of instruction including delay-sloted instructions)
|
||||||
*/
|
*/
|
||||||
public PcodeEmitObjects(ParserWalker walk, int fallOffset) { // For use with emitting precompiled p-code templates
|
public PcodeEmitObjects(ParserWalker walk, int fallOffset) { // For use with emitting precompiled p-code templates
|
||||||
this(walk, null, fallOffset, null, null);
|
this(walk, null, fallOffset, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,12 +51,11 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||||||
* @param ictx is the InstructionContext used to resolve delayslot and crossbuild directives
|
* @param ictx is the InstructionContext used to resolve delayslot and crossbuild directives
|
||||||
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
||||||
* @param override required if pcode overrides are to be utilized
|
* @param override required if pcode overrides are to be utilized
|
||||||
* @param uniqueFactory required when override specified or if overlay normalization is required
|
|
||||||
*/
|
*/
|
||||||
public PcodeEmitObjects(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
public PcodeEmitObjects(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
||||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
PcodeOverride override) {
|
||||||
super(walk, ictx, fallOffset, override, uniqueFactory);
|
super(walk, ictx, fallOffset, override);
|
||||||
oplist = new ArrayList<PcodeOp>();
|
oplist = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PcodeOp[] getPcodeOp() {
|
public PcodeOp[] getPcodeOp() {
|
||||||
@@ -72,8 +72,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||||||
if (labelref == null) {
|
if (labelref == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < labelref.size(); ++i) {
|
for (Integer opindex : labelref) {
|
||||||
int opindex = labelref.get(i);
|
|
||||||
PcodeOp op = oplist.get(opindex);
|
PcodeOp op = oplist.get(opindex);
|
||||||
Varnode vn = op.getInput(0);
|
Varnode vn = op.getInput(0);
|
||||||
int labelid = (int) vn.getOffset();
|
int labelid = (int) vn.getOffset();
|
||||||
@@ -98,7 +97,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||||||
@Override
|
@Override
|
||||||
void addLabelRef() {
|
void addLabelRef() {
|
||||||
if (labelref == null) {
|
if (labelref == null) {
|
||||||
labelref = new ArrayList<Integer>();
|
labelref = new ArrayList<>();
|
||||||
}
|
}
|
||||||
labelref.add(numOps);
|
labelref.add(numOps);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-7
@@ -17,7 +17,8 @@ package ghidra.app.plugin.processors.sleigh;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.lang.InstructionContext;
|
import ghidra.program.model.lang.InstructionContext;
|
||||||
import ghidra.program.model.lang.PackedBytes;
|
import ghidra.program.model.lang.PackedBytes;
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
@@ -63,11 +64,10 @@ public class PcodeEmitPacked extends PcodeEmit {
|
|||||||
* @param ictx instruction contexts
|
* @param ictx instruction contexts
|
||||||
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
||||||
* @param override required if pcode overrides are to be utilized
|
* @param override required if pcode overrides are to be utilized
|
||||||
* @param uniqueFactory required when override specified or if overlay normalization is required
|
|
||||||
*/
|
*/
|
||||||
public PcodeEmitPacked(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
public PcodeEmitPacked(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
||||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
PcodeOverride override) {
|
||||||
super(walk, ictx, fallOffset, override, uniqueFactory);
|
super(walk, ictx, fallOffset, override);
|
||||||
buf = new PackedBytes(512);
|
buf = new PackedBytes(512);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +80,7 @@ public class PcodeEmitPacked extends PcodeEmit {
|
|||||||
if (labelref == null) {
|
if (labelref == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < labelref.size(); ++i) {
|
for (LabelRef ref : labelref) {
|
||||||
LabelRef ref = labelref.get(i);
|
|
||||||
if ((ref.labelIndex >= labeldef.size()) || (labeldef.get(ref.labelIndex) == null)) {
|
if ((ref.labelIndex >= labeldef.size()) || (labeldef.get(ref.labelIndex) == null)) {
|
||||||
throw new SleighException("Reference to non-existant sleigh label");
|
throw new SleighException("Reference to non-existant sleigh label");
|
||||||
}
|
}
|
||||||
@@ -102,7 +101,7 @@ public class PcodeEmitPacked extends PcodeEmit {
|
|||||||
@Override
|
@Override
|
||||||
void addLabelRef() {
|
void addLabelRef() {
|
||||||
if (labelref == null) {
|
if (labelref == null) {
|
||||||
labelref = new ArrayList<LabelRef>();
|
labelref = new ArrayList<>();
|
||||||
}
|
}
|
||||||
int labelIndex = (int) incache[0].offset;
|
int labelIndex = (int) incache[0].offset;
|
||||||
int labelSize = incache[0].size;
|
int labelSize = incache[0].size;
|
||||||
|
|||||||
+85
-53
@@ -161,19 +161,22 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
private static void addExplicitFlow(ConstructState state, OpTpl op, int flags,
|
private static void addExplicitFlow(ConstructState state, OpTpl op, int flags,
|
||||||
FlowSummary summary) {
|
FlowSummary summary) {
|
||||||
if (summary.flowState == null)
|
if (summary.flowState == null) {
|
||||||
summary.flowState = new ArrayList<>();
|
summary.flowState = new ArrayList<>();
|
||||||
|
}
|
||||||
FlowRecord res = new FlowRecord();
|
FlowRecord res = new FlowRecord();
|
||||||
summary.flowState.add(res);
|
summary.flowState.add(res);
|
||||||
res.flowFlags = flags;
|
res.flowFlags = flags;
|
||||||
res.op = op;
|
res.op = op;
|
||||||
res.addressnode = null;
|
res.addressnode = null;
|
||||||
VarnodeTpl dest = op.getInput()[0]; // First varnode input contains the destination address
|
VarnodeTpl dest = op.getInput()[0]; // First varnode input contains the destination address
|
||||||
if ((flags & (JUMPOUT | CALL | CROSSBUILD)) == 0)
|
if ((flags & (JUMPOUT | CALL | CROSSBUILD)) == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
// If the flow is out of the instruction, store the ConstructState so we can easily calculate address
|
// If the flow is out of the instruction, store the ConstructState so we can easily calculate address
|
||||||
if (state == null)
|
if (state == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if ((flags & CROSSBUILD) != 0) {
|
if ((flags & CROSSBUILD) != 0) {
|
||||||
res.addressnode = state;
|
res.addressnode = state;
|
||||||
}
|
}
|
||||||
@@ -218,24 +221,31 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
break;
|
break;
|
||||||
case PcodeOp.BRANCH:
|
case PcodeOp.BRANCH:
|
||||||
destType = res.lastop.getInput()[0].getOffset().getType();
|
destType = res.lastop.getInput()[0].getOffset().getType();
|
||||||
if (destType == ConstTpl.J_NEXT)
|
if (destType == ConstTpl.J_NEXT) {
|
||||||
flags = BRANCH_TO_END;
|
flags = BRANCH_TO_END;
|
||||||
else if (destType == ConstTpl.J_START)
|
}
|
||||||
|
else if (destType == ConstTpl.J_START) {
|
||||||
flags = NO_FALLTHRU;
|
flags = NO_FALLTHRU;
|
||||||
else if (destType == ConstTpl.J_RELATIVE)
|
}
|
||||||
|
else if (destType == ConstTpl.J_RELATIVE) {
|
||||||
flags = NO_FALLTHRU;
|
flags = NO_FALLTHRU;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
flags = JUMPOUT | NO_FALLTHRU;
|
flags = JUMPOUT | NO_FALLTHRU;
|
||||||
|
}
|
||||||
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
||||||
break;
|
break;
|
||||||
case PcodeOp.CBRANCH:
|
case PcodeOp.CBRANCH:
|
||||||
destType = res.lastop.getInput()[0].getOffset().getType();
|
destType = res.lastop.getInput()[0].getOffset().getType();
|
||||||
if (destType == ConstTpl.J_NEXT)
|
if (destType == ConstTpl.J_NEXT) {
|
||||||
flags = BRANCH_TO_END;
|
flags = BRANCH_TO_END;
|
||||||
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE))
|
}
|
||||||
|
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) {
|
||||||
flags = JUMPOUT;
|
flags = JUMPOUT;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
}
|
||||||
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
||||||
break;
|
break;
|
||||||
case PcodeOp.CALL:
|
case PcodeOp.CALL:
|
||||||
@@ -252,8 +262,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
break;
|
break;
|
||||||
case PcodeOp.INDIRECT: // Encode delayslot
|
case PcodeOp.INDIRECT: // Encode delayslot
|
||||||
destType = (int) res.lastop.getInput()[0].getOffset().getReal();
|
destType = (int) res.lastop.getInput()[0].getOffset().getReal();
|
||||||
if (destType > res.delay)
|
if (destType > res.delay) {
|
||||||
res.delay = destType;
|
res.delay = destType;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -263,8 +274,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static FlowType flowListToFlowType(List<FlowRecord> flowstate) {
|
public static FlowType flowListToFlowType(List<FlowRecord> flowstate) {
|
||||||
if (flowstate == null)
|
if (flowstate == null) {
|
||||||
return RefType.FALL_THROUGH;
|
return RefType.FALL_THROUGH;
|
||||||
|
}
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
for (FlowRecord rec : flowstate) {
|
for (FlowRecord rec : flowstate) {
|
||||||
flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL);
|
flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL);
|
||||||
@@ -307,8 +319,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
private static FlowType convertFlowFlags(int flowFlags) {
|
private static FlowType convertFlowFlags(int flowFlags) {
|
||||||
|
|
||||||
if ((flowFlags & LABEL) != 0)
|
if ((flowFlags & LABEL) != 0) {
|
||||||
flowFlags |= BRANCH_TO_END;
|
flowFlags |= BRANCH_TO_END;
|
||||||
|
}
|
||||||
flowFlags &= ~(CROSSBUILD | LABEL);
|
flowFlags &= ~(CROSSBUILD | LABEL);
|
||||||
// NOTE: If prototype has cross-build, flow must be determined dynamically
|
// NOTE: If prototype has cross-build, flow must be determined dynamically
|
||||||
switch (flowFlags) { // Convert flags to a standard flowtype
|
switch (flowFlags) { // Convert flags to a standard flowtype
|
||||||
@@ -395,8 +408,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == null)
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return (hashCode() == obj.hashCode()); // Trust entirely in hash
|
return (hashCode() == obj.hashCode()); // Trust entirely in hash
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,8 +429,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlowType getFlowType(InstructionContext context) {
|
public FlowType getFlowType(InstructionContext context) {
|
||||||
if (!hasCrossBuilds)
|
if (!hasCrossBuilds) {
|
||||||
return flowType;
|
return flowType;
|
||||||
|
}
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
try {
|
try {
|
||||||
flags = gatherFlags(0, context, -1);
|
flags = gatherFlags(0, context, -1);
|
||||||
@@ -473,8 +488,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOpType(int opIndex, InstructionContext context) {
|
public int getOpType(int opIndex, InstructionContext context) {
|
||||||
if (opIndex < 0 || opIndex >= opresolve.length)
|
if (opIndex < 0 || opIndex >= opresolve.length) {
|
||||||
return OperandType.DYNAMIC;
|
return OperandType.DYNAMIC;
|
||||||
|
}
|
||||||
|
|
||||||
SleighParserContext protoContext;
|
SleighParserContext protoContext;
|
||||||
try {
|
try {
|
||||||
@@ -485,20 +501,25 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return OperandType.DYNAMIC;
|
return OperandType.DYNAMIC;
|
||||||
|
}
|
||||||
int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0;
|
int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0;
|
||||||
if (hand.offset_space == null) { // Static handle
|
if (hand.offset_space == null) { // Static handle
|
||||||
int type = hand.space.getType();
|
int type = hand.space.getType();
|
||||||
if (type == AddressSpace.TYPE_REGISTER)
|
if (type == AddressSpace.TYPE_REGISTER) {
|
||||||
return OperandType.REGISTER | indirect;
|
return OperandType.REGISTER | indirect;
|
||||||
if (type == AddressSpace.TYPE_CONSTANT)
|
}
|
||||||
|
if (type == AddressSpace.TYPE_CONSTANT) {
|
||||||
return OperandType.SCALAR | indirect;
|
return OperandType.SCALAR | indirect;
|
||||||
|
}
|
||||||
OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]);
|
OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]);
|
||||||
if (sym.isCodeAddress())
|
if (sym.isCodeAddress()) {
|
||||||
return (OperandType.ADDRESS | OperandType.CODE | indirect);
|
return (OperandType.ADDRESS | OperandType.CODE | indirect);
|
||||||
if (type == AddressSpace.TYPE_RAM)
|
}
|
||||||
|
if (type == AddressSpace.TYPE_RAM) {
|
||||||
return (OperandType.ADDRESS | OperandType.DATA | indirect);
|
return (OperandType.ADDRESS | OperandType.DATA | indirect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return OperandType.DYNAMIC | indirect;
|
return OperandType.DYNAMIC | indirect;
|
||||||
}
|
}
|
||||||
@@ -565,13 +586,16 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
private int gatherFlags(int curflags, InstructionContext context, int secnum)
|
private int gatherFlags(int curflags, InstructionContext context, int secnum)
|
||||||
throws MemoryAccessException, UnknownContextException {
|
throws MemoryAccessException, UnknownContextException {
|
||||||
List<FlowRecord> curlist = null;
|
List<FlowRecord> curlist = null;
|
||||||
if (secnum < 0)
|
if (secnum < 0) {
|
||||||
curlist = flowStateList;
|
curlist = flowStateList;
|
||||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size()))
|
}
|
||||||
|
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
|
||||||
curlist = flowStateListNamed.get(secnum);
|
curlist = flowStateListNamed.get(secnum);
|
||||||
|
}
|
||||||
|
|
||||||
if (curlist == null)
|
if (curlist == null) {
|
||||||
return curflags;
|
return curflags;
|
||||||
|
}
|
||||||
|
|
||||||
for (FlowRecord rec : curlist) {
|
for (FlowRecord rec : curlist) {
|
||||||
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
||||||
@@ -618,13 +642,16 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
InstructionContext context, int secnum)
|
InstructionContext context, int secnum)
|
||||||
throws MemoryAccessException, UnknownContextException {
|
throws MemoryAccessException, UnknownContextException {
|
||||||
List<FlowRecord> curlist = null;
|
List<FlowRecord> curlist = null;
|
||||||
if (secnum < 0)
|
if (secnum < 0) {
|
||||||
curlist = flowStateList;
|
curlist = flowStateList;
|
||||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size()))
|
}
|
||||||
|
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
|
||||||
curlist = flowStateListNamed.get(secnum);
|
curlist = flowStateListNamed.get(secnum);
|
||||||
|
}
|
||||||
|
|
||||||
if (curlist == null)
|
if (curlist == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (FlowRecord rec : curlist) {
|
for (FlowRecord rec : curlist) {
|
||||||
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
||||||
@@ -654,8 +681,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
@Override
|
@Override
|
||||||
public Address[] getFlows(InstructionContext context) {
|
public Address[] getFlows(InstructionContext context) {
|
||||||
|
|
||||||
if (flowStateList.size() == 0)
|
if (flowStateList.size() == 0) {
|
||||||
return emptyFlow;
|
return emptyFlow;
|
||||||
|
}
|
||||||
|
|
||||||
ArrayList<Address> addresses = new ArrayList<>();
|
ArrayList<Address> addresses = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
@@ -668,8 +696,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
return emptyFlow;
|
return emptyFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addresses.size() == 0)
|
if (addresses.size() == 0) {
|
||||||
return emptyFlow;
|
return emptyFlow;
|
||||||
|
}
|
||||||
return addresses.toArray(new Address[addresses.size()]);
|
return addresses.toArray(new Address[addresses.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,8 +775,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
protoContext = (SleighParserContext) context.getParserContext();
|
protoContext = (SleighParserContext) context.getParserContext();
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
hand = protoContext.getFixedHandle(opState);
|
hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
@@ -769,8 +799,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) {
|
if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) {
|
||||||
int size = hand.size;
|
int size = hand.size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
@@ -798,8 +829,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
if (hand.space.getType() == AddressSpace.TYPE_REGISTER) {
|
if (hand.space.getType() == AddressSpace.TYPE_REGISTER) {
|
||||||
return language.getRegister(hand.space, hand.offset_offset, hand.size);
|
return language.getRegister(hand.space, hand.offset_offset, hand.size);
|
||||||
}
|
}
|
||||||
@@ -834,7 +866,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
public Object[] getInputObjects(InstructionContext context) {
|
public Object[] getInputObjects(InstructionContext context) {
|
||||||
PcodeOp[] pcode = null;
|
PcodeOp[] pcode = null;
|
||||||
try {
|
try {
|
||||||
pcode = getPcode(context, null, null);
|
pcode = getPcode(context, null);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
@@ -892,7 +924,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
public Object[] getResultObjects(InstructionContext context) {
|
public Object[] getResultObjects(InstructionContext context) {
|
||||||
PcodeOp[] pcode = null;
|
PcodeOp[] pcode = null;
|
||||||
try {
|
try {
|
||||||
pcode = getPcode(context, null, null);
|
pcode = getPcode(context, null);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
@@ -944,8 +976,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override,
|
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override) {
|
||||||
UniqueAddressFactory uniqueFactory) {
|
|
||||||
try {
|
try {
|
||||||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||||
int fallOffset = getLength();
|
int fallOffset = getLength();
|
||||||
@@ -964,8 +995,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
ParserWalker walker = new ParserWalker(protoContext);
|
ParserWalker walker = new ParserWalker(protoContext);
|
||||||
walker.baseState();
|
walker.baseState();
|
||||||
PcodeEmitObjects emit =
|
PcodeEmitObjects emit = new PcodeEmitObjects(walker, context, fallOffset, override);
|
||||||
new PcodeEmitObjects(walker, context, fallOffset, override, uniqueFactory);
|
|
||||||
emit.build(walker.getConstructor().getTempl(), -1);
|
emit.build(walker.getConstructor().getTempl(), -1);
|
||||||
emit.resolveRelatives();
|
emit.resolveRelatives();
|
||||||
if (!isindelayslot) {
|
if (!isindelayslot) {
|
||||||
@@ -986,8 +1016,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override,
|
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override) {
|
||||||
UniqueAddressFactory uniqueFactory) {
|
|
||||||
int fallOffset = getLength();
|
int fallOffset = getLength();
|
||||||
try {
|
try {
|
||||||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||||
@@ -1006,8 +1035,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
ParserWalker walker = new ParserWalker(protoContext);
|
ParserWalker walker = new ParserWalker(protoContext);
|
||||||
walker.baseState();
|
walker.baseState();
|
||||||
PcodeEmitPacked emit =
|
PcodeEmitPacked emit = new PcodeEmitPacked(walker, context, fallOffset, override);
|
||||||
new PcodeEmitPacked(walker, context, fallOffset, override, uniqueFactory);
|
|
||||||
emit.write(PcodeEmitPacked.inst_tag);
|
emit.write(PcodeEmitPacked.inst_tag);
|
||||||
emit.dumpOffset(emit.getFallOffset());
|
emit.dumpOffset(emit.getFallOffset());
|
||||||
|
|
||||||
@@ -1067,7 +1095,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
||||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
PcodeOverride override) {
|
||||||
if (opIndex < 0 || opIndex >= opRefTypes.length) {
|
if (opIndex < 0 || opIndex >= opRefTypes.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1085,7 +1113,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
if (refType != null) {
|
if (refType != null) {
|
||||||
return refType;
|
return refType;
|
||||||
}
|
}
|
||||||
cacheDefaultOperandRefTypes(context, uniqueFactory);
|
cacheDefaultOperandRefTypes(context);
|
||||||
return opRefTypes[opIndex];
|
return opRefTypes[opIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1097,7 +1125,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
catch (MemoryAccessException e) {
|
catch (MemoryAccessException e) {
|
||||||
return RefType.DATA;
|
return RefType.DATA;
|
||||||
}
|
}
|
||||||
PcodeOp[] pcode = getPcode(context, override, uniqueFactory);
|
PcodeOp[] pcode = getPcode(context, override);
|
||||||
if (pcode == null || pcode.length == 0) {
|
if (pcode == null || pcode.length == 0) {
|
||||||
return RefType.DATA;
|
return RefType.DATA;
|
||||||
}
|
}
|
||||||
@@ -1121,8 +1149,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
return refType;
|
return refType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cacheDefaultOperandRefTypes(InstructionContext context,
|
private void cacheDefaultOperandRefTypes(InstructionContext context) {
|
||||||
UniqueAddressFactory uniqueFactory) {
|
|
||||||
|
|
||||||
// Resolve handles for each operand
|
// Resolve handles for each operand
|
||||||
SleighParserContext protoContext;
|
SleighParserContext protoContext;
|
||||||
@@ -1132,7 +1159,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
catch (MemoryAccessException e) {
|
catch (MemoryAccessException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
PcodeOp[] pcode = getPcode(context, null, uniqueFactory);
|
PcodeOp[] pcode = getPcode(context, null);
|
||||||
if (pcode == null || pcode.length == 0) {
|
if (pcode == null || pcode.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1342,8 +1369,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
if (subct != null) {
|
if (subct != null) {
|
||||||
walker.setConstructor(subct);
|
walker.setConstructor(subct);
|
||||||
subct.applyContext(walker, debug);
|
subct.applyContext(walker, debug);
|
||||||
if (debug != null)
|
if (debug != null) {
|
||||||
debug.indent();
|
debug.indent();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
@@ -1355,8 +1383,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (debug != null)
|
if (debug != null) {
|
||||||
debug.dumpPattern(sym, walker);
|
debug.dumpPattern(sym, walker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walker.setCurrentLength(sym.getMinimumLength());
|
walker.setCurrentLength(sym.getMinimumLength());
|
||||||
walker.popOperand();
|
walker.popOperand();
|
||||||
@@ -1416,10 +1445,12 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
ConstructTpl templ = ct.getTempl();
|
ConstructTpl templ = ct.getTempl();
|
||||||
if (templ != null) {
|
if (templ != null) {
|
||||||
HandleTpl res = templ.getResult();
|
HandleTpl res = templ.getResult();
|
||||||
if (res != null) // Pop up handle to containing operand
|
if (res != null) { // Pop up handle to containing operand
|
||||||
res.fix(walker.getParentHandle(), walker);
|
res.fix(walker.getParentHandle(), walker);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
walker.getParentHandle().setInvalid();
|
walker.getParentHandle().setInvalid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walker.popOperand();
|
walker.popOperand();
|
||||||
}
|
}
|
||||||
@@ -1442,8 +1473,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||||||
if (ct != null) {
|
if (ct != null) {
|
||||||
int oper = walker.getOperand();
|
int oper = walker.getOperand();
|
||||||
int numoper = ct.getNumOperands();
|
int numoper = ct.getNumOperands();
|
||||||
if (oper == 0) // Upon first entry to this Constructor
|
if (oper == 0) { // Upon first entry to this Constructor
|
||||||
ct.applyContext(walker, debug); // Apply its context changes
|
ct.applyContext(walker, debug); // Apply its context changes
|
||||||
|
}
|
||||||
if (oper < numoper) {
|
if (oper < numoper) {
|
||||||
walker.pushOperand(oper);
|
walker.pushOperand(oper);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
+5
-5
@@ -904,8 +904,8 @@ public class SleighLanguage implements Language {
|
|||||||
Endian ldefEndian = description.getEndian();
|
Endian ldefEndian = description.getEndian();
|
||||||
Endian instEndian = description.getInstructionEndian();
|
Endian instEndian = description.getInstructionEndian();
|
||||||
if (slaEndian != ldefEndian && instEndian == ldefEndian) {
|
if (slaEndian != ldefEndian && instEndian == ldefEndian) {
|
||||||
throw new SleighException(".ldefs says " + getLanguageID() + " is " +
|
throw new SleighException(".ldefs says " + getLanguageID() + " is " + ldefEndian +
|
||||||
ldefEndian + " but .sla says " + slaEndian);
|
" but .sla says " + slaEndian);
|
||||||
}
|
}
|
||||||
uniqueBase = SpecXmlUtils.decodeLong(el.getAttribute("uniqbase"));
|
uniqueBase = SpecXmlUtils.decodeLong(el.getAttribute("uniqbase"));
|
||||||
alignment = SpecXmlUtils.decodeInt(el.getAttribute("align"));
|
alignment = SpecXmlUtils.decodeInt(el.getAttribute("align"));
|
||||||
@@ -935,9 +935,9 @@ public class SleighLanguage implements Language {
|
|||||||
String defname = el.getAttribute("defaultspace");
|
String defname = el.getAttribute("defaultspace");
|
||||||
spacetable = new LinkedHashMap<>();
|
spacetable = new LinkedHashMap<>();
|
||||||
// Slot zero is always the constant space
|
// Slot zero is always the constant space
|
||||||
AddressSpace constspc = new GenericAddressSpace("const", 64, AddressSpace.TYPE_CONSTANT, 0);
|
AddressSpace constspc = new GenericAddressSpace(SpaceNames.CONSTANT_SPACE_NAME, 64,
|
||||||
spacetable.put("const", constspc);
|
AddressSpace.TYPE_CONSTANT, SpaceNames.CONSTANT_SPACE_INDEX);
|
||||||
//spacetable.put("OTHER", AddressSpace.OTHER_SPACE);
|
spacetable.put(SpaceNames.CONSTANT_SPACE_NAME, constspc);
|
||||||
default_space = null;
|
default_space = null;
|
||||||
XmlElement subel = parser.peek();
|
XmlElement subel = parser.peek();
|
||||||
if (subel.getName().equals("space_other")) { // tag must be present
|
if (subel.getName().equals("space_other")) { // tag must be present
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/* ###
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offsets for various ranges in the p-code unique space. Offsets are either:
|
||||||
|
* 1) Relative to the last temporary allocated statically by the SLEIGH compiler
|
||||||
|
* or a particular language (.sla), OR
|
||||||
|
* 2) Absolute within the unique address space.
|
||||||
|
* So the layout of the unique address space looks like:
|
||||||
|
* 1) SLEIGH static temporaries
|
||||||
|
* 2) Runtime temporaries used by the SLEIGH p-code generator
|
||||||
|
* 3) Temporaries used by the PcodeInjectLibrary for p-code snippets
|
||||||
|
* 4) Temporaries generated during (decompiler) analysis
|
||||||
|
*
|
||||||
|
* The "unique" space is set to 32 bits across all architectures.
|
||||||
|
* The maximum offset is 0xFFFFFFFF.
|
||||||
|
* The offsets and names should match with the parallel decompiler enum in translate.hh
|
||||||
|
*/
|
||||||
|
public enum UniqueLayout {
|
||||||
|
SLEIGH_BASE(0, true), // First offset after SLEIGH static temporaries
|
||||||
|
RUNTIME_BOOLEAN_INVERT(0, true),
|
||||||
|
RUNTIME_RETURN_LOCATION(0x80, true),
|
||||||
|
RUNTIME_BITRANGE_EA(0x100, true),
|
||||||
|
INJECT(0x200, true),
|
||||||
|
ANALYSIS(0x10000000, false);
|
||||||
|
|
||||||
|
private final long offset;
|
||||||
|
private final boolean isRelative; // Is this offset relative to the end of SLEIGH statics
|
||||||
|
|
||||||
|
UniqueLayout(long off, boolean isRel) {
|
||||||
|
offset = off;
|
||||||
|
isRelative = isRel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the starting offset of a named range in the unique address space. The returned offset
|
||||||
|
* is absolute and specific to the given SLEIGH language.
|
||||||
|
* @param language is the given SLEIGH language
|
||||||
|
* @return the absolute offset
|
||||||
|
*/
|
||||||
|
public long getOffset(SleighLanguage language) {
|
||||||
|
return (isRelative && language != null) ? language.getUniqueBase() + offset : offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-2
@@ -95,6 +95,14 @@ public class ConstTpl {
|
|||||||
select = (short) vf;
|
select = (short) vf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConstTpl(int tp, long val, AddressSpace spc, int ht, int sel) {
|
||||||
|
type = tp;
|
||||||
|
value_real = val;
|
||||||
|
value_spaceid = spc;
|
||||||
|
handle_index = (short) ht;
|
||||||
|
select = (short) sel;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isConstSpace() {
|
public boolean isConstSpace() {
|
||||||
if (type == SPACEID) {
|
if (type == SPACEID) {
|
||||||
return (value_spaceid.getType() == AddressSpace.TYPE_CONSTANT);
|
return (value_spaceid.getType() == AddressSpace.TYPE_CONSTANT);
|
||||||
@@ -121,6 +129,10 @@ public class ConstTpl {
|
|||||||
return handle_index;
|
return handle_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSelect() {
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -160,8 +172,7 @@ public class ConstTpl {
|
|||||||
return hand.size;
|
return hand.size;
|
||||||
case V_OFFSET_PLUS:
|
case V_OFFSET_PLUS:
|
||||||
if (hand.space.getType() != AddressSpace.TYPE_CONSTANT) { // If we are not a constant
|
if (hand.space.getType() != AddressSpace.TYPE_CONSTANT) { // If we are not a constant
|
||||||
if (hand.offset_space == null)
|
if (hand.offset_space == null) {
|
||||||
{
|
|
||||||
return hand.offset_offset + (value_real & 0xffff); // Adjust offset by truncation amount
|
return hand.offset_offset + (value_real & 0xffff); // Adjust offset by truncation amount
|
||||||
}
|
}
|
||||||
return hand.temp_offset + (value_real & 0xffff);
|
return hand.temp_offset + (value_real & 0xffff);
|
||||||
|
|||||||
+13
@@ -63,6 +63,19 @@ public class ConstructTpl {
|
|||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually build a constructor template from pieces. This is used to translate from the
|
||||||
|
* internal SLEIGH compiler pcodeCPort.semantics.ConstructTpl
|
||||||
|
* @param opvec is the list of p-code op templates making up the constructor
|
||||||
|
* @param res is the result handle template for the constructor
|
||||||
|
* @param nmLabels is the number of labels int the template
|
||||||
|
*/
|
||||||
|
public ConstructTpl(OpTpl[] opvec, HandleTpl res, int nmLabels) {
|
||||||
|
vec = opvec;
|
||||||
|
result = res;
|
||||||
|
numlabels = nmLabels;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of labels needing resolution in this template
|
* @return the number of labels needing resolution in this template
|
||||||
*/
|
*/
|
||||||
|
|||||||
+13
-1
@@ -45,6 +45,17 @@ public class HandleTpl {
|
|||||||
protected HandleTpl() {
|
protected HandleTpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HandleTpl(ConstTpl spc, ConstTpl sz, ConstTpl ptrspc, ConstTpl ptroff, ConstTpl ptrsz,
|
||||||
|
ConstTpl tmpspc, ConstTpl tmpoff) {
|
||||||
|
space = spc;
|
||||||
|
size = sz;
|
||||||
|
ptrspace = ptrspc;
|
||||||
|
ptroffset = ptroff;
|
||||||
|
ptrsize = ptrsz;
|
||||||
|
temp_space = tmpspc;
|
||||||
|
temp_offset = tmpoff;
|
||||||
|
}
|
||||||
|
|
||||||
public void fix(FixedHandle hand, ParserWalker walker) {
|
public void fix(FixedHandle hand, ParserWalker walker) {
|
||||||
if (ptrspace.getType() == ConstTpl.REAL) {
|
if (ptrspace.getType() == ConstTpl.REAL) {
|
||||||
// The export is unstarred, but this doesn't mean
|
// The export is unstarred, but this doesn't mean
|
||||||
@@ -72,8 +83,9 @@ public class HandleTpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void fixPrintPiece(FixedHandle hand, ParserWalker walker, int handleIndex) {
|
public void fixPrintPiece(FixedHandle hand, ParserWalker walker, int handleIndex) {
|
||||||
if (!hand.fixable)
|
if (!hand.fixable) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (hand.space.getType() != AddressSpace.TYPE_CONSTANT) {
|
if (hand.space.getType() != AddressSpace.TYPE_CONSTANT) {
|
||||||
hand.fixable = false;
|
hand.fixable = false;
|
||||||
return;
|
return;
|
||||||
|
|||||||
+14
-10
@@ -56,7 +56,7 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new PseudoInstruction within a program.
|
* Construct a new PseudoInstruction within a program.
|
||||||
* @param program
|
* @param program is the given Program
|
||||||
* @param addr address of the instruction
|
* @param addr address of the instruction
|
||||||
* @param prototype prototype of the instruction
|
* @param prototype prototype of the instruction
|
||||||
* @param memBuffer buffer containing the bytes for the instruction
|
* @param memBuffer buffer containing the bytes for the instruction
|
||||||
@@ -221,22 +221,25 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Scalar getScalar(int opIndex) {
|
public Scalar getScalar(int opIndex) {
|
||||||
if (opIndex < 0)
|
if (opIndex < 0) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return instrProto.getScalar(opIndex, this);
|
return instrProto.getScalar(opIndex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register getRegister(int opIndex) {
|
public Register getRegister(int opIndex) {
|
||||||
if (opIndex < 0)
|
if (opIndex < 0) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return instrProto.getRegister(opIndex, this);
|
return instrProto.getRegister(opIndex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getOpObjects(int opIndex) {
|
public Object[] getOpObjects(int opIndex) {
|
||||||
if (opIndex < 0)
|
if (opIndex < 0) {
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
|
}
|
||||||
return instrProto.getOpObjects(opIndex, this);
|
return instrProto.getOpObjects(opIndex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,16 +396,15 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcodeOp[] getPcode() {
|
public PcodeOp[] getPcode() {
|
||||||
return instrProto.getPcode(this, null, null);
|
return instrProto.getPcode(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PcodeOp[] getPcode(boolean includeOverrides) {
|
public PcodeOp[] getPcode(boolean includeOverrides) {
|
||||||
if (!includeOverrides || addrFactory == null) {
|
if (!includeOverrides || addrFactory == null) {
|
||||||
return instrProto.getPcode(this, null, null);
|
return instrProto.getPcode(this, null);
|
||||||
}
|
}
|
||||||
return instrProto.getPcode(this, new InstructionPcodeOverride(this),
|
return instrProto.getPcode(this, new InstructionPcodeOverride(this));
|
||||||
new UniqueAddressFactory(addrFactory, instrProto.getLanguage()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -422,8 +424,9 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instruction getNext() {
|
public Instruction getNext() {
|
||||||
if (program == null)
|
if (program == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return program.getListing().getInstructionAfter(address);
|
return program.getListing().getInstructionAfter(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,8 +447,9 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (program == null)
|
if (program == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
return program.getListing().getInstructionBefore(address);
|
return program.getListing().getInstructionBefore(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -37,7 +37,7 @@ import ghidra.pcodeCPort.slghsymbol.*;
|
|||||||
import ghidra.pcodeCPort.space.*;
|
import ghidra.pcodeCPort.space.*;
|
||||||
import ghidra.pcodeCPort.utils.Utils;
|
import ghidra.pcodeCPort.utils.Utils;
|
||||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
import ghidra.sleigh.grammar.*;
|
import ghidra.sleigh.grammar.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import utilities.util.FileResolutionResult;
|
import utilities.util.FileResolutionResult;
|
||||||
@@ -272,16 +272,16 @@ public class SleighCompile extends SleighBase {
|
|||||||
// Some predefined symbols
|
// Some predefined symbols
|
||||||
root = new SubtableSymbol(location, "instruction"); // Base constructors
|
root = new SubtableSymbol(location, "instruction"); // Base constructors
|
||||||
symtab.addSymbol(root);
|
symtab.addSymbol(root);
|
||||||
insertSpace(new ConstantSpace(this, "const", BasicCompilerSpec.CONSTANT_SPACE_INDEX));
|
insertSpace(new ConstantSpace(this));
|
||||||
SpaceSymbol spacesym = new SpaceSymbol(location, getConstantSpace()); // Constant
|
SpaceSymbol spacesym = new SpaceSymbol(location, getConstantSpace()); // Constant
|
||||||
// space
|
// space
|
||||||
symtab.addSymbol(spacesym);
|
symtab.addSymbol(spacesym);
|
||||||
OtherSpace otherSpace = new OtherSpace(this, BasicCompilerSpec.OTHER_SPACE_NAME,
|
OtherSpace otherSpace =
|
||||||
BasicCompilerSpec.OTHER_SPACE_INDEX);
|
new OtherSpace(this, SpaceNames.OTHER_SPACE_NAME, SpaceNames.OTHER_SPACE_INDEX);
|
||||||
insertSpace(otherSpace);
|
insertSpace(otherSpace);
|
||||||
spacesym = new SpaceSymbol(location, otherSpace);
|
spacesym = new SpaceSymbol(location, otherSpace);
|
||||||
symtab.addSymbol(spacesym);
|
symtab.addSymbol(spacesym);
|
||||||
insertSpace(new UniqueSpace(this, "unique", numSpaces(), 0));
|
insertSpace(new UniqueSpace(this, numSpaces(), 0));
|
||||||
spacesym = new SpaceSymbol(location, getUniqueSpace()); // Temporary register
|
spacesym = new SpaceSymbol(location, getUniqueSpace()); // Temporary register
|
||||||
// space
|
// space
|
||||||
symtab.addSymbol(spacesym);
|
symtab.addSymbol(spacesym);
|
||||||
|
|||||||
+15
-16
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,33 +19,33 @@ import java.io.PrintStream;
|
|||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.error.*;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
import ghidra.pcodeCPort.translate.*;
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
|
|
||||||
|
|
||||||
public class ConstantSpace extends AddrSpace {
|
public class ConstantSpace extends AddrSpace {
|
||||||
public ConstantSpace( Translate t, String nm, int ind ) {
|
public ConstantSpace(Translate t) {
|
||||||
super( t, spacetype.IPTR_CONSTANT, nm, 8, 1, ind, 0, 0 );
|
super(t, spacetype.IPTR_CONSTANT, SpaceNames.CONSTANT_SPACE_NAME, 8, 1,
|
||||||
clearFlags( heritaged | big_endian );
|
SpaceNames.CONSTANT_SPACE_INDEX, 0, 0);
|
||||||
setFlags( big_endian );
|
clearFlags(heritaged | big_endian);
|
||||||
|
setFlags(big_endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int printRaw( PrintStream s, long offset ) {
|
public int printRaw(PrintStream s, long offset) {
|
||||||
s.append( "0x" );
|
s.append("0x");
|
||||||
s.append( Long.toHexString( offset) );
|
s.append(Long.toHexString(offset));
|
||||||
return getTrans().getDefaultSize();
|
return getTrans().getDefaultSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml( PrintStream s ) {
|
public void saveXml(PrintStream s) {
|
||||||
throw new LowlevelError( "Should never save the constant space as XML" );
|
throw new LowlevelError("Should never save the constant space as XML");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreXml( Element el ) {
|
public void restoreXml(Element el) {
|
||||||
throw new LowlevelError( "Should never restore the constant space from XML" );
|
throw new LowlevelError("Should never restore the constant space from XML");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,29 +15,30 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.space;
|
package ghidra.pcodeCPort.space;
|
||||||
|
|
||||||
import ghidra.pcodeCPort.translate.*;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import ghidra.pcodeCPort.translate.Translate;
|
||||||
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
|
|
||||||
public class UniqueSpace extends AddrSpace {
|
public class UniqueSpace extends AddrSpace {
|
||||||
public UniqueSpace( Translate t, String nm, int ind, int fl ) {
|
public UniqueSpace(Translate t, int ind, int fl) {
|
||||||
super( t, spacetype.IPTR_INTERNAL, nm, 4, 1, ind, fl, 0 );
|
super(t, spacetype.IPTR_INTERNAL, SpaceNames.UNIQUE_SPACE_NAME,
|
||||||
|
SpaceNames.UNIQUE_SPACE_SIZE, 1, ind, fl, 0);
|
||||||
|
|
||||||
setFlags( hasphysical );
|
setFlags(hasphysical);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniqueSpace( Translate t ) {
|
public UniqueSpace(Translate t) {
|
||||||
super( t, spacetype.IPTR_INTERNAL );
|
super(t, spacetype.IPTR_INTERNAL);
|
||||||
|
|
||||||
setFlags( hasphysical );
|
setFlags(hasphysical);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveXml( PrintStream s ) {
|
public void saveXml(PrintStream s) {
|
||||||
s.print( "<space_unique" );
|
s.print("<space_unique");
|
||||||
save_basic_attributes( s );
|
save_basic_attributes(s);
|
||||||
s.println( "/>" );
|
s.println("/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -28,7 +28,7 @@ import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
|||||||
import ghidra.pcodeCPort.space.*;
|
import ghidra.pcodeCPort.space.*;
|
||||||
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
|
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
|
||||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
|
|
||||||
public abstract class Translate implements BasicSpaceProvider {
|
public abstract class Translate implements BasicSpaceProvider {
|
||||||
|
|
||||||
@@ -215,10 +215,11 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
public abstract void initialize(DocumentStorage store);
|
public abstract void initialize(DocumentStorage store);
|
||||||
|
|
||||||
protected void registerContext(String name, int sbit, int ebit) {
|
protected void registerContext(String name, int sbit, int ebit) {
|
||||||
|
// Base implementation (for compiling) doesn't need to keep track of context symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContextDefault(String name, int val) {
|
// public void setContextDefault(String name, int val) {
|
||||||
}
|
// }
|
||||||
|
|
||||||
public abstract VarnodeData getRegister(String nm);
|
public abstract VarnodeData getRegister(String nm);
|
||||||
|
|
||||||
@@ -257,11 +258,11 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
|
|
||||||
protected void restoreXmlSpaces(Element el) {
|
protected void restoreXmlSpaces(Element el) {
|
||||||
// The first space should always be the constant space
|
// The first space should always be the constant space
|
||||||
insertSpace(new ConstantSpace(this, "const", BasicCompilerSpec.CONSTANT_SPACE_INDEX));
|
insertSpace(new ConstantSpace(this));
|
||||||
|
|
||||||
// The second space should always be the other space
|
// The second space should always be the other space
|
||||||
insertSpace(new OtherSpace(this, BasicCompilerSpec.OTHER_SPACE_NAME,
|
insertSpace(
|
||||||
BasicCompilerSpec.OTHER_SPACE_INDEX));
|
new OtherSpace(this, SpaceNames.OTHER_SPACE_NAME, SpaceNames.OTHER_SPACE_INDEX));
|
||||||
|
|
||||||
String defname = el.getAttributeValue("defaultspace");
|
String defname = el.getAttributeValue("defaultspace");
|
||||||
List<?> children = el.getChildren();
|
List<?> children = el.getChildren();
|
||||||
@@ -350,7 +351,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
boolean duplicatedefine = false;
|
boolean duplicatedefine = false;
|
||||||
switch (spc.getType()) {
|
switch (spc.getType()) {
|
||||||
case IPTR_CONSTANT:
|
case IPTR_CONSTANT:
|
||||||
if (!spc.getName().equals("const")) {
|
if (!spc.getName().equals(SpaceNames.CONSTANT_SPACE_NAME)) {
|
||||||
nametype_mismatch = true;
|
nametype_mismatch = true;
|
||||||
}
|
}
|
||||||
if (baselist.size() != 0) {
|
if (baselist.size() != 0) {
|
||||||
@@ -359,7 +360,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
constantspace = spc;
|
constantspace = spc;
|
||||||
break;
|
break;
|
||||||
case IPTR_INTERNAL:
|
case IPTR_INTERNAL:
|
||||||
if (!spc.getName().equals("unique")) {
|
if (!spc.getName().equals(SpaceNames.UNIQUE_SPACE_NAME)) {
|
||||||
nametype_mismatch = true;
|
nametype_mismatch = true;
|
||||||
}
|
}
|
||||||
if (uniqspace != null) {
|
if (uniqspace != null) {
|
||||||
@@ -368,7 +369,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
uniqspace = spc;
|
uniqspace = spc;
|
||||||
break;
|
break;
|
||||||
case IPTR_FSPEC:
|
case IPTR_FSPEC:
|
||||||
if (!spc.getName().equals("fspec")) {
|
if (!spc.getName().equals(SpaceNames.FSPEC_SPACE_NAME)) {
|
||||||
nametype_mismatch = true;
|
nametype_mismatch = true;
|
||||||
}
|
}
|
||||||
if (fspecspace != null) {
|
if (fspecspace != null) {
|
||||||
@@ -377,7 +378,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
fspecspace = spc;
|
fspecspace = spc;
|
||||||
break;
|
break;
|
||||||
case IPTR_IOP:
|
case IPTR_IOP:
|
||||||
if (!spc.getName().equals("iop")) {
|
if (!spc.getName().equals(SpaceNames.IOP_SPACE_NAME)) {
|
||||||
nametype_mismatch = true;
|
nametype_mismatch = true;
|
||||||
}
|
}
|
||||||
if (iopspace != null) {
|
if (iopspace != null) {
|
||||||
@@ -386,18 +387,16 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
iopspace = spc;
|
iopspace = spc;
|
||||||
break;
|
break;
|
||||||
case IPTR_SPACEBASE:
|
case IPTR_SPACEBASE:
|
||||||
if (spc.getName().equals("stack")) {
|
if (spc.getName().equals(SpaceNames.STACK_SPACE_NAME)) {
|
||||||
if (stackspace != null) {
|
if (stackspace != null) {
|
||||||
duplicatedefine = true;
|
duplicatedefine = true;
|
||||||
}
|
}
|
||||||
stackspace = spc;
|
stackspace = spc;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
}
|
|
||||||
// fallthru
|
// fallthru
|
||||||
case IPTR_PROCESSOR:
|
case IPTR_PROCESSOR:
|
||||||
if (spc.isOtherSpace()) {
|
if (spc.isOtherSpace()) {
|
||||||
if (spc.getIndex() != BasicCompilerSpec.OTHER_SPACE_INDEX) {
|
if (spc.getIndex() != SpaceNames.OTHER_SPACE_INDEX) {
|
||||||
throw new LowlevelError("OTHER space must be assigned index 1");
|
throw new LowlevelError("OTHER space must be assigned index 1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -481,7 +480,8 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
|
|
||||||
// Get data for the stackpointer
|
// Get data for the stackpointer
|
||||||
VarnodeData point = getRegister(el.getAttributeValue("register"));
|
VarnodeData point = getRegister(el.getAttributeValue("register"));
|
||||||
spc = new SpacebaseSpace("stack", ind, point.size, basespace, point.space.getDelay() + 1);
|
spc = new SpacebaseSpace(SpaceNames.STACK_SPACE_NAME, ind, point.size, basespace,
|
||||||
|
point.space.getDelay() + 1);
|
||||||
insertSpace(spc);
|
insertSpace(spc);
|
||||||
addSpacebase(stackspace, point.space, point.offset, point.size);
|
addSpacebase(stackspace, point.space, point.offset, point.size);
|
||||||
}
|
}
|
||||||
@@ -554,7 +554,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||||||
// spaceOrderMap = SpaceOrderMap.getSpaceOrderMapForProcessor( processorFile );
|
// spaceOrderMap = SpaceOrderMap.getSpaceOrderMapForProcessor( processorFile );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void allowContextSet(boolean val) {
|
// public void allowContextSet(boolean val) {
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -20,7 +20,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import db.DBRecord;
|
import db.DBRecord;
|
||||||
import ghidra.program.database.DBObjectCache;
|
import ghidra.program.database.DBObjectCache;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressOverflowException;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
@@ -128,7 +129,7 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the original context used to establish the shared prototype
|
* Get the original context used to establish the shared prototype
|
||||||
* @param baseContextReg
|
* @param baseContextReg is a context register
|
||||||
* @return prototype context value
|
* @return prototype context value
|
||||||
*/
|
*/
|
||||||
public RegisterValue getOriginalPrototypeContext(Register baseContextReg) {
|
public RegisterValue getOriginalPrototypeContext(Register baseContextReg) {
|
||||||
@@ -158,8 +159,9 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||||||
do {
|
do {
|
||||||
// skip past delay slot instructions
|
// skip past delay slot instructions
|
||||||
try {
|
try {
|
||||||
instr = program.getListing().getInstructionContaining(
|
instr = program.getListing()
|
||||||
instr.getMinAddress().subtractNoWrap(alignment));
|
.getInstructionContaining(
|
||||||
|
instr.getMinAddress().subtractNoWrap(alignment));
|
||||||
}
|
}
|
||||||
catch (AddressOverflowException e) {
|
catch (AddressOverflowException e) {
|
||||||
return null;
|
return null;
|
||||||
@@ -219,10 +221,10 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||||||
return EMPTY_ADDR_ARRAY;
|
return EMPTY_ADDR_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Address> list = new ArrayList<Address>();
|
ArrayList<Address> list = new ArrayList<>();
|
||||||
for (int i = 0; i < refs.length; ++i) {
|
for (Reference ref : refs) {
|
||||||
if (!refs[i].getReferenceType().isIndirect()) {
|
if (!ref.getReferenceType().isIndirect()) {
|
||||||
list.add(refs[i].getToAddress());
|
list.add(ref.getToAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +262,7 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||||||
lock.acquire();
|
lock.acquire();
|
||||||
try {
|
try {
|
||||||
checkIsValid();
|
checkIsValid();
|
||||||
return proto.getOperandRefType(opIndex, this, new InstructionPcodeOverride(this),
|
return proto.getOperandRefType(opIndex, this, new InstructionPcodeOverride(this));
|
||||||
new UniqueAddressFactory(program.getAddressFactory(), program.getLanguage()));
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
lock.release();
|
lock.release();
|
||||||
@@ -593,10 +594,9 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||||||
try {
|
try {
|
||||||
checkIsValid();
|
checkIsValid();
|
||||||
if (!includeOverrides) {
|
if (!includeOverrides) {
|
||||||
return proto.getPcode(this, null, null);
|
return proto.getPcode(this, null);
|
||||||
}
|
}
|
||||||
return proto.getPcode(this, new InstructionPcodeOverride(this),
|
return proto.getPcode(this, new InstructionPcodeOverride(this));
|
||||||
new UniqueAddressFactory(program.getAddressFactory(), program.getLanguage()));
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
lock.release();
|
lock.release();
|
||||||
|
|||||||
+2
-2
@@ -17,7 +17,7 @@ package ghidra.program.model.address;
|
|||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,7 +70,7 @@ public interface AddressSpace extends Comparable<AddressSpace> {
|
|||||||
* get loaded into the final memory image and for user-defined spaces.
|
* get loaded into the final memory image and for user-defined spaces.
|
||||||
*/
|
*/
|
||||||
public static final AddressSpace OTHER_SPACE = new GenericAddressSpace(
|
public static final AddressSpace OTHER_SPACE = new GenericAddressSpace(
|
||||||
BasicCompilerSpec.OTHER_SPACE_NAME, 64, TYPE_OTHER, BasicCompilerSpec.OTHER_SPACE_INDEX);
|
SpaceNames.OTHER_SPACE_NAME, 64, TYPE_OTHER, SpaceNames.OTHER_SPACE_INDEX);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>EXTERNAL_SPACE</code> is used to contain all external locations (i.e., data and functions)
|
* The <code>EXTERNAL_SPACE</code> is used to contain all external locations (i.e., data and functions)
|
||||||
|
|||||||
+4
-4
@@ -18,7 +18,7 @@ package ghidra.program.model.address;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
import ghidra.program.model.lang.SpaceNames;
|
||||||
import ghidra.util.datastruct.IntObjectHashtable;
|
import ghidra.util.datastruct.IntObjectHashtable;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ public class DefaultAddressFactory implements AddressFactory {
|
|||||||
|
|
||||||
private void checkReservedJoin(AddressSpace space) {
|
private void checkReservedJoin(AddressSpace space) {
|
||||||
if (space.getType() == AddressSpace.TYPE_JOIN ||
|
if (space.getType() == AddressSpace.TYPE_JOIN ||
|
||||||
space.getName().equals(BasicCompilerSpec.JOIN_SPACE_NAME)) {
|
space.getName().equals(SpaceNames.JOIN_SPACE_NAME)) {
|
||||||
throw new IllegalArgumentException("Join space should not be specified");
|
throw new IllegalArgumentException("Join space should not be specified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ public class DefaultAddressFactory implements AddressFactory {
|
|||||||
|
|
||||||
private void checkReservedStack(AddressSpace space) {
|
private void checkReservedStack(AddressSpace space) {
|
||||||
if (space.getType() == AddressSpace.TYPE_STACK ||
|
if (space.getType() == AddressSpace.TYPE_STACK ||
|
||||||
space.getName().equalsIgnoreCase(BasicCompilerSpec.STACK_SPACE_NAME)) {
|
space.getName().equalsIgnoreCase(SpaceNames.STACK_SPACE_NAME)) {
|
||||||
throw new IllegalArgumentException("Stack space should not be specified");
|
throw new IllegalArgumentException("Stack space should not be specified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,7 +399,7 @@ public class DefaultAddressFactory implements AddressFactory {
|
|||||||
throw new DuplicateNameException("Space named " + space.getName() + " already exists!");
|
throw new DuplicateNameException("Space named " + space.getName() + " already exists!");
|
||||||
}
|
}
|
||||||
if (space.getType() == AddressSpace.TYPE_VARIABLE) {
|
if (space.getType() == AddressSpace.TYPE_VARIABLE) {
|
||||||
spaceNameTable.put("join", space);// Add VARIABLE space with name "join"
|
spaceNameTable.put(SpaceNames.JOIN_SPACE_NAME, space);// Add VARIABLE space with name "join"
|
||||||
return;// Don't put it in the spaces array or the id lookup table
|
return;// Don't put it in the spaces array or the id lookup table
|
||||||
}
|
}
|
||||||
spaces.add(space);
|
spaces.add(space);
|
||||||
|
|||||||
-54
@@ -1,54 +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.program.model.address;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
|
||||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
|
||||||
import ghidra.program.model.lang.Language;
|
|
||||||
|
|
||||||
public class UniqueAddressFactory {
|
|
||||||
|
|
||||||
private AddressFactory addrFactory;
|
|
||||||
private AddressSpace uniqueSpace;
|
|
||||||
private final long firstAvailableOffset;
|
|
||||||
private long nextOffset;
|
|
||||||
|
|
||||||
public UniqueAddressFactory(AddressFactory addrFactory, Language language) {
|
|
||||||
this.addrFactory = addrFactory;
|
|
||||||
this.uniqueSpace = addrFactory.getUniqueSpace();
|
|
||||||
if (language instanceof SleighLanguage) {
|
|
||||||
firstAvailableOffset = ((SleighLanguage) language).getUniqueBase();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
firstAvailableOffset = 0;
|
|
||||||
}
|
|
||||||
nextOffset = firstAvailableOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Address getNextUniqueAddress() {
|
|
||||||
Address addr = uniqueSpace.getAddress(nextOffset);
|
|
||||||
nextOffset += SleighBase.MAX_UNIQUE_SIZE;
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void reset() {
|
|
||||||
nextOffset = firstAvailableOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressFactory getAddressFactory() {
|
|
||||||
return addrFactory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+7
-15
@@ -48,14 +48,6 @@ import ghidra.xml.*;
|
|||||||
*/
|
*/
|
||||||
public class BasicCompilerSpec implements CompilerSpec {
|
public class BasicCompilerSpec implements CompilerSpec {
|
||||||
|
|
||||||
public static final String STACK_SPACE_NAME = "stack";
|
|
||||||
public static final String JOIN_SPACE_NAME = "join";
|
|
||||||
public static final String OTHER_SPACE_NAME = "OTHER";
|
|
||||||
|
|
||||||
//must match AddrSpace enum (see space.hh)
|
|
||||||
public static final int CONSTANT_SPACE_INDEX = 0;
|
|
||||||
public static final int OTHER_SPACE_INDEX = 1;
|
|
||||||
|
|
||||||
private final CompilerSpecDescription description;
|
private final CompilerSpecDescription description;
|
||||||
private String sourceName;
|
private String sourceName;
|
||||||
private final SleighLanguage language;
|
private final SleighLanguage language;
|
||||||
@@ -426,21 +418,21 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||||||
@Override
|
@Override
|
||||||
public AddressSpace getAddressSpace(String spaceName) {
|
public AddressSpace getAddressSpace(String spaceName) {
|
||||||
AddressSpace space;
|
AddressSpace space;
|
||||||
if (STACK_SPACE_NAME.equals(spaceName)) {
|
if (SpaceNames.STACK_SPACE_NAME.equals(spaceName)) {
|
||||||
space = stackSpace;
|
space = stackSpace;
|
||||||
}
|
}
|
||||||
else if (JOIN_SPACE_NAME.equals(spaceName)) {
|
else if (SpaceNames.JOIN_SPACE_NAME.equals(spaceName)) {
|
||||||
if (joinSpace == null) {
|
if (joinSpace == null) {
|
||||||
// This is a special address space that is only used internally to represent bonded registers
|
// This is a special address space that is only used internally to represent bonded registers
|
||||||
joinSpace =
|
joinSpace = new GenericAddressSpace(SpaceNames.JOIN_SPACE_NAME, 64,
|
||||||
new GenericAddressSpace(JOIN_SPACE_NAME, 64, AddressSpace.TYPE_JOIN, 10);
|
AddressSpace.TYPE_JOIN, 10);
|
||||||
}
|
}
|
||||||
space = joinSpace;
|
space = joinSpace;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
space = language.getAddressFactory().getAddressSpace(spaceName);
|
space = language.getAddressFactory().getAddressSpace(spaceName);
|
||||||
}
|
}
|
||||||
if (spaceName.equals(OTHER_SPACE_NAME)) {
|
if (spaceName.equals(SpaceNames.OTHER_SPACE_NAME)) {
|
||||||
space = AddressSpace.OTHER_SPACE;
|
space = AddressSpace.OTHER_SPACE;
|
||||||
}
|
}
|
||||||
if (space == null) {
|
if (space == null) {
|
||||||
@@ -701,7 +693,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||||||
parser.end();
|
parser.end();
|
||||||
|
|
||||||
if (stackPointer == null) {
|
if (stackPointer == null) {
|
||||||
stackSpace = new GenericAddressSpace(STACK_SPACE_NAME,
|
stackSpace = new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME,
|
||||||
language.getDefaultSpace().getSize(),
|
language.getDefaultSpace().getSize(),
|
||||||
language.getDefaultSpace().getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
language.getDefaultSpace().getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
||||||
}
|
}
|
||||||
@@ -979,7 +971,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||||||
throw new SleighException("Undefined base stack space: " + baseSpaceName);
|
throw new SleighException("Undefined base stack space: " + baseSpaceName);
|
||||||
}
|
}
|
||||||
int stackSpaceSize = Math.min(stackPointer.getBitLength(), stackBaseSpace.getSize());
|
int stackSpaceSize = Math.min(stackPointer.getBitLength(), stackBaseSpace.getSize());
|
||||||
stackSpace = new GenericAddressSpace(STACK_SPACE_NAME, stackSpaceSize,
|
stackSpace = new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME, stackSpaceSize,
|
||||||
stackBaseSpace.getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
stackBaseSpace.getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
||||||
String reverseJustifyStr = el.getAttribute("reversejustify");
|
String reverseJustifyStr = el.getAttribute("reversejustify");
|
||||||
if (reverseJustifyStr != null) {
|
if (reverseJustifyStr != null) {
|
||||||
|
|||||||
+6
-13
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,8 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.program.model.lang;
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.UniqueAddressFactory;
|
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
@@ -26,8 +26,6 @@ import ghidra.program.model.scalar.Scalar;
|
|||||||
import ghidra.program.model.symbol.FlowType;
|
import ghidra.program.model.symbol.FlowType;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InstructionPrototype is designed to describe one machine level instruction.
|
* InstructionPrototype is designed to describe one machine level instruction.
|
||||||
* A language parser can return the same InstructionProtoype object for the
|
* A language parser can return the same InstructionProtoype object for the
|
||||||
@@ -252,11 +250,10 @@ public interface InstructionPrototype {
|
|||||||
* @param opIndex the index of the operand. (zero based)
|
* @param opIndex the index of the operand. (zero based)
|
||||||
* @param context the instruction context
|
* @param context the instruction context
|
||||||
* @param override if not null, steers local overrides of pcode generation
|
* @param override if not null, steers local overrides of pcode generation
|
||||||
* @param uniqueFactory must be specified if flowOverride is not null
|
|
||||||
* @return reference type.
|
* @return reference type.
|
||||||
*/
|
*/
|
||||||
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
||||||
PcodeOverride override, UniqueAddressFactory uniqueFactory);
|
PcodeOverride override);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the operand at opIndex should have a delimiter following it.
|
* Return true if the operand at opIndex should have a delimiter following it.
|
||||||
@@ -290,22 +287,18 @@ public interface InstructionPrototype {
|
|||||||
*
|
*
|
||||||
* @param context the instruction context
|
* @param context the instruction context
|
||||||
* @param override if not null, may indicate that different elements of the pcode generation are overridden
|
* @param override if not null, may indicate that different elements of the pcode generation are overridden
|
||||||
* @param uniqueFactory must be specified if flowOverride is not null
|
|
||||||
* @return array of PCODE,
|
* @return array of PCODE,
|
||||||
* zero length array if language doesn't support PCODE for this instruction
|
* zero length array if language doesn't support PCODE for this instruction
|
||||||
*/
|
*/
|
||||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override,
|
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override);
|
||||||
UniqueAddressFactory uniqueFactory);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as getPcode but returns the operations in a packed format to optimize transfer to other processes
|
* Same as getPcode but returns the operations in a packed format to optimize transfer to other processes
|
||||||
* @param context the instruction context
|
* @param context the instruction context
|
||||||
* @param override if not null, may indicate that different elements of the pcode generation are overridden
|
* @param override if not null, may indicate that different elements of the pcode generation are overridden
|
||||||
* @param uniqueFactory must be specified if flowOverride is not null
|
* @return the set of packed bytes encoding the p-code
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override,
|
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override);
|
||||||
UniqueAddressFactory uniqueFactory);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an array of PCode operations (micro code) that a particular operand
|
* Get an array of PCode operations (micro code) that a particular operand
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user