GP-4285 Compressed SLEIGH

This commit is contained in:
caheckman 2024-01-10 22:53:12 +00:00
parent b380fd5fa6
commit 8fbd171cdf
207 changed files with 15233 additions and 6055 deletions

View file

@ -0,0 +1 @@
MODULE FILE LICENSE: src/decompile/zlib zlib License

View file

@ -26,7 +26,6 @@ if (findProject(':Generic') == null) {
* Define the "native build model" for building the decompiler executables. * Define the "native build model" for building the decompiler executables.
*/ */
model { model {
// Define the source files that are compiled and linked to become the decompiler. // Define the source files that are compiled and linked to become the decompiler.
// The decompiler source is a bit weird in that all the cpp and headers all live in // The decompiler source is a bit weird in that all the cpp and headers all live in
// the same directory with other files that are not used by the decompiler. // the same directory with other files that are not used by the decompiler.
@ -174,6 +173,8 @@ model {
include "slghpattern.cc" include "slghpattern.cc"
include "semantics.cc" include "semantics.cc"
include "context.cc" include "context.cc"
include "slaformat.cc"
include "compression.cc"
include "filemanage.cc" include "filemanage.cc"
include "slgh_compile.cc" include "slgh_compile.cc"
@ -188,7 +189,27 @@ model {
srcDir "src/decompile/cpp" srcDir "src/decompile/cpp"
} }
} // end cpp } // end cpp
if (isCurrentWindows()) {
c {
source {
srcDir "src/decompile/zlib"
include "*.c"
}
}
}
} // end sources (sleigh) } // end sources (sleigh)
binaries {
all{ b ->
if (b.toolChain in Gcc || b.toolChain in Clang) {
b.linker.args "-lz"
}
else {
b.cppCompiler.define "LOCAL_ZLIB"
}
}
} // end binaries.all (sleigh)
} // end sleigh } // end sleigh
} // end components } // end components
@ -223,7 +244,15 @@ model {
b.cppCompiler.define "WIN64" b.cppCompiler.define "WIN64"
b.cppCompiler.define "_WIN64" b.cppCompiler.define "_WIN64"
} }
} }
b.cCompiler.args "/W3"
b.cCompiler.args "/O2"
b.cCompiler.args "/Oy" // Omit frame pointer
b.cCompiler.define "_CRT_SECURE_NO_DEPRECATE"
b.cCompiler.define "_CRT_NONSTDC_NO_DEPRECATE"
b.cCompiler.define "WIN64"
b.cCompiler.define "ZLIB_WINAPI"
b.cCompiler.define "NO_GZIP"
} }
else if (b.toolChain in Clang) { else if (b.toolChain in Clang) {
b.cppCompiler.args "-std=c++11" b.cppCompiler.args "-std=c++11"

View file

@ -4,6 +4,7 @@
##MODULE IP: Modified Nuvola Icons - LGPL 2.1 ##MODULE IP: Modified Nuvola Icons - LGPL 2.1
##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Oxygen Icons - LGPL 3.0
##MODULE IP: Tango Icons - Public Domain ##MODULE IP: Tango Icons - Public Domain
##MODULE IP: zlib License
Module.manifest||GHIDRA||||END| Module.manifest||GHIDRA||||END|
data/decompiler.theme.properties||GHIDRA||||END| data/decompiler.theme.properties||GHIDRA||||END|
src/decompile/.cproject||GHIDRA||||END| src/decompile/.cproject||GHIDRA||||END|
@ -67,6 +68,7 @@ src/decompile/datatests/twodim.xml||GHIDRA||||END|
src/decompile/datatests/union_datatype.xml||GHIDRA||||END| src/decompile/datatests/union_datatype.xml||GHIDRA||||END|
src/decompile/datatests/varcross.xml||GHIDRA||||END| src/decompile/datatests/varcross.xml||GHIDRA||||END|
src/decompile/datatests/wayoffarray.xml||GHIDRA||||END| src/decompile/datatests/wayoffarray.xml||GHIDRA||||END|
src/decompile/zlib/README.txt||GHIDRA||||END|
src/main/doc/commonprofile.xsl||GHIDRA||||END| src/main/doc/commonprofile.xsl||GHIDRA||||END|
src/main/doc/cspec.xml||GHIDRA||||END| src/main/doc/cspec.xml||GHIDRA||||END|
src/main/doc/cspec_html.xsl||GHIDRA||||END| src/main/doc/cspec_html.xsl||GHIDRA||||END|

View file

@ -50,9 +50,9 @@ YACC=bison
# libraries # libraries
#INCLUDES=-I$(BFDHOME)/include #INCLUDES=-I$(BFDHOME)/include
INCLUDES= INCLUDES=
BFDLIB=-lbfd -lz BFDLIB=-lbfd
LNK= LNK=-lz
# Source files # Source files
ALL_SOURCE= $(wildcard *.cc) ALL_SOURCE= $(wildcard *.cc)
@ -87,7 +87,7 @@ DECCORE=capability architecture options graph cover block cast typeop database c
printlanguage printc printjava memstate opbehavior paramid signature $(COREEXT_NAMES) printlanguage printc printjava memstate opbehavior paramid signature $(COREEXT_NAMES)
# Files used for any project that use the sleigh decoder # Files used for any project that use the sleigh decoder
SLEIGH= sleigh pcodeparse pcodecompile sleighbase slghsymbol \ SLEIGH= sleigh pcodeparse pcodecompile sleighbase slghsymbol \
slghpatexpress slghpattern semantics context filemanage slghpatexpress slghpattern semantics context slaformat compression filemanage
# Additional files for the GHIDRA specific build # Additional files for the GHIDRA specific build
GHIDRA= ghidra_arch inject_ghidra ghidra_translate loadimage_ghidra \ GHIDRA= ghidra_arch inject_ghidra ghidra_translate loadimage_ghidra \
typegrp_ghidra database_ghidra ghidra_context cpool_ghidra \ typegrp_ghidra database_ghidra ghidra_context cpool_ghidra \
@ -260,10 +260,10 @@ test: ghidra_test_dbg
./ghidra_test_dbg ./ghidra_test_dbg
ghidra_dbg: $(GHIDRA_DBG_OBJS) ghidra_dbg: $(GHIDRA_DBG_OBJS)
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_dbg $(GHIDRA_DBG_OBJS) $(LNK) $(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_dbg $(GHIDRA_DBG_OBJS)
ghidra_opt: $(GHIDRA_OPT_OBJS) ghidra_opt: $(GHIDRA_OPT_OBJS)
$(CXX) $(OPT_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_opt $(GHIDRA_OPT_OBJS) $(LNK) $(CXX) $(OPT_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_opt $(GHIDRA_OPT_OBJS)
sleigh_dbg: $(SLEIGH_DBG_OBJS) sleigh_dbg: $(SLEIGH_DBG_OBJS)
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o sleigh_dbg $(SLEIGH_DBG_OBJS) $(LNK) $(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o sleigh_dbg $(SLEIGH_DBG_OBJS) $(LNK)

View file

@ -98,10 +98,10 @@ public:
void encode(Encoder &encoder) const; ///< Encode \b this to a stream void encode(Encoder &encoder) const; ///< Encode \b this to a stream
void encode(Encoder &encoder,int4 size) const; ///< Encode \b this and a size to a stream void encode(Encoder &encoder,int4 size) const; ///< Encode \b this and a size to a stream
/// Restore an address from parsed XML /// Decode an address from a stream
static Address decode(Decoder &decoder); static Address decode(Decoder &decoder);
/// Restore an address and size from parsed XML /// Decode an address and size from a stream
static Address decode(Decoder &decoder,int4 &size); static Address decode(Decoder &decoder,int4 &size);
}; };
@ -221,7 +221,7 @@ class RangeProperties {
bool seenLast; ///< End of the range is actively specified bool seenLast; ///< End of the range is actively specified
public: public:
RangeProperties(void) { first = 0; last = 0; isRegister = false; seenLast = false; } RangeProperties(void) { first = 0; last = 0; isRegister = false; seenLast = false; }
void decode(Decoder &decoder); ///< Restore \b this from an XML stream void decode(Decoder &decoder); ///< Decode \b this from a stream
}; };
/// \brief A disjoint set of Ranges, possibly across multiple address spaces /// \brief A disjoint set of Ranges, possibly across multiple address spaces

View file

@ -236,7 +236,7 @@ public:
void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function
void setPrintLanguage(const string &nm); ///< Establish a particular output language void setPrintLanguage(const string &nm); ///< Establish a particular output language
void globalify(void); ///< Mark \e all spaces as global void globalify(void); ///< Mark \e all spaces as global
void decodeFlowOverride(Decoder &decoder); ///< Set flow overrides from XML void decodeFlowOverride(Decoder &decoder); ///< Decode flow overrides from a stream
virtual ~Architecture(void); ///< Destructor virtual ~Architecture(void); ///< Destructor
/// \brief Get a string describing \b this architecture /// \brief Get a string describing \b this architecture

View file

@ -132,7 +132,7 @@ private:
// the result of the condition being false // the result of the condition being false
static void replaceEdgeMap(vector<BlockEdge> &vec); ///< Update block references in edges with copy map static void replaceEdgeMap(vector<BlockEdge> &vec); ///< Update block references in edges with copy map
void addInEdge(FlowBlock *b,uint4 lab); ///< Add an edge coming into \b this void addInEdge(FlowBlock *b,uint4 lab); ///< Add an edge coming into \b this
void decodeNextInEdge(Decoder &decoder,BlockMap &resolver); ///< Restore the next input edge from XML void decodeNextInEdge(Decoder &decoder,BlockMap &resolver); ///< Decode the next input edge from stream
void halfDeleteInEdge(int4 slot); ///< Delete the \e in half of an edge, correcting indices void halfDeleteInEdge(int4 slot); ///< Delete the \e in half of an edge, correcting indices
void halfDeleteOutEdge(int4 slot); ///< Delete the \e out half of an edge, correcting indices void halfDeleteOutEdge(int4 slot); ///< Delete the \e out half of an edge, correcting indices
void removeInEdge(int4 slot); ///< Remove an incoming edge void removeInEdge(int4 slot); ///< Remove an incoming edge

View file

@ -68,7 +68,7 @@ public:
int4 getUniq(void) const { return uniq; } ///< Get the sub-sorting index int4 getUniq(void) const { return uniq; } ///< Get the sub-sorting index
const string &getText(void) const { return text; } ///< Get the body of the comment const string &getText(void) const { return text; } ///< Get the body of the comment
void encode(Encoder &encoder) const; ///< Encode the comment to a stream void encode(Encoder &encoder) const; ///< Encode the comment to a stream
void decode(Decoder &decoder); ///< Restore the comment from XML void decode(Decoder &decoder); ///< Decode the comment from a stream
static uint4 encodeCommentType(const string &name); ///< Convert name string to comment property static uint4 encodeCommentType(const string &name); ///< Convert name string to comment property
static string decodeCommentType(uint4 val); ///< Convert comment property to string static string decodeCommentType(uint4 val); ///< Convert comment property to string
}; };
@ -146,7 +146,7 @@ public:
/// \param encoder is the stream encoder /// \param encoder is the stream encoder
virtual void encode(Encoder &encoder) const=0; virtual void encode(Encoder &encoder) const=0;
/// \brief Restore all comments from a \<commentdb> element /// \brief Decode all comments from a \<commentdb> element
/// ///
/// \param decoder is the stream decoder /// \param decoder is the stream decoder
virtual void decode(Decoder &decoder)=0; virtual void decode(Decoder &decoder)=0;

View file

@ -0,0 +1,165 @@
/* ###
* 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.
*/
#include "compression.hh"
namespace ghidra {
/// The compression \b level ranges from 1-9 from faster/least compression to slower/most compression.
/// Use a \b level of 0 for no compression and -1 for the \e default compression level.
/// \param level is the compression level
Compress::Compress(int4 level)
{
compStream.zalloc = Z_NULL;
compStream.zfree = Z_NULL;
compStream.opaque = Z_NULL;
int4 ret = deflateInit(&compStream, level);
if (ret != Z_OK)
throw LowlevelError("Could not initialize deflate stream state");
}
Compress::~Compress(void)
{
deflateEnd(&compStream);
}
/// Return the number of bytes of output space still available. Output may be limited by the amount
/// of space in the output buffer or the amount of data available in the current input buffer.
/// \param buffer is where compressed bytes are stored
/// \param sz is the size, in bytes, of the buffer
/// \param finish is set to \b true if this is the final buffer to add to the stream
/// \return the number of output bytes still available
int4 Compress::deflate(uint1 *buffer,int4 sz,bool finish)
{
int flush = finish ? Z_FINISH : Z_NO_FLUSH;
compStream.avail_out = sz;
compStream.next_out = buffer;
int ret = ::deflate(&compStream, flush);
if (ret == Z_STREAM_ERROR)
throw LowlevelError("Error compressing stream");
return compStream.avail_out;
}
Decompress::Decompress(void)
{
streamFinished = false;
compStream.zalloc = Z_NULL;
compStream.zfree = Z_NULL;
compStream.opaque = Z_NULL;
compStream.avail_in = 0;
compStream.next_in = Z_NULL;
int ret = inflateInit(&compStream);
if (ret != Z_OK)
throw LowlevelError("Could not initialize inflate stream state");
}
/// Return the number of bytes of output space still available. Output may be limited by the amount
/// of space in the output buffer or the amount of data available in the current input buffer.
/// \param buffer is where uncompressed bytes are stored
/// \param sz is the size, in bytes, of the buffer
/// \return the number of output bytes still available
int4 Decompress::inflate(uint1 *buffer,int4 sz)
{
compStream.avail_out = sz;
compStream.next_out = buffer;
int ret = ::inflate(&compStream, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
case Z_STREAM_ERROR:
throw LowlevelError("Error decompressing stream");
case Z_STREAM_END:
streamFinished = true;
break;
default:
break;
}
return compStream.avail_out;
}
Decompress::~Decompress(void)
{
inflateEnd(&compStream);
}
const int4 CompressBuffer::IN_BUFFER_SIZE = 4096;
const int4 CompressBuffer::OUT_BUFFER_SIZE = 4096;
/// \param s is the backing output stream
/// \param level is the level of compression
CompressBuffer::CompressBuffer(ostream &s,int4 level)
: outStream(s), compressor(level)
{
inBuffer = new uint1[IN_BUFFER_SIZE];
outBuffer = new uint1[OUT_BUFFER_SIZE];
setp((char *)inBuffer,(char *)inBuffer + IN_BUFFER_SIZE-1);
}
CompressBuffer::~CompressBuffer(void)
{
delete [] inBuffer;
delete [] outBuffer;
}
/// The compressor is called repeatedly and its output is written to the backing stream
/// until the compressor can no longer fill the \e output buffer.
/// \param lastBuffer is \b true if this is the final set of bytes to add to the compressed stream
void CompressBuffer::flushInput(bool lastBuffer)
{
int len = pptr() - pbase();
compressor.input((uint1 *)pbase(),len);
int4 outAvail;
do {
outAvail = OUT_BUFFER_SIZE;
outAvail = compressor.deflate(outBuffer,outAvail,lastBuffer);
outStream.write((char *)outBuffer,OUT_BUFFER_SIZE-outAvail);
} while(outAvail == 0);
pbump(-len);
}
/// \param c is the final character filling the buffer
/// \return the written character
int CompressBuffer::overflow(int c)
{
if (c != EOF) {
*pptr() = c;
pbump(1);
}
flushInput(false);
return c;
}
/// \return 0 for success
int CompressBuffer::sync(void)
{
flushInput(true);
return 0;
}
}

View file

@ -0,0 +1,100 @@
/* ###
* 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.
*/
/// \file compression.hh
/// \brief The Compress and Decompress classes wrapping the deflate and inflate algorithms
#ifndef __COMPRESSION__
#define __COMPRESSION__
#include "error.hh"
#ifdef LOCAL_ZLIB
#include "../zlib/zlib.h"
#else
#include <zlib.h>
#endif
namespace ghidra {
/// \brief Wrapper for the deflate algorithm
///
/// Initialize/free algorithm resources. Provide successive arrays of bytes to compress via
/// the input() method. Compute successive arrays of compressed bytes via the deflate() method.
class Compress {
z_stream compStream; ///< The zlib deflate algorithm state
public:
Compress(int4 level); ///< Initialize the deflate algorithm state
~Compress(void); ///< Free algorithm state resources
/// \brief Provide the next sequence of bytes to be compressed
///
/// \param buffer is a pointer to the bytes to compress
/// \param sz is the number of bytes
void input(uint1 *buffer,int4 sz) {
compStream.avail_in = sz;
compStream.next_in = buffer;
}
int4 deflate(uint1 *buffer,int4 sz,bool finish); ///< Deflate as much as possible into given buffer
};
/// \brief Wrapper for the inflate algorithm
///
/// Initialize/free algorithm resources. Provide successive arrays of compressed bytes via
/// the input() method. Compute successive arrays of uncompressed bytes via the inflate() method.
class Decompress {
z_stream compStream; ///< The zlib inflate algorithm state
bool streamFinished; ///< Set to \b true if the end of the compressed stream has been reached
public:
Decompress(void); ///< Initialize the inflate algorithm state
~Decompress(void); ///< Free algorithm state resources
/// \brief Provide the next sequence of compressed bytes
///
/// \param buffer is a pointer to the compressed bytes
/// \param sz is the number of bytes
void input(uint1 *buffer,int4 sz) {
compStream.next_in = buffer;
compStream.avail_in = sz;
}
bool isFinished(void) const { return streamFinished; } ///< Return \b if end of compressed stream is reached
int4 inflate(uint1 *buffer,int4 sz); ///< Inflate as much as possible into given buffer
};
/// \brief Stream buffer that performs compression
///
/// Provides an ostream filter that compresses the stream using the \e deflate algorithm.
/// The stream buffer is provided a backing stream that is the ultimate destination of the compressed bytes.
/// A front-end stream is initialized with \b this stream buffer.
/// After writing the full sequence of bytes to compressed to the front-end stream, make sure to
/// call the stream's flush() method to emit the final compressed bytes to the backing stream.
class CompressBuffer : public std::streambuf {
static const int4 IN_BUFFER_SIZE; ///< Number of bytes in the \e input buffer
static const int4 OUT_BUFFER_SIZE; ///< Number of bytes in the \e output buffer
ostream &outStream; ///< The backing stream receiving compressed bytes
uint1 *inBuffer; ///< The \e input buffer
uint1 *outBuffer; ///< The \e output buffer
Compress compressor; ///< Compressor state
protected:
void flushInput(bool lastBuffer); ///< Compress the current set of bytes in the \e input buffer
virtual int overflow(int c); ///< Pass the filled input buffer to the compressor
virtual int sync(void); ///< Pass remaining bytes in the input buffer to the compressor
public:
CompressBuffer(ostream &s,int4 level); ///< Constructor
~CompressBuffer(void); ///< Destructor
};
}
#endif

View file

@ -628,66 +628,4 @@ uintb FloatFormat::opRound(uintb a) const
return getEncoding(round(val)); // round half away from zero return getEncoding(round(val)); // round half away from zero
} }
/// Write the format out to a \<floatformat> XML tag.
/// \param s is the output stream
void FloatFormat::saveXml(ostream &s) const
{
s << "<floatformat";
a_v_i(s,"size",size);
a_v_i(s,"signpos",signbit_pos);
a_v_i(s,"fracpos",frac_pos);
a_v_i(s,"fracsize",frac_size);
a_v_i(s,"exppos",exp_pos);
a_v_i(s,"expsize",exp_size);
a_v_i(s,"bias",bias);
a_v_b(s,"jbitimplied",jbitimplied);
s << "/>\n";
}
/// Restore \b object from a \<floatformat> XML tag
/// \param el is the element
void FloatFormat::restoreXml(const Element *el)
{
{
istringstream s(el->getAttributeValue("size"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> size;
}
{
istringstream s(el->getAttributeValue("signpos"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> signbit_pos;
}
{
istringstream s(el->getAttributeValue("fracpos"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> frac_pos;
}
{
istringstream s(el->getAttributeValue("fracsize"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> frac_size;
}
{
istringstream s(el->getAttributeValue("exppos"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> exp_pos;
}
{
istringstream s(el->getAttributeValue("expsize"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> exp_size;
}
{
istringstream s(el->getAttributeValue("bias"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> bias;
}
jbitimplied = xml_readbool(el->getAttributeValue("jbitimplied"));
maxexponent = (1<<exp_size)-1;
calcPrecision();
}
} // End namespace ghidra } // End namespace ghidra

View file

@ -19,7 +19,7 @@
#ifndef __FLOAT_HH__ #ifndef __FLOAT_HH__
#define __FLOAT_HH__ #define __FLOAT_HH__
#include "xml.hh" #include "error.hh"
namespace ghidra { namespace ghidra {
@ -61,7 +61,6 @@ private:
uintb getNaNEncoding(bool sgn) const; ///< Get an encoded NaN value uintb getNaNEncoding(bool sgn) const; ///< Get an encoded NaN value
void calcPrecision(void); ///< Calculate the decimal precision of this format void calcPrecision(void); ///< Calculate the decimal precision of this format
public: public:
FloatFormat(void) {} ///< Construct for use with restoreXml()
FloatFormat(int4 sz); ///< Construct default IEEE 754 standard settings FloatFormat(int4 sz); ///< Construct default IEEE 754 standard settings
int4 getSize(void) const { return size; } ///< Get the size of the encoding in bytes int4 getSize(void) const { return size; } ///< Get the size of the encoding in bytes
double getHostFloat(uintb encoding,floatclass *type) const; ///< Convert an encoding into host's double double getHostFloat(uintb encoding,floatclass *type) const; ///< Convert an encoding into host's double
@ -93,9 +92,6 @@ public:
uintb opRound(uintb a) const; ///< Round uintb opRound(uintb a) const; ///< Round
uintb opInt2Float(uintb a,int4 sizein) const; ///< Convert integer to floating-point uintb opInt2Float(uintb a,int4 sizein) const; ///< Convert integer to floating-point
uintb opFloat2Float(uintb a,const FloatFormat &outformat) const; ///< Convert between floating-point precisions uintb opFloat2Float(uintb a,const FloatFormat &outformat) const; ///< Convert between floating-point precisions
void saveXml(ostream &s) const; ///< Save the format to an XML stream
void restoreXml(const Element *el); ///< Restore the format from XML
}; };
} // End namespace ghidra } // End namespace ghidra

View file

@ -1959,7 +1959,7 @@ const string FspecSpace::NAME = "fspec";
/// \param t is the associated processor translator /// \param t is the associated processor translator
/// \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,int4 ind) FspecSpace::FspecSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
: AddrSpace(m,t,IPTR_FSPEC,NAME,sizeof(void *),1,ind,0,1) : AddrSpace(m,t,IPTR_FSPEC,NAME,false,sizeof(void *),1,ind,0,1,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
@ -2008,12 +2008,6 @@ void FspecSpace::printRaw(ostream &s,uintb offset) const
} }
} }
void FspecSpace::saveXml(ostream &s) const
{
throw LowlevelError("Should never encode fspec space to stream");
}
void FspecSpace::decode(Decoder &decoder) void FspecSpace::decode(Decoder &decoder)
{ {

View file

@ -345,7 +345,6 @@ public:
virtual void encodeAttributes(Encoder &encoder,uintb offset) const; virtual void encodeAttributes(Encoder &encoder,uintb offset) const;
virtual void encodeAttributes(Encoder &encoder,uintb offset,int4 size) const; virtual void encodeAttributes(Encoder &encoder,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 decode(Decoder &decoder); virtual void decode(Decoder &decoder);
static const string NAME; ///< Reserved name for the fspec space static const string NAME; ///< Reserved name for the fspec space
}; };

View file

@ -197,7 +197,7 @@ public:
void printBlockTree(ostream &s) const; ///< Print a description of control-flow structuring to a stream void printBlockTree(ostream &s) const; ///< Print a description of control-flow structuring to a stream
void printLocalRange(ostream &s) const; ///< Print description of memory ranges associated with local scopes void printLocalRange(ostream &s) const; ///< Print description of memory ranges associated with local scopes
void encode(Encoder &encoder,uint8 id,bool savetree) const; ///< Encode a description of \b this function to stream void encode(Encoder &encoder,uint8 id,bool savetree) const; ///< Encode a description of \b this function to stream
uint8 decode(Decoder &decoder); ///< Restore the state of \b this function from an XML description uint8 decode(Decoder &decoder); ///< Restore the state of \b this function from a stream
void encodeJumpTable(Encoder &encoder) const; ///< Encode a description of jump-tables to stream void encodeJumpTable(Encoder &encoder) const; ///< Encode a description of jump-tables to stream
void decodeJumpTable(Decoder &decoder); ///< Decode jump-tables from a stream void decodeJumpTable(Decoder &decoder); ///< Decode jump-tables from a stream
void encodeTree(Encoder &encoder) const; ///< Encode a description of the p-code tree to stream void encodeTree(Encoder &encoder) const; ///< Encode a description of the p-code tree to stream

View file

@ -321,7 +321,7 @@ void IfcOption::execute(istream &s)
} }
try { try {
string res = dcp->conf->options->set(ElementId::find(optname),p1,p2,p3); string res = dcp->conf->options->set(ElementId::find(optname,0),p1,p2,p3);
*status->optr << res << endl; *status->optr << res << endl;
} }
catch(ParseError &err) { catch(ParseError &err) {

View file

@ -91,7 +91,8 @@ void InjectPayloadSleigh::decode(Decoder &decoder)
void InjectPayloadSleigh::printTemplate(ostream &s) const void InjectPayloadSleigh::printTemplate(ostream &s) const
{ {
tpl->saveXml(s,-1); XmlEncode encoder(s);
tpl->encode(encoder,-1);
} }
void InjectPayloadSleigh::checkParameterRestrictions(InjectContextSleigh &con, void InjectPayloadSleigh::checkParameterRestrictions(InjectContextSleigh &con,
@ -247,7 +248,8 @@ void ExecutablePcodeSleigh::decode(Decoder &decoder)
void ExecutablePcodeSleigh::printTemplate(ostream &s) const void ExecutablePcodeSleigh::printTemplate(ostream &s) const
{ {
tpl->saveXml(s,-1); XmlEncode encoder(s);
tpl->encode(encoder,-1);
} }
InjectPayloadDynamic::~InjectPayloadDynamic(void) InjectPayloadDynamic::~InjectPayloadDynamic(void)

View file

@ -24,6 +24,9 @@ unordered_map<string,uint4> AttributeId::lookupAttributeId;
const int4 PackedDecode::BUFFER_SIZE = 1024; const int4 PackedDecode::BUFFER_SIZE = 1024;
const char XmlEncode::spaces[] = "\n ";
const int4 XmlEncode::MAX_SPACES = 24+1;
/// Access static vector of AttributeId objects that are registered during static initialization /// Access static vector of AttributeId objects that are registered during static initialization
/// The list itself is created once on the first call to this method. /// The list itself is created once on the first call to this method.
/// \return a reference to the vector /// \return a reference to the vector
@ -38,11 +41,13 @@ vector<AttributeId *> &AttributeId::getList(void)
/// in the global hashtable. /// in the global hashtable.
/// \param nm is the name of the attribute /// \param nm is the name of the attribute
/// \param i is an id to associate with the attribute /// \param i is an id to associate with the attribute
AttributeId::AttributeId(const string &nm,uint4 i) /// \param scope is an id for the scope of this attribute
AttributeId::AttributeId(const string &nm,uint4 i,int4 scope)
: name(nm) : name(nm)
{ {
id = i; id = i;
getList().push_back(this); if (scope == 0)
getList().push_back(this);
} }
/// Fill the hashtable mapping attribute names to their id, from registered attribute objects /// Fill the hashtable mapping attribute names to their id, from registered attribute objects
@ -78,11 +83,13 @@ vector<ElementId *> &ElementId::getList(void)
/// in the global hashtable. /// in the global hashtable.
/// \param nm is the name of the element /// \param nm is the name of the element
/// \param i is an id to associate with the element /// \param i is an id to associate with the element
ElementId::ElementId(const string &nm,uint4 i) /// \param scope is an id for the scope of this element
ElementId::ElementId(const string &nm,uint4 i,int4 scope)
: name(nm) : name(nm)
{ {
id = i; id = i;
getList().push_back(this); if (scope == 0)
getList().push_back(this);
} }
/// Fill the hashtable mapping element names to their id, from registered element objects /// Fill the hashtable mapping element names to their id, from registered element objects
@ -132,7 +139,7 @@ uint4 XmlDecode::peekElement(void)
return 0; return 0;
el = *iter; el = *iter;
} }
return ElementId::find(el->getName()); return ElementId::find(el->getName(),scope);
} }
uint4 XmlDecode::openElement(void) uint4 XmlDecode::openElement(void)
@ -156,7 +163,7 @@ uint4 XmlDecode::openElement(void)
elStack.push_back(el); elStack.push_back(el);
iterStack.push_back(el->getChildren().begin()); iterStack.push_back(el->getChildren().begin());
attributeIndex = -1; attributeIndex = -1;
return ElementId::find(el->getName()); return ElementId::find(el->getName(),scope);
} }
uint4 XmlDecode::openElement(const ElementId &elemId) uint4 XmlDecode::openElement(const ElementId &elemId)
@ -194,7 +201,7 @@ void XmlDecode::closeElement(uint4 id)
const Element *el = elStack.back(); const Element *el = elStack.back();
if (iterStack.back() != el->getChildren().end()) if (iterStack.back() != el->getChildren().end())
throw DecoderError("Closing element <" + el->getName() + "> with additional children"); throw DecoderError("Closing element <" + el->getName() + "> with additional children");
if (ElementId::find(el->getName()) != id) if (ElementId::find(el->getName(), scope) != id)
throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id"); throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id");
#endif #endif
elStack.pop_back(); elStack.pop_back();
@ -207,7 +214,7 @@ void XmlDecode::closeElementSkipping(uint4 id)
{ {
#ifdef CPUI_DEBUG #ifdef CPUI_DEBUG
const Element *el = elStack.back(); const Element *el = elStack.back();
if (ElementId::find(el->getName()) != id) if (ElementId::find(el->getName(), scope) != id)
throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id"); throw DecoderError("Trying to close <" + el->getName() + "> with mismatching id");
#endif #endif
elStack.pop_back(); elStack.pop_back();
@ -228,7 +235,7 @@ uint4 XmlDecode::getNextAttributeId(void)
int4 nextIndex = attributeIndex + 1; int4 nextIndex = attributeIndex + 1;
if (nextIndex < el->getNumAttributes()) { if (nextIndex < el->getNumAttributes()) {
attributeIndex = nextIndex; attributeIndex = nextIndex;
return AttributeId::find(el->getAttributeName(attributeIndex)); return AttributeId::find(el->getAttributeName(attributeIndex),scope);
} }
return 0; return 0;
} }
@ -419,40 +426,89 @@ AddrSpace *XmlDecode::readSpace(const AttributeId &attribId)
return res; return res;
} }
OpCode XmlDecode::readOpcode(void)
{
const Element *el = elStack.back();
string nm = el->getAttributeValue(attributeIndex);
OpCode opc = get_opcode(nm);
if (opc == (OpCode)0)
throw DecoderError("Bad encoded OpCode");
return opc;
}
OpCode XmlDecode::readOpcode(AttributeId &attribId)
{
const Element *el = elStack.back();
string nm;
if (attribId == ATTRIB_CONTENT) {
nm = el->getContent();
}
else {
int4 index = findMatchingAttribute(el, attribId.getName());
nm = el->getAttributeValue(index);
}
OpCode opc = get_opcode(nm);
if (opc == (OpCode)0)
throw DecoderError("Bad encoded OpCode");
return opc;
}
void XmlEncode::newLine(void)
{
if (!doFormatting)
return;
int numSpaces = depth * 2 + 1;
if (numSpaces > MAX_SPACES) {
numSpaces = MAX_SPACES;
}
outStream.write(spaces,numSpaces);
}
void XmlEncode::openElement(const ElementId &elemId) void XmlEncode::openElement(const ElementId &elemId)
{ {
if (elementTagIsOpen) if (tagStatus == tag_start)
outStream << '>'; outStream << '>';
else else
elementTagIsOpen = true; tagStatus = tag_start;
newLine();
outStream << '<' << elemId.getName(); outStream << '<' << elemId.getName();
depth += 1;
} }
void XmlEncode::closeElement(const ElementId &elemId) void XmlEncode::closeElement(const ElementId &elemId)
{ {
if (elementTagIsOpen) { depth -= 1;
if (tagStatus == tag_start) {
outStream << "/>"; outStream << "/>";
elementTagIsOpen = false; tagStatus = tag_stop;
} return;
else {
outStream << "</" << elemId.getName() << '>';
} }
if (tagStatus != tag_content)
newLine();
else
tagStatus = tag_stop;
outStream << "</" << elemId.getName() << '>';
} }
void XmlEncode::writeBool(const AttributeId &attribId,bool val) void XmlEncode::writeBool(const AttributeId &attribId,bool val)
{ {
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) { if (tagStatus == tag_start) {
outStream << '>'; outStream << '>';
elementTagIsOpen = false;
} }
if (val) if (val)
outStream << "true"; outStream << "true";
else else
outStream << "false"; outStream << "false";
tagStatus = tag_content;
return; return;
} }
a_v_b(outStream, attribId.getName(), val); a_v_b(outStream, attribId.getName(), val);
@ -462,11 +518,11 @@ void XmlEncode::writeSignedInteger(const AttributeId &attribId,intb val)
{ {
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) { if (tagStatus == tag_start) {
outStream << '>'; outStream << '>';
elementTagIsOpen = false;
} }
outStream << dec << val; outStream << dec << val;
tagStatus = tag_content;
return; return;
} }
a_v_i(outStream, attribId.getName(), val); a_v_i(outStream, attribId.getName(), val);
@ -476,11 +532,11 @@ void XmlEncode::writeUnsignedInteger(const AttributeId &attribId,uintb val)
{ {
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) { if (tagStatus == tag_start) {
outStream << '>'; outStream << '>';
elementTagIsOpen = false;
} }
outStream << hex << "0x" << val; outStream << hex << "0x" << val;
tagStatus = tag_content;
return; return;
} }
a_v_u(outStream, attribId.getName(), val); a_v_u(outStream, attribId.getName(), val);
@ -490,11 +546,11 @@ void XmlEncode::writeString(const AttributeId &attribId,const string &val)
{ {
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) { if (tagStatus == tag_start) {
outStream << '>'; outStream << '>';
elementTagIsOpen = false;
} }
xml_escape(outStream, val.c_str()); xml_escape(outStream, val.c_str());
tagStatus = tag_content;
return; return;
} }
a_v(outStream,attribId.getName(),val); a_v(outStream,attribId.getName(),val);
@ -514,16 +570,33 @@ void XmlEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
{ {
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (elementTagIsOpen) { if (tagStatus == tag_start) {
outStream << '>'; outStream << '>';
elementTagIsOpen = false;
} }
xml_escape(outStream, spc->getName().c_str()); xml_escape(outStream, spc->getName().c_str());
tagStatus = tag_content;
return; return;
} }
a_v(outStream,attribId.getName(),spc->getName()); a_v(outStream,attribId.getName(),spc->getName());
} }
void XmlEncode::writeOpcode(const AttributeId &attribId,OpCode opc)
{
const char *name = get_opname(opc);
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
if (tagStatus == tag_start) {
outStream << '>';
}
outStream << name;
tagStatus = tag_content;
return;
}
outStream << ' ' << attribId.getName() << "=\"";
outStream << name;
outStream << "\"";
}
/// The integer is encoded, 7-bits per byte, starting with the most significant 7-bits. /// The integer is encoded, 7-bits per byte, starting with the most significant 7-bits.
/// The integer is decode from the \e current position, and the position is advanced. /// The integer is decode from the \e current position, and the position is advanced.
/// \param len is the number of bytes to extract /// \param len is the number of bytes to extract
@ -598,6 +671,27 @@ void PackedDecode::skipAttributeRemaining(uint1 typeByte)
advancePosition(curPos, length); // Skip -length- data advancePosition(curPos, length); // Skip -length- data
} }
/// Set decoder to beginning of the stream. Add padding to end of the stream.
/// \param bufPos is the number of bytes used by the last input buffer
void PackedDecode::endIngest(int4 bufPos)
{
endPos.seqIter = inStream.begin(); // Set position to beginning of stream
if (endPos.seqIter != inStream.end()) {
endPos.current = (*endPos.seqIter).start;
endPos.end = (*endPos.seqIter).end;
// Make sure there is at least one character after ingested buffer
if (bufPos == BUFFER_SIZE) {
// Last buffer was entirely filled
uint1 *endbuf = new uint1[1]; // Add one more buffer
inStream.emplace_back(endbuf,endbuf + 1);
bufPos = 0;
}
uint1 *buf = inStream.back().start;
buf[bufPos] = ELEMENT_END;
}
}
PackedDecode::~PackedDecode(void) PackedDecode::~PackedDecode(void)
{ {
@ -612,25 +706,11 @@ void PackedDecode::ingestStream(istream &s)
{ {
int4 gcount = 0; int4 gcount = 0;
while(s.peek() > 0) { while(s.peek() > 0) {
uint1 *buf = new uint1[BUFFER_SIZE + 1]; uint1 *buf = allocateNextInputBuffer(1);
inStream.emplace_back(buf,buf+BUFFER_SIZE);
s.get((char *)buf,BUFFER_SIZE+1,'\0'); s.get((char *)buf,BUFFER_SIZE+1,'\0');
gcount = s.gcount(); gcount = s.gcount();
} }
endPos.seqIter = inStream.begin(); endIngest(gcount);
if (endPos.seqIter != inStream.end()) {
endPos.current = (*endPos.seqIter).start;
endPos.end = (*endPos.seqIter).end;
// Make sure there is at least one character after ingested buffer
if (gcount == BUFFER_SIZE) {
// Last buffer was entirely filled
uint1 *endbuf = new uint1[1]; // Add one more buffer
inStream.emplace_back(endbuf,endbuf + 1);
gcount = 0;
}
uint1 *buf = inStream.back().start;
buf[gcount] = ELEMENT_END;
}
} }
uint4 PackedDecode::peekElement(void) uint4 PackedDecode::peekElement(void)
@ -959,6 +1039,24 @@ AddrSpace *PackedDecode::readSpace(const AttributeId &attribId)
return res; return res;
} }
OpCode PackedDecode::readOpcode(void)
{
int4 val = (int4)readSignedInteger();
if (val < 0 || val >= CPUI_MAX)
throw DecoderError("Bad encoded OpCode");
return (OpCode)val;
}
OpCode PackedDecode::readOpcode(AttributeId &attribId)
{
findMatchingAttribute(attribId);
OpCode opc = readOpcode();
curPos = startPos;
return opc;
}
/// The value is either an unsigned integer, an address space index, or (the absolute value of) a signed integer. /// The value is either an unsigned integer, an address space index, or (the absolute value of) a signed integer.
/// A type header is passed in with the particular type code for the value already filled in. /// A type header is passed in with the particular type code for the value already filled in.
/// This method then fills in the length code, outputs the full type header and the encoded bytes of the integer. /// This method then fills in the length code, outputs the full type header and the encoded bytes of the integer.
@ -973,7 +1071,7 @@ void PackedEncode::writeInteger(uint1 typeByte,uint8 val)
lenCode = 0; lenCode = 0;
sa = -1; sa = -1;
} }
if (val < 0x800000000) { else if (val < 0x800000000) {
if (val < 0x200000) { if (val < 0x200000) {
if (val < 0x80) { if (val < 0x80) {
lenCode = 1; // 7-bits lenCode = 1; // 7-bits
@ -1119,6 +1217,13 @@ void PackedEncode::writeSpace(const AttributeId &attribId,const AddrSpace *spc)
} }
} }
void PackedEncode::writeOpcode(const AttributeId &attribId,OpCode opc)
{
writeHeader(ATTRIBUTE, attribId.getId());
writeInteger((TYPECODE_SIGNEDINT_POSITIVE << TYPECODE_SHIFT), opc);
}
// Common attributes. Attributes with multiple uses // Common attributes. Attributes with multiple uses
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1); AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
AttributeId ATTRIB_ALIGN = AttributeId("align",2); AttributeId ATTRIB_ALIGN = AttributeId("align",2);

View file

@ -17,6 +17,7 @@
#define __MARSHAL_HH__ #define __MARSHAL_HH__
#include "xml.hh" #include "xml.hh"
#include "opcodes.hh"
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
@ -43,11 +44,11 @@ class AttributeId {
string name; ///< The name of the attribute string name; ///< The name of the attribute
uint4 id; ///< The (internal) id of the attribute uint4 id; ///< The (internal) id of the attribute
public: public:
AttributeId(const string &nm,uint4 i); ///< Construct given a name and id AttributeId(const string &nm,uint4 i,int4 scope=0); ///< Construct given a name and id
const string &getName(void) const { return name; } ///< Get the attribute's name const string &getName(void) const { return name; } ///< Get the attribute's name
uint4 getId(void) const { return id; } ///< Get the attribute's id uint4 getId(void) const { return id; } ///< Get the attribute's id
bool operator==(const AttributeId &op2) const { return (id == op2.id); } ///< Test equality with another AttributeId bool operator==(const AttributeId &op2) const { return (id == op2.id); } ///< Test equality with another AttributeId
static uint4 find(const string &nm); ///< Find the id associated with a specific attribute name static uint4 find(const string &nm,int4 scope); ///< Find the id associated with a specific attribute name
static void initialize(void); ///< Populate a hashtable with all AttributeId objects static void initialize(void); ///< Populate a hashtable with all AttributeId objects
friend bool operator==(uint4 id,const AttributeId &op2) { return (id == op2.id); } ///< Test equality of a raw integer id with an AttributeId friend bool operator==(uint4 id,const AttributeId &op2) { return (id == op2.id); } ///< Test equality of a raw integer id with an AttributeId
friend bool operator==(const AttributeId &op1,uint4 id) { return (op1.id == id); } ///< Test equality of an AttributeId with a raw integer id friend bool operator==(const AttributeId &op1,uint4 id) { return (op1.id == id); } ///< Test equality of an AttributeId with a raw integer id
@ -67,11 +68,11 @@ class ElementId {
string name; ///< The name of the element string name; ///< The name of the element
uint4 id; ///< The (internal) id of the attribute uint4 id; ///< The (internal) id of the attribute
public: public:
ElementId(const string &nm,uint4 i); ///< Construct given a name and id ElementId(const string &nm,uint4 i,int4 scope=0); ///< Construct given a name and id
const string &getName(void) const { return name; } ///< Get the element's name const string &getName(void) const { return name; } ///< Get the element's name
uint4 getId(void) const { return id; } ///< Get the element's id uint4 getId(void) const { return id; } ///< Get the element's id
bool operator==(const ElementId &op2) const { return (id == op2.id); } ///< Test equality with another ElementId bool operator==(const ElementId &op2) const { return (id == op2.id); } ///< Test equality with another ElementId
static uint4 find(const string &nm); ///< Find the id associated with a specific element name static uint4 find(const string &nm,int4 scope); ///< Find the id associated with a specific element name
static void initialize(void); ///< Populate a hashtable with all ElementId objects static void initialize(void); ///< Populate a hashtable with all ElementId objects
friend bool operator==(uint4 id,const ElementId &op2) { return (id == op2.id); } ///< Test equality of a raw integer id with an ElementId friend bool operator==(uint4 id,const ElementId &op2) { return (id == op2.id); } ///< Test equality of a raw integer id with an ElementId
friend bool operator==(const ElementId &op1,uint4 id) { return (op1.id == id); } ///< Test equality of an ElementId with a raw integer id friend bool operator==(const ElementId &op1,uint4 id) { return (op1.id == id); } ///< Test equality of an ElementId with a raw integer id
@ -269,6 +270,21 @@ public:
/// \return the address space associated with the attribute /// \return the address space associated with the attribute
virtual AddrSpace *readSpace(const AttributeId &attribId)=0; virtual AddrSpace *readSpace(const AttributeId &attribId)=0;
/// \brief Parse the current attribute as a p-code OpCode
///
/// The last attribute, as returned by getNextAttributeId, is returned as an OpCode.
/// \return the OpCode associated with the current attribute
virtual OpCode readOpcode(void)=0;
/// \brief Find the specific attribute in the current element and return it as an OpCode
///
/// Search attributes from the current element for a match to the given attribute id.
/// Return this attribute as an OpCode. If there is no matching attribute id, an exception is thrown.
/// Parse via getNextAttributeId is reset.
/// \param attribId is the specific attribute id to match
/// \return the OpCode associated with the attribute
virtual OpCode readOpcode(AttributeId &attribId)=0;
/// \brief Skip parsing of the next element /// \brief Skip parsing of the next element
/// ///
/// The element skipped is the one that would be opened by the next call to openElement. /// The element skipped is the one that would be opened by the next call to openElement.
@ -350,6 +366,13 @@ public:
/// \param attribId is the given AttributeId annotation /// \param attribId is the given AttributeId annotation
/// \param spc is the address space to encode /// \param spc is the address space to encode
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc)=0; virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc)=0;
/// \brief Write a p-code operation opcode into the encoding, associating it with the given annotation
///
/// \param attribId is the given annotation
/// \param opc is the opcode
virtual void writeOpcode(const AttributeId &attribId,OpCode opc)=0;
}; };
/// \brief An XML based decoder /// \brief An XML based decoder
@ -363,12 +386,13 @@ class XmlDecode : public Decoder {
vector<const Element *> elStack; ///< Stack of currently \e open elements vector<const Element *> elStack; ///< Stack of currently \e open elements
vector<List::const_iterator> iterStack; ///< Index of next child for each \e open element vector<List::const_iterator> iterStack; ///< Index of next child for each \e open element
int4 attributeIndex; ///< Position of \e current attribute to parse (in \e current element) int4 attributeIndex; ///< Position of \e current attribute to parse (in \e current element)
int4 scope; ///< Scope of element/attribute tags to look up
int4 findMatchingAttribute(const Element *el,const string &attribName); int4 findMatchingAttribute(const Element *el,const string &attribName);
public: public:
XmlDecode(const AddrSpaceManager *spc,const Element *root) : Decoder(spc) { XmlDecode(const AddrSpaceManager *spc,const Element *root,int4 sc=0) : Decoder(spc) {
document = (Document *)0; rootElement = root; attributeIndex = -1; } ///< Constructor with preparsed root document = (Document *)0; rootElement = root; attributeIndex = -1; scope = sc; } ///< Constructor with preparsed root
XmlDecode(const AddrSpaceManager *spc) : Decoder(spc) { XmlDecode(const AddrSpaceManager *spc,int4 sc=0) : Decoder(spc) {
document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; scope=sc; } ///< Constructor for use with ingestStream
const Element *getCurrentXmlElement(void) const { return elStack.back(); } ///< Get pointer to underlying XML element object const Element *getCurrentXmlElement(void) const { return elStack.back(); } ///< Get pointer to underlying XML element object
virtual ~XmlDecode(void); virtual ~XmlDecode(void);
virtual void ingestStream(istream &s); virtual void ingestStream(istream &s);
@ -392,6 +416,8 @@ public:
virtual string readString(const AttributeId &attribId); virtual string readString(const AttributeId &attribId);
virtual AddrSpace *readSpace(void); virtual AddrSpace *readSpace(void);
virtual AddrSpace *readSpace(const AttributeId &attribId); virtual AddrSpace *readSpace(const AttributeId &attribId);
virtual OpCode readOpcode(void);
virtual OpCode readOpcode(AttributeId &attribId);
}; };
/// \brief An XML based encoder /// \brief An XML based encoder
@ -400,10 +426,20 @@ public:
/// receive the XML document as calls are made on the encoder. /// receive the XML document as calls are made on the encoder.
class XmlEncode : public Encoder { class XmlEncode : public Encoder {
friend class XmlDecode; friend class XmlDecode;
enum {
tag_start = 0, ///< Tag has been opened, attributes can be written
tag_content = 1, ///< Opening tag and content have been written
tag_stop = 2 ///< No tag is currently being written
};
static const char spaces[]; ///< Array of ' ' characters for emitting indents
static const int4 MAX_SPACES;
ostream &outStream; ///< The stream receiving the encoded data ostream &outStream; ///< The stream receiving the encoded data
bool elementTagIsOpen; ///< If \b true, new attributes can be written to the current element int4 tagStatus; ///< Stage of writing an element tag
int4 depth; ///< Depth of open elements
bool doFormatting; ///< \b true if encoder should indent and emit newlines
void newLine(void); ///< Emit a newline and proper indenting for the next tag
public: public:
XmlEncode(ostream &s) : outStream(s) { elementTagIsOpen = false; } ///< Construct from a stream XmlEncode(ostream &s,bool doFormat=true) : outStream(s) { depth=0; tagStatus=tag_stop; doFormatting=doFormat; } ///< Construct from a stream
virtual void openElement(const ElementId &elemId); virtual void openElement(const ElementId &elemId);
virtual void closeElement(const ElementId &elemId); virtual void closeElement(const ElementId &elemId);
virtual void writeBool(const AttributeId &attribId,bool val); virtual void writeBool(const AttributeId &attribId,bool val);
@ -412,6 +448,7 @@ public:
virtual void writeString(const AttributeId &attribId,const string &val); virtual void writeString(const AttributeId &attribId,const string &val);
virtual void writeStringIndexed(const AttributeId &attribId,uint4 index,const string &val); virtual void writeStringIndexed(const AttributeId &attribId,uint4 index,const string &val);
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc); virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc);
virtual void writeOpcode(const AttributeId &attribId,OpCode opc);
}; };
/// \brief Protocol format for PackedEncode and PackedDecode classes /// \brief Protocol format for PackedEncode and PackedDecode classes
@ -505,6 +542,9 @@ private:
void findMatchingAttribute(const AttributeId &attribId); ///< Find attribute matching the given id in open element void findMatchingAttribute(const AttributeId &attribId); ///< Find attribute matching the given id in open element
void skipAttribute(void); ///< Skip over the attribute at the current position void skipAttribute(void); ///< Skip over the attribute at the current position
void skipAttributeRemaining(uint1 typeByte); ///< Skip over remaining attribute data, after a mismatch void skipAttributeRemaining(uint1 typeByte); ///< Skip over remaining attribute data, after a mismatch
protected:
uint1 *allocateNextInputBuffer(int4 pad); ///< Allocate the next chunk of space in the input stream
void endIngest(int4 bufPos); ///< Finish set up for reading input stream
public: public:
PackedDecode(const AddrSpaceManager *spcManager) : Decoder(spcManager) {} ///< Constructor PackedDecode(const AddrSpaceManager *spcManager) : Decoder(spcManager) {} ///< Constructor
virtual ~PackedDecode(void); virtual ~PackedDecode(void);
@ -529,6 +569,8 @@ public:
virtual string readString(const AttributeId &attribId); virtual string readString(const AttributeId &attribId);
virtual AddrSpace *readSpace(void); virtual AddrSpace *readSpace(void);
virtual AddrSpace *readSpace(const AttributeId &attribId); virtual AddrSpace *readSpace(const AttributeId &attribId);
virtual OpCode readOpcode(void);
virtual OpCode readOpcode(AttributeId &attribId);
}; };
/// \brief A byte-based encoder designed to marshal from the decompiler efficiently /// \brief A byte-based encoder designed to marshal from the decompiler efficiently
@ -548,6 +590,7 @@ public:
virtual void writeString(const AttributeId &attribId,const string &val); virtual void writeString(const AttributeId &attribId,const string &val);
virtual void writeStringIndexed(const AttributeId &attribId,uint4 index,const string &val); virtual void writeStringIndexed(const AttributeId &attribId,uint4 index,const string &val);
virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc); virtual void writeSpace(const AttributeId &attribId,const AddrSpace *spc);
virtual void writeOpcode(const AttributeId &attribId,OpCode opc);
}; };
/// An exception is thrown if the position currently points to the last byte in the stream /// An exception is thrown if the position currently points to the last byte in the stream
@ -602,6 +645,17 @@ inline void PackedDecode::advancePosition(Position &pos,int4 skip)
pos.current += skip; pos.current += skip;
} }
/// Allocate an array of BUFFER_SIZE bytes and add it to the in-memory stream
/// \param pad is the number of bytes of padding to add to the allocation size, above BUFFER_SIZE
/// \return the newly allocated buffer
inline uint1 *PackedDecode::allocateNextInputBuffer(int4 pad)
{
uint1 *buf = new uint1[BUFFER_SIZE + pad];
inStream.emplace_back(buf,buf+BUFFER_SIZE);
return buf;
}
/// \param header is the type of header /// \param header is the type of header
/// \param id is the id associated with the element or attribute /// \param id is the id associated with the element or attribute
inline void PackedEncode::writeHeader(uint1 header,uint4 id) inline void PackedEncode::writeHeader(uint1 header,uint4 id)
@ -624,29 +678,35 @@ extern ElementId ELEM_UNKNOWN; ///< Special element to represent an element wit
extern AttributeId ATTRIB_UNKNOWN; ///< Special attribute to represent an attribute with an unrecognized name extern AttributeId ATTRIB_UNKNOWN; ///< Special attribute to represent an attribute with an unrecognized name
extern AttributeId ATTRIB_CONTENT; ///< Special attribute for XML text content of an element extern AttributeId ATTRIB_CONTENT; ///< Special attribute for XML text content of an element
/// The name is looked up in the global list of all attributes. If the attribute is not in the list, a special /// The name is looked up in the scoped list of attributes. If the attribute is not in the list, a special
/// placeholder attribute, ATTRIB_UNKNOWN, is returned as a placeholder for attributes with unrecognized names. /// placeholder attribute, ATTRIB_UNKNOWN, is returned as a placeholder for attributes with unrecognized names.
/// \param nm is the name of the attribute /// \param nm is the name of the attribute
/// \param scope is the id of the scope in which to lookup of the name
/// \return the associated id /// \return the associated id
inline uint4 AttributeId::find(const string &nm) inline uint4 AttributeId::find(const string &nm,int4 scope)
{ {
unordered_map<string,uint4>::const_iterator iter = lookupAttributeId.find(nm); if (scope == 0) { // Current only support reverse look up for scope 0
if (iter != lookupAttributeId.end()) unordered_map<string,uint4>::const_iterator iter = lookupAttributeId.find(nm);
return (*iter).second; if (iter != lookupAttributeId.end())
return (*iter).second;
}
return ATTRIB_UNKNOWN.id; return ATTRIB_UNKNOWN.id;
} }
/// The name is looked up in the global list of all elements. If the element is not in the list, a special /// The name is looked up in the scoped list of elements. If the element is not in the list, a special
/// placeholder element, ELEM_UNKNOWN, is returned as a placeholder for elements with unrecognized names. /// placeholder element, ELEM_UNKNOWN, is returned as a placeholder for elements with unrecognized names.
/// \param nm is the name of the element /// \param nm is the name of the element
/// \param scope is the id of the scope in which to search
/// \return the associated id /// \return the associated id
inline uint4 ElementId::find(const string &nm) inline uint4 ElementId::find(const string &nm,int4 scope)
{ {
unordered_map<string,uint4>::const_iterator iter = lookupElementId.find(nm); if (scope == 0) {
if (iter != lookupElementId.end()) unordered_map<string,uint4>::const_iterator iter = lookupElementId.find(nm);
return (*iter).second; if (iter != lookupElementId.end())
return (*iter).second;
}
return ELEM_UNKNOWN.id; return ELEM_UNKNOWN.id;
} }

View file

@ -31,7 +31,7 @@ const string IopSpace::NAME = "iop";
/// \param t is the associated processor translator /// \param t is the associated processor translator
/// \param ind is the associated index /// \param ind is the associated index
IopSpace::IopSpace(AddrSpaceManager *m,const Translate *t,int4 ind) IopSpace::IopSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
: AddrSpace(m,t,IPTR_IOP,NAME,sizeof(void *),1,ind,0,1) : AddrSpace(m,t,IPTR_IOP,NAME,false,sizeof(void *),1,ind,0,1,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
@ -58,12 +58,6 @@ void IopSpace::printRaw(ostream &s,uintb offset) const
bl->getStart().printRaw(s); bl->getStart().printRaw(s);
} }
void IopSpace::saveXml(ostream &s) const
{
throw LowlevelError("Should never encode iop space to stream");
}
void IopSpace::decode(Decoder &decoder) void IopSpace::decode(Decoder &decoder)
{ {

View file

@ -40,7 +40,6 @@ public:
virtual void encodeAttributes(Encoder &encoder,uintb offset) const { encoder.writeString(ATTRIB_SPACE, "iop"); } virtual void encodeAttributes(Encoder &encoder,uintb offset) const { encoder.writeString(ATTRIB_SPACE, "iop"); }
virtual void encodeAttributes(Encoder &encoder,uintb offset,int4 size) const { encoder.writeString(ATTRIB_SPACE, "iop"); } virtual void encodeAttributes(Encoder &encoder,uintb offset,int4 size) const { encoder.writeString(ATTRIB_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 decode(Decoder &decoder); virtual void decode(Decoder &decoder);
static const string NAME; ///< Reserved name for the iop space static const string NAME; ///< Reserved name for the iop space
}; };

View file

@ -84,7 +84,7 @@ bool ArchOption::onOrOff(const string &p)
void OptionDatabase::registerOption(ArchOption *option) void OptionDatabase::registerOption(ArchOption *option)
{ {
uint4 id = ElementId::find(option->getName()); // Option name must match a known element name uint4 id = ElementId::find(option->getName(),0); // Option name must match a known element name
optionmap[id] = option; optionmap[id] = option;
} }

View file

@ -290,39 +290,6 @@ void ConstTpl::transfer(const vector<HandleTpl *> &params)
} }
} }
void ConstTpl::printHandleSelector(ostream &s,v_field val)
{
switch(val) {
case v_space:
s << "space";
break;
case v_offset:
s << "offset";
break;
case v_size:
s << "size";
break;
case v_offset_plus:
s << "offset_plus";
break;
}
}
ConstTpl::v_field ConstTpl::readHandleSelector(const string &name)
{
if (name == "space")
return v_space;
if (name == "offset")
return v_offset;
if (name == "size")
return v_size;
if (name == "offset_plus")
return v_offset_plus;
throw LowlevelError("Bad handle selector");
}
void ConstTpl::changeHandleIndex(const vector<int4> &handmap) void ConstTpl::changeHandleIndex(const vector<int4> &handmap)
{ {
@ -330,120 +297,129 @@ void ConstTpl::changeHandleIndex(const vector<int4> &handmap)
value.handle_index = handmap[value.handle_index]; value.handle_index = handmap[value.handle_index];
} }
void ConstTpl::saveXml(ostream &s) const void ConstTpl::encode(Encoder &encoder) const
{ {
s << "<const_tpl type=\"";
switch(type) { switch(type) {
case real: case real:
s << "real\" val=\"0x" << hex << value_real << "\"/>"; encoder.openElement(sla::ELEM_CONST_REAL);
encoder.writeUnsignedInteger(sla::ATTRIB_VAL, value_real);
encoder.closeElement(sla::ELEM_CONST_REAL);
break; break;
case handle: case handle:
s << "handle\" val=\"" << dec << value.handle_index << "\" "; encoder.openElement(sla::ELEM_CONST_HANDLE);
s << "s=\""; encoder.writeSignedInteger(sla::ATTRIB_VAL, value.handle_index);
printHandleSelector(s,select); encoder.writeSignedInteger(sla::ATTRIB_S, select);
s << "\"";
if (select == v_offset_plus) if (select == v_offset_plus)
s << " plus=\"0x" << hex << value_real << "\""; encoder.writeUnsignedInteger(sla::ATTRIB_PLUS, value_real);
s << "/>"; encoder.closeElement(sla::ELEM_CONST_HANDLE);
break; break;
case j_start: case j_start:
s << "start\"/>"; encoder.openElement(sla::ELEM_CONST_START);
encoder.closeElement(sla::ELEM_CONST_START);
break; break;
case j_next: case j_next:
s << "next\"/>"; encoder.openElement(sla::ELEM_CONST_NEXT);
encoder.closeElement(sla::ELEM_CONST_NEXT);
break; break;
case j_next2: case j_next2:
s << "next2\"/>"; encoder.openElement(sla::ELEM_CONST_NEXT2);
encoder.closeElement(sla::ELEM_CONST_NEXT2);
break; break;
case j_curspace: case j_curspace:
s << "curspace\"/>"; encoder.openElement(sla::ELEM_CONST_CURSPACE);
encoder.closeElement(sla::ELEM_CONST_CURSPACE);
break; break;
case j_curspace_size: case j_curspace_size:
s << "curspace_size\"/>"; encoder.openElement(sla::ELEM_CONST_CURSPACE_SIZE);
encoder.closeElement(sla::ELEM_CONST_CURSPACE_SIZE);
break; break;
case spaceid: case spaceid:
s << "spaceid\" name=\"" << value.spaceid->getName() << "\"/>"; encoder.openElement(sla::ELEM_CONST_SPACEID);
encoder.writeSpace(sla::ATTRIB_SPACE, value.spaceid);
encoder.closeElement(sla::ELEM_CONST_SPACEID);
break; break;
case j_relative: case j_relative:
s << "relative\" val=\"0x" << hex << value_real << "\"/>"; encoder.openElement(sla::ELEM_CONST_RELATIVE);
encoder.writeUnsignedInteger(sla::ATTRIB_VAL, value_real);
encoder.closeElement(sla::ELEM_CONST_RELATIVE);
break; break;
case j_flowref: case j_flowref:
s << "flowref\"/>"; encoder.openElement(sla::ELEM_CONST_FLOWREF);
encoder.closeElement(sla::ELEM_CONST_FLOWREF);
break; break;
case j_flowref_size: case j_flowref_size:
s << "flowref_size\"/>"; encoder.openElement(sla::ELEM_CONST_FLOWREF_SIZE);
encoder.closeElement(sla::ELEM_CONST_FLOWREF_SIZE);
break; break;
case j_flowdest: case j_flowdest:
s << "flowdest\"/>"; encoder.openElement(sla::ELEM_CONST_FLOWDEST);
encoder.closeElement(sla::ELEM_CONST_FLOWDEST);
break; break;
case j_flowdest_size: case j_flowdest_size:
s << "flowdest_size\"/>"; encoder.openElement(sla::ELEM_CONST_FLOWDEST_SIZE);
encoder.closeElement(sla::ELEM_CONST_FLOWDEST_SIZE);
break; break;
} }
} }
void ConstTpl::restoreXml(const Element *el,const AddrSpaceManager *manage) void ConstTpl::decode(Decoder &decoder)
{ {
const string &typestring(el->getAttributeValue("type")); uint4 el = decoder.openElement();
if (typestring == "real") { if (el == sla::ELEM_CONST_REAL) {
type = real; type = real;
istringstream s(el->getAttributeValue("val")); value_real = decoder.readUnsignedInteger(sla::ATTRIB_VAL);
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> value_real;
} }
else if (typestring=="handle") { else if (el == sla::ELEM_CONST_HANDLE) {
type = handle; type = handle;
istringstream s(el->getAttributeValue("val")); value.handle_index = decoder.readSignedInteger(sla::ATTRIB_VAL);
s.unsetf(ios::dec | ios::hex | ios::oct); uint4 selectInt = decoder.readSignedInteger(sla::ATTRIB_S);
s >> value.handle_index; if (selectInt > v_offset_plus)
select = readHandleSelector(el->getAttributeValue("s")); throw DecoderError("Bad handle selector encoding");
select = (v_field)selectInt;
if (select == v_offset_plus) { if (select == v_offset_plus) {
istringstream s2(el->getAttributeValue("plus")); value_real = decoder.readUnsignedInteger(sla::ATTRIB_PLUS);
s2.unsetf(ios::dec | ios::hex | ios::oct);
s2 >> value_real;
} }
} }
else if (typestring=="start") { else if (el == sla::ELEM_CONST_START) {
type = j_start; type = j_start;
} }
else if (typestring=="next") { else if (el == sla::ELEM_CONST_NEXT) {
type = j_next; type = j_next;
} }
else if (typestring=="next2") { else if (el == sla::ELEM_CONST_NEXT2) {
type = j_next2; type = j_next2;
} }
else if (typestring=="curspace") { else if (el == sla::ELEM_CONST_CURSPACE) {
type = j_curspace; type = j_curspace;
} }
else if (typestring=="curspace_size") { else if (el == sla::ELEM_CONST_CURSPACE_SIZE) {
type = j_curspace_size; type = j_curspace_size;
} }
else if (typestring=="spaceid") { else if (el == sla::ELEM_CONST_SPACEID) {
type = spaceid; type = spaceid;
value.spaceid = manage->getSpaceByName(el->getAttributeValue("name")); value.spaceid = decoder.readSpace(sla::ATTRIB_SPACE);
} }
else if (typestring=="relative") { else if (el == sla::ELEM_CONST_RELATIVE) {
type = j_relative; type = j_relative;
istringstream s(el->getAttributeValue("val")); value_real = decoder.readUnsignedInteger(sla::ATTRIB_VAL);
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> value_real;
} }
else if (typestring == "flowref") { else if (el == sla::ELEM_CONST_FLOWREF) {
type = j_flowref; type = j_flowref;
} }
else if (typestring == "flowref_size") { else if (el == sla::ELEM_CONST_FLOWREF_SIZE) {
type = j_flowref_size; type = j_flowref_size;
} }
else if (typestring == "flowdest") { else if (el == sla::ELEM_CONST_FLOWDEST) {
type = j_flowdest; type = j_flowdest;
} }
else if (typestring == "flowdest_size") { else if (el == sla::ELEM_CONST_FLOWDEST_SIZE) {
type = j_flowdest_size; type = j_flowdest_size;
} }
else else
throw LowlevelError("Bad constant type"); throw LowlevelError("Bad constant type");
decoder.closeElement(el);
} }
VarnodeTpl::VarnodeTpl(int4 hand,bool zerosize) : VarnodeTpl::VarnodeTpl(int4 hand,bool zerosize) :
@ -544,27 +520,24 @@ bool VarnodeTpl::adjustTruncation(int4 sz,bool isbigendian)
return true; return true;
} }
void VarnodeTpl::saveXml(ostream &s) const void VarnodeTpl::encode(Encoder &encoder) const
{ {
s << "<varnode_tpl>"; encoder.openElement(sla::ELEM_VARNODE_TPL);
space.saveXml(s); space.encode(encoder);
offset.saveXml(s); offset.encode(encoder);
size.saveXml(s); size.encode(encoder);
s << "</varnode_tpl>\n"; encoder.closeElement(sla::ELEM_VARNODE_TPL);
} }
void VarnodeTpl::restoreXml(const Element *el,const AddrSpaceManager *manage) void VarnodeTpl::decode(Decoder &decoder)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement(sla::ELEM_VARNODE_TPL);
List::const_iterator iter; space.decode(decoder);
iter = list.begin(); offset.decode(decoder);
space.restoreXml(*iter,manage); size.decode(decoder);
++iter; decoder.closeElement(el);
offset.restoreXml(*iter,manage);
++iter;
size.restoreXml(*iter,manage);
} }
bool VarnodeTpl::operator<(const VarnodeTpl &op2) const bool VarnodeTpl::operator<(const VarnodeTpl &op2) const
@ -633,39 +606,32 @@ void HandleTpl::changeHandleIndex(const vector<int4> &handmap)
temp_offset.changeHandleIndex(handmap); temp_offset.changeHandleIndex(handmap);
} }
void HandleTpl::saveXml(ostream &s) const void HandleTpl::encode(Encoder &encoder) const
{ {
s << "<handle_tpl>"; encoder.openElement(sla::ELEM_HANDLE_TPL);
space.saveXml(s); space.encode(encoder);
size.saveXml(s); size.encode(encoder);
ptrspace.saveXml(s); ptrspace.encode(encoder);
ptroffset.saveXml(s); ptroffset.encode(encoder);
ptrsize.saveXml(s); ptrsize.encode(encoder);
temp_space.saveXml(s); temp_space.encode(encoder);
temp_offset.saveXml(s); temp_offset.encode(encoder);
s << "</handle_tpl>\n"; encoder.closeElement(sla::ELEM_HANDLE_TPL);
} }
void HandleTpl::restoreXml(const Element *el,const AddrSpaceManager *manage) void HandleTpl::decode(Decoder &decoder)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement(sla::ELEM_HANDLE_TPL);
List::const_iterator iter; space.decode(decoder);
iter = list.begin(); size.decode(decoder);
space.restoreXml(*iter,manage); ptrspace.decode(decoder);
++iter; ptroffset.decode(decoder);
size.restoreXml(*iter,manage); ptrsize.decode(decoder);
++iter; temp_space.decode(decoder);
ptrspace.restoreXml(*iter,manage); temp_offset.decode(decoder);
++iter; decoder.closeElement(el);
ptroffset.restoreXml(*iter,manage);
++iter;
ptrsize.restoreXml(*iter,manage);
++iter;
temp_space.restoreXml(*iter,manage);
++iter;
temp_offset.restoreXml(*iter,manage);
} }
OpTpl::~OpTpl(void) OpTpl::~OpTpl(void)
@ -710,39 +676,43 @@ void OpTpl::changeHandleIndex(const vector<int4> &handmap)
(*iter)->changeHandleIndex(handmap); (*iter)->changeHandleIndex(handmap);
} }
void OpTpl::saveXml(ostream &s) const void OpTpl::encode(Encoder &encoder) const
{ {
s << "<op_tpl code=\"" << get_opname(opc) << "\">"; encoder.openElement(sla::ELEM_OP_TPL);
if (output == (VarnodeTpl *)0) encoder.writeOpcode(sla::ATTRIB_CODE, opc);
s << "<null/>\n"; if (output == (VarnodeTpl *)0) {
encoder.openElement(sla::ELEM_NULL);
encoder.closeElement(sla::ELEM_NULL);
}
else else
output->saveXml(s); output->encode(encoder);
for(int4 i=0;i<input.size();++i) for(int4 i=0;i<input.size();++i)
input[i]->saveXml(s); input[i]->encode(encoder);
s << "</op_tpl>\n"; encoder.closeElement(sla::ELEM_OP_TPL);
} }
void OpTpl::restoreXml(const Element *el,const AddrSpaceManager *manage) void OpTpl::decode(Decoder &decoder)
{ {
opc = get_opcode(el->getAttributeValue("code")); uint4 el = decoder.openElement(sla::ELEM_OP_TPL);
const List &list(el->getChildren()); opc = decoder.readOpcode(sla::ATTRIB_CODE);
List::const_iterator iter; uint4 subel = decoder.peekElement();
iter = list.begin(); if (subel == sla::ELEM_NULL) {
if ((*iter)->getName() == "null") decoder.openElement();
decoder.closeElement(subel);
output = (VarnodeTpl *)0; output = (VarnodeTpl *)0;
}
else { else {
output = new VarnodeTpl(); output = new VarnodeTpl();
output->restoreXml(*iter,manage); output->decode(decoder);
} }
++iter; while(decoder.peekElement() != 0) {
while(iter != list.end()) {
VarnodeTpl *vn = new VarnodeTpl(); VarnodeTpl *vn = new VarnodeTpl();
vn->restoreXml(*iter,manage); vn->decode(decoder);
input.push_back(vn); input.push_back(vn);
++iter;
} }
decoder.closeElement(el);
} }
ConstructTpl::~ConstructTpl(void) ConstructTpl::~ConstructTpl(void)
@ -882,63 +852,61 @@ void ConstructTpl::deleteOps(const vector<int4> &indices)
vec.pop_back(); vec.pop_back();
} }
void ConstructTpl::saveXml(ostream &s,int4 sectionid) const void ConstructTpl::encode(Encoder &encoder,int4 sectionid) const
{ {
s << "<construct_tpl"; encoder.openElement(sla::ELEM_CONSTRUCT_TPL);
if (sectionid >=0 ) if (sectionid >=0 )
s << " section=\"" << dec << sectionid << "\""; encoder.writeSignedInteger(sla::ATTRIB_SECTION, sectionid);
if (delayslot != 0) if (delayslot != 0)
s << " delay=\"" << dec << delayslot << "\""; encoder.writeSignedInteger(sla::ATTRIB_DELAY, delayslot);
if (numlabels != 0) if (numlabels != 0)
s << " labels=\"" << dec << numlabels << "\""; encoder.writeSignedInteger(sla::ATTRIB_LABELS, numlabels);
s << ">\n";
if (result != (HandleTpl *)0) if (result != (HandleTpl *)0)
result->saveXml(s); result->encode(encoder);
else else {
s << "<null/>"; encoder.openElement(sla::ELEM_NULL);
encoder.closeElement(sla::ELEM_NULL);
}
for(int4 i=0;i<vec.size();++i) for(int4 i=0;i<vec.size();++i)
vec[i]->saveXml(s); vec[i]->encode(encoder);
s << "</construct_tpl>\n"; encoder.closeElement(sla::ELEM_CONSTRUCT_TPL);
} }
int4 ConstructTpl::restoreXml(const Element *el,const AddrSpaceManager *manage) int4 ConstructTpl::decode(Decoder &decoder)
{ {
uint4 el = decoder.openElement(sla::ELEM_CONSTRUCT_TPL);
int4 sectionid = -1; int4 sectionid = -1;
for(int4 i=0;i<el->getNumAttributes();++i) { uint4 attrib = decoder.getNextAttributeId();
if (el->getAttributeName(i)=="delay") { while(attrib != 0) {
istringstream s(el->getAttributeValue(i)); if (attrib == sla::ATTRIB_DELAY) {
s.unsetf(ios::dec | ios::hex | ios::oct); delayslot = decoder.readSignedInteger();
s >> delayslot;
} }
else if (el->getAttributeName(i)=="labels") { else if (attrib == sla::ATTRIB_LABELS) {
istringstream s(el->getAttributeValue(i)); numlabels = decoder.readSignedInteger();
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> numlabels;
} }
else if (el->getAttributeName(i)=="section") { else if (attrib == sla::ATTRIB_SECTION) {
istringstream s(el->getAttributeValue(i)); sectionid = decoder.readSignedInteger();
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> sectionid;
} }
attrib = decoder.getNextAttributeId();
} }
const List &list(el->getChildren()); uint4 subel = decoder.peekElement();
List::const_iterator iter; if (subel == sla::ELEM_NULL) {
iter = list.begin(); decoder.openElement();
if ((*iter)->getName() == "null") decoder.closeElement(subel);
result = (HandleTpl *)0; result = (HandleTpl *)0;
}
else { else {
result = new HandleTpl(); result = new HandleTpl();
result->restoreXml(*iter,manage); result->decode(decoder);
} }
++iter; while(decoder.peekElement() != 0) {
while(iter != list.end()) {
OpTpl *op = new OpTpl(); OpTpl *op = new OpTpl();
op->restoreXml(*iter,manage); op->decode(decoder);
vec.push_back(op); vec.push_back(op);
++iter;
} }
decoder.closeElement(el);
return sectionid; return sectionid;
} }

View file

@ -17,6 +17,7 @@
#define __SEMANTICS_HH__ #define __SEMANTICS_HH__
#include "context.hh" #include "context.hh"
#include "slaformat.hh"
namespace ghidra { namespace ghidra {
@ -45,8 +46,6 @@ private:
} value; } value;
uintb value_real; uintb value_real;
v_field select; // Which part of handle to use as constant v_field select; // Which part of handle to use as constant
static void printHandleSelector(ostream &s,v_field val);
static v_field readHandleSelector(const string &name);
public: public:
ConstTpl(void) { type = real; value_real = 0; } ConstTpl(void) { type = real; value_real = 0; }
ConstTpl(const ConstTpl &op2) { ConstTpl(const ConstTpl &op2) {
@ -72,8 +71,8 @@ public:
void changeHandleIndex(const vector<int4> &handmap); void changeHandleIndex(const vector<int4> &handmap);
void fillinSpace(FixedHandle &hand,const ParserWalker &walker) const; void fillinSpace(FixedHandle &hand,const ParserWalker &walker) const;
void fillinOffset(FixedHandle &hand,const ParserWalker &walker) const; void fillinOffset(FixedHandle &hand,const ParserWalker &walker) const;
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,const AddrSpaceManager *manage); void decode(Decoder &decoder);
}; };
class VarnodeTpl { class VarnodeTpl {
@ -102,8 +101,8 @@ public:
bool isRelative(void) const { return (offset.getType() == ConstTpl::j_relative); } bool isRelative(void) const { return (offset.getType() == ConstTpl::j_relative); }
void changeHandleIndex(const vector<int4> &handmap); void changeHandleIndex(const vector<int4> &handmap);
bool adjustTruncation(int4 sz,bool isbigendian); bool adjustTruncation(int4 sz,bool isbigendian);
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,const AddrSpaceManager *manage); void decode(Decoder &decoder);
}; };
class HandleTpl { class HandleTpl {
@ -132,8 +131,8 @@ public:
void setTempOffset(uintb val) { temp_offset = ConstTpl(ConstTpl::real,val); } void setTempOffset(uintb val) { temp_offset = ConstTpl(ConstTpl::real,val); }
void fix(FixedHandle &hand,const ParserWalker &walker) const; void fix(FixedHandle &hand,const ParserWalker &walker) const;
void changeHandleIndex(const vector<int4> &handmap); void changeHandleIndex(const vector<int4> &handmap);
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,const AddrSpaceManager *manage); void decode(Decoder &decoder);
}; };
class OpTpl { class OpTpl {
@ -156,8 +155,8 @@ public:
void setInput(VarnodeTpl *vt,int4 slot) { input[slot] = vt; } void setInput(VarnodeTpl *vt,int4 slot) { input[slot] = vt; }
void removeInput(int4 index); void removeInput(int4 index);
void changeHandleIndex(const vector<int4> &handmap); void changeHandleIndex(const vector<int4> &handmap);
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,const AddrSpaceManager *manage); void decode(Decoder &decoder);
}; };
class ConstructTpl { class ConstructTpl {
@ -185,8 +184,8 @@ public:
void setInput(VarnodeTpl *vn,int4 index,int4 slot); void setInput(VarnodeTpl *vn,int4 index,int4 slot);
void setOutput(VarnodeTpl *vn,int4 index); void setOutput(VarnodeTpl *vn,int4 index);
void deleteOps(const vector<int4> &indices); void deleteOps(const vector<int4> &indices);
void saveXml(ostream &s,int4 sectionid) const; void encode(Encoder &encoder,int4 sectionid) const;
int4 restoreXml(const Element *el,const AddrSpaceManager *manage); int4 decode(Decoder &decoder);
}; };
class PcodeEmit; // Forward declaration for emitter class PcodeEmit; // Forward declaration for emitter

View file

@ -0,0 +1,258 @@
/* ###
* 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.
*/
#include "slaformat.hh"
namespace ghidra {
namespace sla {
const int4 FORMAT_SCOPE = 1;
const int4 FORMAT_VERSION = 4;
// ATTRIB_CONTEXT = 1 is reserved
AttributeId ATTRIB_VAL = AttributeId("val", 2, FORMAT_SCOPE);
AttributeId ATTRIB_ID = AttributeId("id", 3, FORMAT_SCOPE);
AttributeId ATTRIB_SPACE = AttributeId("space", 4, FORMAT_SCOPE);
AttributeId ATTRIB_S = AttributeId("s", 5, FORMAT_SCOPE);
AttributeId ATTRIB_OFF = AttributeId("off", 6, FORMAT_SCOPE);
AttributeId ATTRIB_CODE = AttributeId("code", 7, FORMAT_SCOPE);
AttributeId ATTRIB_MASK = AttributeId("mask", 8, FORMAT_SCOPE);
AttributeId ATTRIB_INDEX = AttributeId("index", 9, FORMAT_SCOPE);
AttributeId ATTRIB_NONZERO = AttributeId("nonzero", 10, FORMAT_SCOPE);
AttributeId ATTRIB_PIECE = AttributeId("piece", 11, FORMAT_SCOPE);
AttributeId ATTRIB_NAME = AttributeId("name", 12, FORMAT_SCOPE);
AttributeId ATTRIB_SCOPE = AttributeId("scope", 13, FORMAT_SCOPE);
AttributeId ATTRIB_STARTBIT = AttributeId("startbit", 14, FORMAT_SCOPE);
AttributeId ATTRIB_SIZE = AttributeId("size", 15, FORMAT_SCOPE);
AttributeId ATTRIB_TABLE = AttributeId("table", 16, FORMAT_SCOPE);
AttributeId ATTRIB_CT = AttributeId("ct", 17, FORMAT_SCOPE);
AttributeId ATTRIB_MINLEN = AttributeId("minlen", 18, FORMAT_SCOPE);
AttributeId ATTRIB_BASE = AttributeId("base", 19, FORMAT_SCOPE);
AttributeId ATTRIB_NUMBER = AttributeId("number", 20, FORMAT_SCOPE);
AttributeId ATTRIB_CONTEXT = AttributeId("context", 21, FORMAT_SCOPE);
AttributeId ATTRIB_PARENT = AttributeId("parent", 22, FORMAT_SCOPE);
AttributeId ATTRIB_SUBSYM = AttributeId("subsym", 23, FORMAT_SCOPE);
AttributeId ATTRIB_LINE = AttributeId("line", 24, FORMAT_SCOPE);
AttributeId ATTRIB_SOURCE = AttributeId("source", 25, FORMAT_SCOPE);
AttributeId ATTRIB_LENGTH = AttributeId("length", 26, FORMAT_SCOPE);
AttributeId ATTRIB_FIRST = AttributeId("first", 27, FORMAT_SCOPE);
AttributeId ATTRIB_PLUS = AttributeId("plus", 28, FORMAT_SCOPE);
AttributeId ATTRIB_SHIFT = AttributeId("shift", 29, FORMAT_SCOPE);
AttributeId ATTRIB_ENDBIT = AttributeId("endbit", 30, FORMAT_SCOPE);
AttributeId ATTRIB_SIGNBIT = AttributeId("signbit", 31, FORMAT_SCOPE);
AttributeId ATTRIB_ENDBYTE = AttributeId("endbyte", 32, FORMAT_SCOPE);
AttributeId ATTRIB_STARTBYTE = AttributeId("startbyte", 33, FORMAT_SCOPE);
AttributeId ATTRIB_VERSION = AttributeId("version", 34, FORMAT_SCOPE);
AttributeId ATTRIB_BIGENDIAN = AttributeId("bigendian", 35, FORMAT_SCOPE);
AttributeId ATTRIB_ALIGN = AttributeId("align", 36, FORMAT_SCOPE);
AttributeId ATTRIB_UNIQBASE = AttributeId("uniqbase", 37, FORMAT_SCOPE);
AttributeId ATTRIB_MAXDELAY = AttributeId("maxdelay", 38, FORMAT_SCOPE);
AttributeId ATTRIB_UNIQMASK = AttributeId("uniqmask", 39, FORMAT_SCOPE);
AttributeId ATTRIB_NUMSECTIONS = AttributeId("numsections", 40, FORMAT_SCOPE);
AttributeId ATTRIB_DEFAULTSPACE = AttributeId("defaultspace", 41, FORMAT_SCOPE);
AttributeId ATTRIB_DELAY = AttributeId("delay", 42, FORMAT_SCOPE);
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize", 43, FORMAT_SCOPE);
AttributeId ATTRIB_PHYSICAL = AttributeId("physical", 44, FORMAT_SCOPE);
AttributeId ATTRIB_SCOPESIZE = AttributeId("scopesize", 45, FORMAT_SCOPE);
AttributeId ATTRIB_SYMBOLSIZE = AttributeId("symbolsize", 46, FORMAT_SCOPE);
AttributeId ATTRIB_VARNODE = AttributeId("varnode", 47, FORMAT_SCOPE);
AttributeId ATTRIB_LOW = AttributeId("low", 48, FORMAT_SCOPE);
AttributeId ATTRIB_HIGH = AttributeId("high", 49, FORMAT_SCOPE);
AttributeId ATTRIB_FLOW = AttributeId("flow", 50, FORMAT_SCOPE);
AttributeId ATTRIB_CONTAIN = AttributeId("contain", 51, FORMAT_SCOPE);
AttributeId ATTRIB_I = AttributeId("i", 52, FORMAT_SCOPE);
AttributeId ATTRIB_NUMCT = AttributeId("numct", 53, FORMAT_SCOPE);
AttributeId ATTRIB_SECTION = AttributeId("section", 54, FORMAT_SCOPE);
AttributeId ATTRIB_LABELS = AttributeId("labels", 55, FORMAT_SCOPE);
ElementId ELEM_CONST_REAL = ElementId("const_real", 1, FORMAT_SCOPE);
ElementId ELEM_VARNODE_TPL = ElementId("varnode_tpl", 2, FORMAT_SCOPE);
ElementId ELEM_CONST_SPACEID = ElementId("const_spaceid", 3, FORMAT_SCOPE);
ElementId ELEM_CONST_HANDLE = ElementId("const_handle", 4, FORMAT_SCOPE);
ElementId ELEM_OP_TPL = ElementId("op_tpl", 5, FORMAT_SCOPE);
ElementId ELEM_MASK_WORD = ElementId("mask_word", 6, FORMAT_SCOPE);
ElementId ELEM_PAT_BLOCK = ElementId("pat_block", 7, FORMAT_SCOPE);
ElementId ELEM_PRINT = ElementId("print", 8, FORMAT_SCOPE);
ElementId ELEM_PAIR = ElementId("pair", 9, FORMAT_SCOPE);
ElementId ELEM_CONTEXT_PAT = ElementId("context_pat", 10, FORMAT_SCOPE);
ElementId ELEM_NULL = ElementId("null", 11, FORMAT_SCOPE);
ElementId ELEM_OPERAND_EXP = ElementId("operand_exp", 12, FORMAT_SCOPE);
ElementId ELEM_OPERAND_SYM = ElementId("operand_sym", 13, FORMAT_SCOPE);
ElementId ELEM_OPERAND_SYM_HEAD = ElementId("operand_sym_head", 14, FORMAT_SCOPE);
ElementId ELEM_OPER = ElementId("oper", 15, FORMAT_SCOPE);
ElementId ELEM_DECISION = ElementId("decision", 16, FORMAT_SCOPE);
ElementId ELEM_OPPRINT = ElementId("opprint", 17, FORMAT_SCOPE);
ElementId ELEM_INSTRUCT_PAT = ElementId("instruct_pat", 18, FORMAT_SCOPE);
ElementId ELEM_COMBINE_PAT = ElementId("combine_pat", 19, FORMAT_SCOPE);
ElementId ELEM_CONSTRUCTOR = ElementId("constructor", 20, FORMAT_SCOPE);
ElementId ELEM_CONSTRUCT_TPL = ElementId("construct_tpl", 21, FORMAT_SCOPE);
ElementId ELEM_SCOPE = ElementId("scope", 22, FORMAT_SCOPE);
ElementId ELEM_VARNODE_SYM = ElementId("varnode_sym", 23, FORMAT_SCOPE);
ElementId ELEM_VARNODE_SYM_HEAD = ElementId("varnode_sym_head", 24, FORMAT_SCOPE);
ElementId ELEM_USEROP = ElementId("userop", 25, FORMAT_SCOPE);
ElementId ELEM_USEROP_HEAD = ElementId("userop_head", 26, FORMAT_SCOPE);
ElementId ELEM_TOKENFIELD = ElementId("tokenfield", 27, FORMAT_SCOPE);
ElementId ELEM_VAR = ElementId("var", 28, FORMAT_SCOPE);
ElementId ELEM_CONTEXTFIELD = ElementId("contextfield", 29, FORMAT_SCOPE);
ElementId ELEM_HANDLE_TPL = ElementId("handle_tpl", 30, FORMAT_SCOPE);
ElementId ELEM_CONST_RELATIVE = ElementId("const_relative", 31, FORMAT_SCOPE);
ElementId ELEM_CONTEXT_OP = ElementId("context_op", 32, FORMAT_SCOPE);
ElementId ELEM_SLEIGH = ElementId("sleigh", 33, FORMAT_SCOPE);
ElementId ELEM_SPACES = ElementId("spaces", 34, FORMAT_SCOPE);
ElementId ELEM_SOURCEFILES = ElementId("sourcefiles", 35, FORMAT_SCOPE);
ElementId ELEM_SOURCEFILE = ElementId("sourcefile", 36, FORMAT_SCOPE);
ElementId ELEM_SPACE = ElementId("space", 37, FORMAT_SCOPE);
ElementId ELEM_SYMBOL_TABLE = ElementId("symbol_table", 38, FORMAT_SCOPE);
ElementId ELEM_VALUE_SYM = ElementId("value_sym", 39, FORMAT_SCOPE);
ElementId ELEM_VALUE_SYM_HEAD = ElementId("value_sym_head", 40, FORMAT_SCOPE);
ElementId ELEM_CONTEXT_SYM = ElementId("context_sym", 41, FORMAT_SCOPE);
ElementId ELEM_CONTEXT_SYM_HEAD = ElementId("context_sym_head", 42, FORMAT_SCOPE);
ElementId ELEM_END_SYM = ElementId("end_sym", 43, FORMAT_SCOPE);
ElementId ELEM_END_SYM_HEAD = ElementId("end_sym_head", 44, FORMAT_SCOPE);
ElementId ELEM_SPACE_OTHER = ElementId("space_other", 45, FORMAT_SCOPE);
ElementId ELEM_SPACE_UNIQUE = ElementId("space_unique", 46, FORMAT_SCOPE);
ElementId ELEM_AND_EXP = ElementId("and_exp", 47, FORMAT_SCOPE);
ElementId ELEM_DIV_EXP = ElementId("div_exp", 48, FORMAT_SCOPE);
ElementId ELEM_LSHIFT_EXP = ElementId("lshift_exp", 49, FORMAT_SCOPE);
ElementId ELEM_MINUS_EXP = ElementId("minus_exp", 50, FORMAT_SCOPE);
ElementId ELEM_MULT_EXP = ElementId("mult_exp", 51, FORMAT_SCOPE);
ElementId ELEM_NOT_EXP = ElementId("not_exp", 52, FORMAT_SCOPE);
ElementId ELEM_OR_EXP = ElementId("or_exp", 53, FORMAT_SCOPE);
ElementId ELEM_PLUS_EXP = ElementId("plus_exp", 54, FORMAT_SCOPE);
ElementId ELEM_RSHIFT_EXP = ElementId("rshift_exp", 55, FORMAT_SCOPE);
ElementId ELEM_SUB_EXP = ElementId("sub_exp", 56, FORMAT_SCOPE);
ElementId ELEM_XOR_EXP = ElementId("xor_exp", 57, FORMAT_SCOPE);
ElementId ELEM_INTB = ElementId("intb", 58, FORMAT_SCOPE);
ElementId ELEM_END_EXP = ElementId("end_exp", 59, FORMAT_SCOPE);
ElementId ELEM_NEXT2_EXP = ElementId("next2_exp", 60, FORMAT_SCOPE);
ElementId ELEM_START_EXP = ElementId("start_exp", 61, FORMAT_SCOPE);
ElementId ELEM_EPSILON_SYM = ElementId("epsilon_sym", 62, FORMAT_SCOPE);
ElementId ELEM_EPSILON_SYM_HEAD = ElementId("epsilon_sym_head", 63, FORMAT_SCOPE);
ElementId ELEM_NAME_SYM = ElementId("name_sym", 64, FORMAT_SCOPE);
ElementId ELEM_NAME_SYM_HEAD = ElementId("name_sym_head", 65, FORMAT_SCOPE);
ElementId ELEM_NAMETAB = ElementId("nametab", 66, FORMAT_SCOPE);
ElementId ELEM_NEXT2_SYM = ElementId("next2_sym", 67, FORMAT_SCOPE);
ElementId ELEM_NEXT2_SYM_HEAD = ElementId("next2_sym_head", 68, FORMAT_SCOPE);
ElementId ELEM_START_SYM = ElementId("start_sym", 69, FORMAT_SCOPE);
ElementId ELEM_START_SYM_HEAD = ElementId("start_sym_head", 70, FORMAT_SCOPE);
ElementId ELEM_SUBTABLE_SYM = ElementId("subtable_sym", 71, FORMAT_SCOPE);
ElementId ELEM_SUBTABLE_SYM_HEAD = ElementId("subtable_sym_head", 72, FORMAT_SCOPE);
ElementId ELEM_VALUEMAP_SYM = ElementId("valuemap_sym", 73, FORMAT_SCOPE);
ElementId ELEM_VALUEMAP_SYM_HEAD = ElementId("valuemap_sym_head", 74, FORMAT_SCOPE);
ElementId ELEM_VALUETAB = ElementId("valuetab", 75, FORMAT_SCOPE);
ElementId ELEM_VARLIST_SYM = ElementId("varlist_sym", 76, FORMAT_SCOPE);
ElementId ELEM_VARLIST_SYM_HEAD = ElementId("varlist_sym_head", 77, FORMAT_SCOPE);
ElementId ELEM_OR_PAT = ElementId("or_pat", 78, FORMAT_SCOPE);
ElementId ELEM_COMMIT = ElementId("commit", 79, FORMAT_SCOPE);
ElementId ELEM_CONST_START = ElementId("const_start", 80, FORMAT_SCOPE);
ElementId ELEM_CONST_NEXT = ElementId("const_next", 81, FORMAT_SCOPE);
ElementId ELEM_CONST_NEXT2 = ElementId("const_next2", 82, FORMAT_SCOPE);
ElementId ELEM_CONST_CURSPACE = ElementId("const_curspace", 83, FORMAT_SCOPE);
ElementId ELEM_CONST_CURSPACE_SIZE = ElementId("const_curspace_size", 84, FORMAT_SCOPE);
ElementId ELEM_CONST_FLOWREF = ElementId("const_flowref", 85, FORMAT_SCOPE);
ElementId ELEM_CONST_FLOWREF_SIZE = ElementId("const_flowref_size", 86, FORMAT_SCOPE);
ElementId ELEM_CONST_FLOWDEST = ElementId("const_flowdest", 87, FORMAT_SCOPE);
ElementId ELEM_CONST_FLOWDEST_SIZE = ElementId("const_flowdest_size", 88, FORMAT_SCOPE);
/// The bytes of the header are read from the stream and verified against the required form and current version.
/// If the form matches, \b true is returned. No additional bytes are read.
/// \param s is the given stream
/// \return \b true if a valid header is present
bool isSlaFormat(istream &s)
{
uint1 header[4];
s.read((char *)header,4);
if (!s)
return false;
if (header[0] != 's' || header[1] != 'l' || header[2] != 'a')
return false;
if (header[3] != FORMAT_VERSION)
return false;
return true;
}
/// A valid header, including the format version number, is written to the stream.
/// \param s is the given stream
void writeSlaHeader(ostream &s)
{
char header[4];
header[0] = 's';
header[1] = 'l';
header[2] = 'a';
header[3] = FORMAT_VERSION;
s.write(header,4);
}
/// \param s is the backing stream that will receive the final bytes of the .sla file
/// \param level is the compression level
FormatEncode::FormatEncode(ostream &s,int4 level)
: PackedEncode(compStream), compBuffer(s,level), compStream(&compBuffer)
{
writeSlaHeader(s);
}
void FormatEncode::flush(void)
{
compStream.flush();
}
const int4 FormatDecode::IN_BUFFER_SIZE = 4096;
/// \param spcManager is the (uninitialized) manager that will hold decoded address spaces
FormatDecode::FormatDecode(const AddrSpaceManager *spcManager)
: PackedDecode(spcManager)
{
inBuffer = new uint1[IN_BUFFER_SIZE];
}
FormatDecode::~FormatDecode(void)
{
delete [] inBuffer;
}
void FormatDecode::ingestStream(istream &s)
{
if (!isSlaFormat(s))
throw LowlevelError("Missing SLA format header");
Decompress decompressor;
uint1 *outBuf;
int4 outAvail = 0;
while(!decompressor.isFinished()) {
s.read((char *)inBuffer,IN_BUFFER_SIZE);
int4 gcount = s.gcount();
if (gcount == 0)
break;
decompressor.input(inBuffer,gcount);
do {
if (outAvail == 0) {
outBuf = allocateNextInputBuffer(0);
outAvail = BUFFER_SIZE;
}
outAvail = decompressor.inflate(outBuf + (BUFFER_SIZE - outAvail), outAvail);
} while(outAvail == 0);
}
endIngest(BUFFER_SIZE - outAvail);
}
} // End sla namespace
} // End ghidra namespace

View file

@ -0,0 +1,205 @@
/* ###
* 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.
*/
/// \file slaformat.hh
/// \brief Encoding values for the SLA file format
#ifndef __SLAFORMAT__
#define __SLAFORMAT__
#include "compression.hh"
#include "marshal.hh"
namespace ghidra {
namespace sla {
extern const int4 FORMAT_SCOPE; ///< Grouping elements/attributes for SLA file format
extern const int4 FORMAT_VERSION; ///< Current version of the .sla file
extern AttributeId ATTRIB_VAL; ///< SLA format attribute "val"
extern AttributeId ATTRIB_ID; ///< SLA format attribute "id"
extern AttributeId ATTRIB_SPACE; ///< SLA format attribute "space"
extern AttributeId ATTRIB_S; ///< SLA format attribute "s"
extern AttributeId ATTRIB_OFF; ///< SLA format attribute "off"
extern AttributeId ATTRIB_CODE; ///< SLA format attribute "code"
extern AttributeId ATTRIB_MASK; ///< SLA format attribute "mask"
extern AttributeId ATTRIB_INDEX; ///< SLA format attribute "index"
extern AttributeId ATTRIB_NONZERO; ///< SLA format attribute "nonzero"
extern AttributeId ATTRIB_PIECE; ///< SLA format attribute "piece"
extern AttributeId ATTRIB_NAME; ///< SLA format attribute "name"
extern AttributeId ATTRIB_SCOPE; ///< SLA format attribute "scope"
extern AttributeId ATTRIB_STARTBIT; ///< SLA format attribute "startbit"
extern AttributeId ATTRIB_SIZE; ///< SLA format attribute "size"
extern AttributeId ATTRIB_TABLE; ///< SLA format attribute "table"
extern AttributeId ATTRIB_CT; ///< SLA format attribute "ct"
extern AttributeId ATTRIB_MINLEN; ///< SLA format attribute "minlen"
extern AttributeId ATTRIB_BASE; ///< SLA format attribute "base"
extern AttributeId ATTRIB_NUMBER; ///< SLA format attribute "number"
extern AttributeId ATTRIB_CONTEXT; ///< SLA format attribute "context"
extern AttributeId ATTRIB_PARENT; ///< SLA format attribute "parent"
extern AttributeId ATTRIB_SUBSYM; ///< SLA format attribute "subsym"
extern AttributeId ATTRIB_LINE; ///< SLA format attribute "line"
extern AttributeId ATTRIB_SOURCE; ///< SLA format attribute "source"
extern AttributeId ATTRIB_LENGTH; ///< SLA format attribute "length"
extern AttributeId ATTRIB_FIRST; ///< SLA format attribute "first"
extern AttributeId ATTRIB_PLUS; ///< SLA format attribute "plus"
extern AttributeId ATTRIB_SHIFT; ///< SLA format attribute "shift"
extern AttributeId ATTRIB_ENDBIT; ///< SLA format attribute "endbit"
extern AttributeId ATTRIB_SIGNBIT; ///< SLA format attribute "signbit"
extern AttributeId ATTRIB_ENDBYTE; ///< SLA format attribute "endbyte"
extern AttributeId ATTRIB_STARTBYTE; ///< SLA format attribute "startbyte"
extern AttributeId ATTRIB_VERSION; ///< SLA format attribute "version"
extern AttributeId ATTRIB_BIGENDIAN; ///< SLA format attribute "bigendian"
extern AttributeId ATTRIB_ALIGN; ///< SLA format attribute "align"
extern AttributeId ATTRIB_UNIQBASE; ///< SLA format attribute "uniqbase"
extern AttributeId ATTRIB_MAXDELAY; ///< SLA format attribute "maxdelay"
extern AttributeId ATTRIB_UNIQMASK; ///< SLA format attribute "uniqmask"
extern AttributeId ATTRIB_NUMSECTIONS; ///< SLA format attribute "numsections"
extern AttributeId ATTRIB_DEFAULTSPACE; ///< SLA format attribute "defaultspace"
extern AttributeId ATTRIB_DELAY; ///< SLA format attribute "delay"
extern AttributeId ATTRIB_WORDSIZE; ///< SLA format attribute "wordsize"
extern AttributeId ATTRIB_PHYSICAL; ///< SLA format attribute "physical"
extern AttributeId ATTRIB_SCOPESIZE; ///< SLA format attribute "scopesize"
extern AttributeId ATTRIB_SYMBOLSIZE; ///< SLA format attribute "symbolsize"
extern AttributeId ATTRIB_VARNODE; ///< SLA format attribute "varnode"
extern AttributeId ATTRIB_LOW; ///< SLA format attribute "low"
extern AttributeId ATTRIB_HIGH; ///< SLA format attribute "high"
extern AttributeId ATTRIB_FLOW; ///< SLA format attribute "flow"
extern AttributeId ATTRIB_CONTAIN; ///< SLA format attribute "contain"
extern AttributeId ATTRIB_I; ///< SLA format attribute "i"
extern AttributeId ATTRIB_NUMCT; ///< SLA format attribute "numct"
extern AttributeId ATTRIB_SECTION; ///< SLA format attribute "section"
extern AttributeId ATTRIB_LABELS; ///< SLA format attribute "labels"
extern ElementId ELEM_CONST_REAL; ///< SLA format element "const_real"
extern ElementId ELEM_VARNODE_TPL; ///< SLA format element "varnode_tpl"
extern ElementId ELEM_CONST_SPACEID; ///< SLA format element "const_spaceid"
extern ElementId ELEM_CONST_HANDLE; ///< SLA format element "const_handle"
extern ElementId ELEM_OP_TPL; ///< SLA format element "op_tpl"
extern ElementId ELEM_MASK_WORD; ///< SLA format element "mask_word"
extern ElementId ELEM_PAT_BLOCK; ///< SLA format element "pat_block"
extern ElementId ELEM_PRINT; ///< SLA format element "print"
extern ElementId ELEM_PAIR; ///< SLA format element "pair"
extern ElementId ELEM_CONTEXT_PAT; ///< SLA format element "context_pat"
extern ElementId ELEM_NULL; ///< SLA format element "null"
extern ElementId ELEM_OPERAND_EXP; ///< SLA format element "operand_exp"
extern ElementId ELEM_OPERAND_SYM; ///< SLA format element "operand_sym"
extern ElementId ELEM_OPERAND_SYM_HEAD; ///< SLA format element "operand_sym_head"
extern ElementId ELEM_OPER; ///< SLA format element "oper"
extern ElementId ELEM_DECISION; ///< SLA format element "decision"
extern ElementId ELEM_OPPRINT; ///< SLA format element "opprint"
extern ElementId ELEM_INSTRUCT_PAT; ///< SLA format element "instruct_pat"
extern ElementId ELEM_COMBINE_PAT; ///< SLA format element "combine_pat"
extern ElementId ELEM_CONSTRUCTOR; ///< SLA format element "constructor"
extern ElementId ELEM_CONSTRUCT_TPL; ///< SLA format element "construct_tpl"
extern ElementId ELEM_SCOPE; ///< SLA format element "scope"
extern ElementId ELEM_VARNODE_SYM; ///< SLA format element "varnode_sym"
extern ElementId ELEM_VARNODE_SYM_HEAD; ///< SLA format element "varnode_sym_head"
extern ElementId ELEM_USEROP; ///< SLA format element "userop"
extern ElementId ELEM_USEROP_HEAD; ///< SLA format element "userop_head"
extern ElementId ELEM_TOKENFIELD; ///< SLA format element "tokenfield"
extern ElementId ELEM_VAR; ///< SLA format element "var"
extern ElementId ELEM_CONTEXTFIELD; ///< SLA format element "contextfield"
extern ElementId ELEM_HANDLE_TPL; ///< SLA format element "handle_tpl"
extern ElementId ELEM_CONST_RELATIVE; ///< SLA format element "const_relative"
extern ElementId ELEM_CONTEXT_OP; ///< SLA format element "context_op"
extern ElementId ELEM_SLEIGH; ///< SLA format element "sleigh"
extern ElementId ELEM_SPACES; ///< SLA format element "spaces"
extern ElementId ELEM_SOURCEFILES; ///< SLA format element "sourcefiles"
extern ElementId ELEM_SOURCEFILE; ///< SLA format element "sourcefile"
extern ElementId ELEM_SPACE; ///< SLA format element "space"
extern ElementId ELEM_SYMBOL_TABLE; ///< SLA format element "symbol_table"
extern ElementId ELEM_VALUE_SYM; ///< SLA format element "value_sym"
extern ElementId ELEM_VALUE_SYM_HEAD; ///< SLA format element "value_sym_head"
extern ElementId ELEM_CONTEXT_SYM; ///< SLA format element "context_sym"
extern ElementId ELEM_CONTEXT_SYM_HEAD; ///< SLA format element "context_sym_head"
extern ElementId ELEM_END_SYM; ///< SLA format element "end_sym"
extern ElementId ELEM_END_SYM_HEAD; ///< SLA format element "end_sym_head"
extern ElementId ELEM_SPACE_OTHER; ///< SLA format element "space_other"
extern ElementId ELEM_SPACE_UNIQUE; ///< SLA format element "space_unique"
extern ElementId ELEM_AND_EXP; ///< SLA format element "and_exp"
extern ElementId ELEM_DIV_EXP; ///< SLA format element "div_exp"
extern ElementId ELEM_LSHIFT_EXP; ///< SLA format element "lshift_exp"
extern ElementId ELEM_MINUS_EXP; ///< SLA format element "minus_exp"
extern ElementId ELEM_MULT_EXP; ///< SLA format element "mult_exp"
extern ElementId ELEM_NOT_EXP; ///< SLA format element "not_exp"
extern ElementId ELEM_OR_EXP; ///< SLA format element "or_exp"
extern ElementId ELEM_PLUS_EXP; ///< SLA format element "plus_exp"
extern ElementId ELEM_RSHIFT_EXP; ///< SLA format element "rshift_exp"
extern ElementId ELEM_SUB_EXP; ///< SLA format element "sub_exp"
extern ElementId ELEM_XOR_EXP; ///< SLA format element "xor_exp"
extern ElementId ELEM_INTB; ///< SLA format element "intb"
extern ElementId ELEM_END_EXP; ///< SLA format element "end_exp"
extern ElementId ELEM_NEXT2_EXP; ///< SLA format element "next2_exp"
extern ElementId ELEM_START_EXP; ///< SLA format element "start_exp"
extern ElementId ELEM_EPSILON_SYM; ///< SLA format element "epsilon_sym"
extern ElementId ELEM_EPSILON_SYM_HEAD; ///< SLA format element "epsilon_sym_head"
extern ElementId ELEM_NAME_SYM; ///< SLA format element "name_sym"
extern ElementId ELEM_NAME_SYM_HEAD; ///< SLA format element "name_sym_head"
extern ElementId ELEM_NAMETAB; ///< SLA format element "nametab"
extern ElementId ELEM_NEXT2_SYM; ///< SLA format element "next2_sym"
extern ElementId ELEM_NEXT2_SYM_HEAD; ///< SLA format element "next2_sym_head"
extern ElementId ELEM_START_SYM; ///< SLA format element "start_sym"
extern ElementId ELEM_START_SYM_HEAD; ///< SLA format element "start_sym_head"
extern ElementId ELEM_SUBTABLE_SYM; ///< SLA format element "subtable_sym"
extern ElementId ELEM_SUBTABLE_SYM_HEAD; ///< SLA format element "subtable_sym_head"
extern ElementId ELEM_VALUEMAP_SYM; ///< SLA format element "valuemap_sym"
extern ElementId ELEM_VALUEMAP_SYM_HEAD; ///< SLA format element "valuemap_sym_head"
extern ElementId ELEM_VALUETAB; ///< SLA format element "valuetab"
extern ElementId ELEM_VARLIST_SYM; ///< SLA format element "varlist_sym"
extern ElementId ELEM_VARLIST_SYM_HEAD; ///< SLA format element "varlist_sym_head"
extern ElementId ELEM_OR_PAT; ///< SLA format element "or_pat"
extern ElementId ELEM_COMMIT; ///< SLA format element "commit"
extern ElementId ELEM_CONST_START; ///< SLA format element "const_start"
extern ElementId ELEM_CONST_NEXT; ///< SLA format element "const_next"
extern ElementId ELEM_CONST_NEXT2; ///< SLA format element "const_next2"
extern ElementId ELEM_CONST_CURSPACE; ///< SLA format element "curspace"
extern ElementId ELEM_CONST_CURSPACE_SIZE; ///< SLA format element "curspace_size"
extern ElementId ELEM_CONST_FLOWREF; ///< SLA format element "const_flowref"
extern ElementId ELEM_CONST_FLOWREF_SIZE; ///< SLA format element "const_flowref_size"
extern ElementId ELEM_CONST_FLOWDEST; ///< SLA format element "const_flowdest"
extern ElementId ELEM_CONST_FLOWDEST_SIZE; ///< SLA format element "const_flowdest_size"
extern bool isSlaFormat(istream &s); ///< Verify a .sla file header at the current point of the given stream
extern void writeSlaHeader(ostream &s); ///< Write a .sla file header to the given stream
/// \brief The encoder for the .sla file format
///
/// This provides the format header, does compression, and encodes the raw data elements/attributes.
class FormatEncode : public PackedEncode {
CompressBuffer compBuffer; ///< The compression stream filter
ostream compStream; ///< The front-end stream receiving uncompressed bytes
public:
FormatEncode(ostream &s,int4 level); ///< Initialize an encoder at a specific compression level
void flush(void); ///< Flush any buffered bytes in the encoder to the backing stream
};
/// \brief The decoder for the .sla file format
///
/// This verifies the .sla file header, does decompression, and decodes the raw data elements/attributes.
class FormatDecode : public PackedDecode {
static const int4 IN_BUFFER_SIZE; ///< The size of the \e input buffer
uint1 *inBuffer; ///< The \e input buffer
public:
FormatDecode(const AddrSpaceManager *spcManager); ///< Initialize the decoder
virtual ~FormatDecode(void); ///< Destructor
virtual void ingestStream(istream &s);
};
} // End namespace sla
} // End namespace ghidra
#endif

View file

@ -559,7 +559,13 @@ void Sleigh::initialize(DocumentStorage &store)
const Element *el = store.getTag("sleigh"); const Element *el = store.getTag("sleigh");
if (el == (const Element *)0) if (el == (const Element *)0)
throw LowlevelError("Could not find sleigh tag"); throw LowlevelError("Could not find sleigh tag");
restoreXml(el); sla::FormatDecode decoder(this);
ifstream s(el->getContent());
if (!s)
throw LowlevelError("Could not open .sla file: " + el->getContent());
decoder.ingestStream(s);
s.close();
decode(decoder);
} }
else else
reregisterContext(); reregisterContext();

View file

@ -356,8 +356,11 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
specpaths.findFile(processorfile,language.getProcessorSpec()); specpaths.findFile(processorfile,language.getProcessorSpec());
specpaths.findFile(compilerfile,compilertag.getSpec()); specpaths.findFile(compilerfile,compilertag.getSpec());
if (!language_reuse) if (!language_reuse) {
specpaths.findFile(slafile,language.getSlaFile()); specpaths.findFile(slafile,language.getSlaFile());
if (slafile.empty())
throw SleighError("Could not find .sla file for " + archid);
}
try { try {
Document *doc = store.openDocument(processorfile); Document *doc = store.openDocument(processorfile);
@ -394,16 +397,11 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
} }
if (!language_reuse) { if (!language_reuse) {
istringstream s("<sleigh>" + slafile + "</sleigh>");
try { try {
Document *doc = store.openDocument(slafile); Document *doc = store.parseDocument(s);
store.registerTag(doc->getRoot()); store.registerTag(doc->getRoot());
} }
catch(DecoderError &err) {
ostringstream serr;
serr << "XML error parsing SLEIGH file: " << slafile;
serr << "\n " << err.explain;
throw SleighError(serr.str());
}
catch(LowlevelError &err) { catch(LowlevelError &err) {
ostringstream serr; ostringstream serr;
serr << "Error reading SLEIGH file: " << slafile; serr << "Error reading SLEIGH file: " << slafile;

View file

@ -17,8 +17,6 @@
namespace ghidra { namespace ghidra {
const int4 SleighBase::SLA_FORMAT_VERSION = 3;
const uint4 SleighBase::MAX_UNIQUE_SIZE = 128; const uint4 SleighBase::MAX_UNIQUE_SIZE = 128;
int4 SourceFileIndexer::index(const string filename){ int4 SourceFileIndexer::index(const string filename){
@ -39,26 +37,32 @@ string SourceFileIndexer::getFilename(int4 index){
return indexToFile[index]; return indexToFile[index];
} }
void SourceFileIndexer::restoreXml(const Element *el){ void SourceFileIndexer::decode(Decoder &decoder)
const List &sourceFiles(el->getChildren());
List::const_iterator iter = sourceFiles.begin(); {
for (; iter != sourceFiles.end(); ++iter){ uint4 el = decoder.openElement(sla::ELEM_SOURCEFILES);
string filename = (*iter)->getAttributeValue("name"); while(decoder.peekElement() == sla::ELEM_SOURCEFILE) {
int4 index = stoi((*iter)->getAttributeValue("index"),NULL,10); int4 subel = decoder.openElement();
fileToIndex[filename] = index; string filename = decoder.readString(sla::ATTRIB_NAME);
indexToFile[index] = filename; int4 index = decoder.readSignedInteger(sla::ATTRIB_INDEX);
} decoder.closeElement(subel);
fileToIndex[filename] = index;
indexToFile[index] = filename;
}
decoder.closeElement(el);
} }
void SourceFileIndexer::saveXml(ostream& s) const { void SourceFileIndexer::encode(Encoder &encoder) const
s << "<sourcefiles>\n";
for (int4 i = 0; i < leastUnusedIndex; ++i){ {
s << ("<sourcefile name=\""); encoder.openElement(sla::ELEM_SOURCEFILES);
const char *str = indexToFile.at(i).c_str(); for (int4 i = 0; i < leastUnusedIndex; ++i){
xml_escape(s,str); encoder.openElement(sla::ELEM_SOURCEFILE);
s << "\" index=\"" << dec << i << "\"/>\n"; encoder.writeString(sla::ATTRIB_NAME, indexToFile.at(i));
} encoder.writeSignedInteger(sla::ATTRIB_INDEX, i);
s << "</sourcefiles>\n"; encoder.closeElement(sla::ELEM_SOURCEFILE);
}
encoder.closeElement(sla::ELEM_SOURCEFILES);
} }
SleighBase::SleighBase(void) SleighBase::SleighBase(void)
@ -175,27 +179,55 @@ void SleighBase::getUserOpNames(vector<string> &res) const
res = userop; // Return list of all language defined user ops (with index) res = userop; // Return list of all language defined user ops (with index)
} }
/// This does the bulk of the work of creating a .sla file /// Write a tag fully describing the details of the space.
/// \param s is the output stream /// \param encoder is the stream being written
void SleighBase::saveXml(ostream &s) const /// \param spc is the given address space
void SleighBase::encodeSlaSpace(Encoder &encoder,AddrSpace *spc) const
{ {
s << "<sleigh"; if (spc->getType() == IPTR_INTERNAL)
a_v_i(s,"version",SLA_FORMAT_VERSION); encoder.openElement(sla::ELEM_SPACE_UNIQUE);
a_v_b(s,"bigendian",isBigEndian()); else if (spc->isOtherSpace())
a_v_i(s,"align",alignment); encoder.openElement(sla::ELEM_SPACE_OTHER);
a_v_u(s,"uniqbase",getUniqueBase()); else
encoder.openElement(sla::ELEM_SPACE);
encoder.writeString(sla::ATTRIB_NAME,spc->getName());
encoder.writeSignedInteger(sla::ATTRIB_INDEX, spc->getIndex());
encoder.writeBool(sla::ATTRIB_BIGENDIAN, isBigEndian());
encoder.writeSignedInteger(sla::ATTRIB_DELAY, spc->getDelay());
// if (spc->getDelay() != spc->getDeadcodeDelay())
// encoder.writeSignedInteger(sla::ATTRIB_DEADCODEDELAY, spc->getDeadcodeDelay());
encoder.writeSignedInteger(sla::ATTRIB_SIZE, spc->getAddrSize());
if (spc->getWordSize() > 1)
encoder.writeSignedInteger(sla::ATTRIB_WORDSIZE, spc->getWordSize());
encoder.writeBool(sla::ATTRIB_PHYSICAL, spc->hasPhysical());
if (spc->getType() == IPTR_INTERNAL)
encoder.closeElement(sla::ELEM_SPACE_UNIQUE);
else if (spc->isOtherSpace())
encoder.closeElement(sla::ELEM_SPACE_OTHER);
else
encoder.closeElement(sla::ELEM_SPACE);
}
/// This does the bulk of the work of creating a .sla file
/// \param encoder is the stream encoder
void SleighBase::encode(Encoder &encoder) const
{
encoder.openElement(sla::ELEM_SLEIGH);
encoder.writeSignedInteger(sla::ATTRIB_VERSION, sla::FORMAT_VERSION);
encoder.writeBool(sla::ATTRIB_BIGENDIAN, isBigEndian());
encoder.writeSignedInteger(sla::ATTRIB_ALIGN, alignment);
encoder.writeUnsignedInteger(sla::ATTRIB_UNIQBASE, getUniqueBase());
if (maxdelayslotbytes > 0) if (maxdelayslotbytes > 0)
a_v_u(s,"maxdelay",maxdelayslotbytes); encoder.writeUnsignedInteger(sla::ATTRIB_MAXDELAY, maxdelayslotbytes);
if (unique_allocatemask != 0) if (unique_allocatemask != 0)
a_v_u(s,"uniqmask",unique_allocatemask); encoder.writeUnsignedInteger(sla::ATTRIB_UNIQMASK, unique_allocatemask);
if (numSections != 0) if (numSections != 0)
a_v_u(s,"numsections",numSections); encoder.writeUnsignedInteger(sla::ATTRIB_NUMSECTIONS, numSections);
s << ">\n"; indexer.encode(encoder);
indexer.saveXml(s); encoder.openElement(sla::ELEM_SPACES);
s << "<spaces"; encoder.writeString(sla::ATTRIB_DEFAULTSPACE, getDefaultCodeSpace()->getName());
a_v(s,"defaultspace",getDefaultCodeSpace()->getName());
s << ">\n";
for(int4 i=0;i<numSpaces();++i) { for(int4 i=0;i<numSpaces();++i) {
AddrSpace *spc = getSpace(i); AddrSpace *spc = getSpace(i);
if (spc == (AddrSpace *)0) continue; if (spc == (AddrSpace *)0) continue;
@ -204,76 +236,129 @@ void SleighBase::saveXml(ostream &s) const
(spc->getType()==IPTR_IOP)|| (spc->getType()==IPTR_IOP)||
(spc->getType()==IPTR_JOIN)) (spc->getType()==IPTR_JOIN))
continue; continue;
spc->saveXml(s); encodeSlaSpace(encoder,spc);
} }
s << "</spaces>\n"; encoder.closeElement(sla::ELEM_SPACES);
symtab.saveXml(s); symtab.encode(encoder);
s << "</sleigh>\n"; encoder.closeElement(sla::ELEM_SLEIGH);
}
/// This is identical to the functionality of decodeSpace, but the AddrSpace information is stored
/// in the .sla file format.
/// \param decoder is the stream decoder
/// \param trans is the translator object to be associated with the new space
/// \return a pointer to the initialized AddrSpace
AddrSpace *SleighBase::decodeSlaSpace(Decoder &decoder,const Translate *trans)
{
uint4 elemId = decoder.openElement();
AddrSpace *res;
int4 index = 0;
int4 addressSize = 0;
int4 delay = -1;
int4 deadcodedelay = -1;
string name;
int4 wordsize = 1;
bool bigEnd = false;
uint4 flags = 0;
for (;;) {
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
if (attribId == sla::ATTRIB_NAME) {
name = decoder.readString();
}
if (attribId == sla::ATTRIB_INDEX)
index = decoder.readSignedInteger();
else if (attribId == sla::ATTRIB_SIZE)
addressSize = decoder.readSignedInteger();
else if (attribId == sla::ATTRIB_WORDSIZE)
wordsize = decoder.readUnsignedInteger();
else if (attribId == sla::ATTRIB_BIGENDIAN) {
bigEnd = decoder.readBool();
}
else if (attribId == sla::ATTRIB_DELAY)
delay = decoder.readSignedInteger();
else if (attribId == sla::ATTRIB_PHYSICAL) {
if (decoder.readBool())
flags |= AddrSpace::hasphysical;
}
}
decoder.closeElement(elemId);
if (deadcodedelay == -1)
deadcodedelay = delay; // If deadcodedelay attribute not present, set it to delay
if (index == 0)
throw LowlevelError("Expecting index attribute");
if (elemId == sla::ELEM_SPACE_UNIQUE)
res = new UniqueSpace(this,trans,index,flags);
else if (elemId == sla::ELEM_SPACE_OTHER)
res = new OtherSpace(this,trans,index);
else {
if (addressSize == 0 || delay == -1 || name.size() == 0)
throw LowlevelError("Expecting size/delay/name attributes");
res = new AddrSpace(this,trans,IPTR_PROCESSOR,name,bigEnd,addressSize,wordsize,index,flags,delay,deadcodedelay);
}
return res;
}
/// This is identical in functionality to decodeSpaces but the AddrSpace information
/// is stored in the .sla file format.
/// \param decoder is the stream decoder
/// \param trans is the processor translator to be associated with the spaces
void SleighBase::decodeSlaSpaces(Decoder &decoder,const Translate *trans)
{
// The first space should always be the constant space
insertSpace(new ConstantSpace(this,trans));
uint4 elemId = decoder.openElement(sla::ELEM_SPACES);
string defname = decoder.readString(sla::ATTRIB_DEFAULTSPACE);
while(decoder.peekElement() != 0) {
AddrSpace *spc = decodeSlaSpace(decoder,trans);
insertSpace(spc);
}
decoder.closeElement(elemId);
AddrSpace *spc = getSpaceByName(defname);
if (spc == (AddrSpace *)0)
throw LowlevelError("Bad 'defaultspace' attribute: "+defname);
setDefaultCodeSpace(spc->getIndex());
} }
/// This parses the main \<sleigh> tag (from a .sla file), which includes the description /// This parses the main \<sleigh> tag (from a .sla file), which includes the description
/// of address spaces and the symbol table, with its associated decoding tables /// of address spaces and the symbol table, with its associated decoding tables
/// \param el is the root XML element /// \param decoder is the stream to decode
void SleighBase::restoreXml(const Element *el) void SleighBase::decode(Decoder &decoder)
{ {
maxdelayslotbytes = 0; maxdelayslotbytes = 0;
unique_allocatemask = 0; unique_allocatemask = 0;
numSections = 0; numSections = 0;
int4 version = 0; int4 version = 0;
setBigEndian(xml_readbool(el->getAttributeValue("bigendian"))); uint4 el = decoder.openElement(sla::ELEM_SLEIGH);
{ uint4 attrib = decoder.getNextAttributeId();
istringstream s(el->getAttributeValue("align")); while(attrib != 0) {
s.unsetf(ios::dec | ios::hex | ios::oct); if (attrib == sla::ATTRIB_BIGENDIAN)
s >> alignment; setBigEndian(decoder.readBool());
else if (attrib == sla::ATTRIB_ALIGN)
alignment = decoder.readSignedInteger();
else if (attrib == sla::ATTRIB_UNIQBASE)
setUniqueBase(decoder.readUnsignedInteger());
else if (attrib == sla::ATTRIB_MAXDELAY)
maxdelayslotbytes = decoder.readUnsignedInteger();
else if (attrib == sla::ATTRIB_UNIQMASK)
unique_allocatemask = decoder.readUnsignedInteger();
else if (attrib == sla::ATTRIB_NUMSECTIONS)
numSections = decoder.readUnsignedInteger();
else if (attrib == sla::ATTRIB_VERSION)
version = decoder.readSignedInteger();
attrib = decoder.getNextAttributeId();
} }
{ if (version != sla::FORMAT_VERSION)
istringstream s(el->getAttributeValue("uniqbase"));
s.unsetf(ios::dec | ios::hex | ios::oct);
uintm ubase;
s >> ubase;
setUniqueBase(ubase);
}
int4 numattr = el->getNumAttributes();
for(int4 i=0;i<numattr;++i) {
const string &attrname( el->getAttributeName(i) );
if (attrname == "maxdelay") {
istringstream s1(el->getAttributeValue(i));
s1.unsetf(ios::dec | ios::hex | ios::oct);
s1 >> maxdelayslotbytes;
}
else if (attrname == "uniqmask") {
istringstream s2(el->getAttributeValue(i));
s2.unsetf(ios::dec | ios::hex | ios::oct);
s2 >> unique_allocatemask;
}
else if (attrname == "numsections") {
istringstream s3(el->getAttributeValue(i));
s3.unsetf(ios::dec | ios::hex | ios::oct);
s3 >> numSections;
}
else if (attrname == "version") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> version;
}
}
if (version != SLA_FORMAT_VERSION)
throw LowlevelError(".sla file has wrong format"); throw LowlevelError(".sla file has wrong format");
const List &list(el->getChildren()); indexer.decode(decoder);
List::const_iterator iter; decodeSlaSpaces(decoder,this);
iter = list.begin(); symtab.decode(decoder,this);
while((*iter)->getName() == "floatformat") { decoder.closeElement(el);
floatformats.emplace_back();
floatformats.back().restoreXml(*iter);
++iter;
}
indexer.restoreXml(*iter);
iter++;
XmlDecode decoder(this,*iter);
decodeSpaces(decoder,this);
iter++;
symtab.restoreXml(*iter,this);
root = (SubtableSymbol *)symtab.getGlobalScope()->findSymbol("instruction"); root = (SubtableSymbol *)symtab.getGlobalScope()->findSymbol("instruction");
vector<string> errorPairs; vector<string> errorPairs;
buildXrefs(errorPairs); buildXrefs(errorPairs);

View file

@ -19,6 +19,7 @@
#define __SLEIGHBASE_HH__ #define __SLEIGHBASE_HH__
#include "translate.hh" #include "translate.hh"
#include "slaformat.hh"
#include "slghsymbol.hh" #include "slghsymbol.hh"
namespace ghidra { namespace ghidra {
@ -41,8 +42,8 @@ public:
int4 index(const string filename); int4 index(const string filename);
int4 getIndex(const string); ///< get the index of a file. Error if the file is not in the index. int4 getIndex(const string); ///< get the index of a file. Error if the file is not in the index.
string getFilename(int4); ///< get the filename corresponding to an index string getFilename(int4); ///< get the filename corresponding to an index
void restoreXml(const Element *el); ///< read a stored index mapping from an XML file void decode(Decoder &decoder); ///< decode a stored index mapping from a stream
void saveXml(ostream&) const; ///< save the index mapping to an XML file void encode(Encoder &encoder) const; ///< Encode the index mapping to stream
private: private:
int4 leastUnusedIndex; ///< one-up count for assigning indices to files int4 leastUnusedIndex; ///< one-up count for assigning indices to files
@ -57,7 +58,6 @@ private:
/// - Reading the various SLEIGH specification files /// - Reading the various SLEIGH specification files
/// - Building and writing out SLEIGH specification files /// - Building and writing out SLEIGH specification files
class SleighBase : public Translate { class SleighBase : public Translate {
static const int4 SLA_FORMAT_VERSION; ///< Current version of the .sla file read/written by SleighBash
vector<string> userop; ///< Names of user-define p-code ops for \b this Translate object vector<string> userop; ///< Names of user-define p-code ops for \b this Translate object
map<VarnodeData,string> varnode_xref; ///< A map from Varnodes in the \e register space to register names map<VarnodeData,string> varnode_xref; ///< A map from Varnodes in the \e register space to register names
protected: protected:
@ -69,7 +69,9 @@ protected:
SourceFileIndexer indexer; ///< source file index used when generating SLEIGH constructor debug info SourceFileIndexer indexer; ///< source file index used when generating SLEIGH constructor debug info
void buildXrefs(vector<string> &errorPairs); ///< Build register map. Collect user-ops and context-fields. void buildXrefs(vector<string> &errorPairs); ///< Build register map. Collect user-ops and context-fields.
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 AddrSpace *decodeSlaSpace(Decoder &decoder,const Translate *trans); ///< Add a space parsed from a .sla file
void decodeSlaSpaces(Decoder &decoder,const Translate *trans); ///< Restore address spaces from a .sla file
void decode(Decoder &decoder); /// Decode a SELIGH specification from a stream
public: public:
static const uint4 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
@ -83,7 +85,8 @@ public:
SleighSymbol *findSymbol(const string &nm) const { return symtab.findSymbol(nm); } ///< Find a specific SLEIGH symbol by name in the current scope SleighSymbol *findSymbol(const string &nm) const { return symtab.findSymbol(nm); } ///< Find a specific SLEIGH symbol by name in the current scope
SleighSymbol *findSymbol(uintm id) const { return symtab.findSymbol(id); } ///< Find a specific SLEIGH symbol by id SleighSymbol *findSymbol(uintm id) const { return symtab.findSymbol(id); } ///< Find a specific SLEIGH symbol by id
SleighSymbol *findGlobalSymbol(const string &nm) const { return symtab.findGlobalSymbol(nm); } ///< Find a specific global SLEIGH symbol by name SleighSymbol *findGlobalSymbol(const string &nm) const { return symtab.findGlobalSymbol(nm); } ///< Find a specific global SLEIGH symbol by name
void saveXml(ostream &s) const; ///< Write out the SLEIGH specification as an XML \<sleigh> tag. void encodeSlaSpace(Encoder &encoder,AddrSpace *spc) const; ///< Write the details of given space in .sla format
void encode(Encoder &encoder) const; ///< Write out the SLEIGH specification as a \<sleigh> tag.
}; };
} // End namespace ghidra } // End namespace ghidra

View file

@ -1789,6 +1789,7 @@ SleighCompile::SleighCompile(void)
warnalllocalcollisions = false; warnalllocalcollisions = false;
warnallnops = false; warnallnops = false;
failinsensitivedups = true; failinsensitivedups = true;
debugoutput = false;
root = (SubtableSymbol *)0; root = (SubtableSymbol *)0;
curmacro = (MacroSymbol *)0; curmacro = (MacroSymbol *)0;
curct = (Constructor *)0; curct = (Constructor *)0;
@ -2301,7 +2302,7 @@ uint4 SleighCompile::getUniqueAddr(void)
/// A number of checks are also performed, which may generate errors or warnings, including /// A number of checks are also performed, which may generate errors or warnings, including
/// size restriction checks, pattern conflict checks, NOP constructor checks, and /// size restriction checks, pattern conflict checks, NOP constructor checks, and
/// local collision checks. Once this method is run, \b this SleighCompile is ready for the /// local collision checks. Once this method is run, \b this SleighCompile is ready for the
/// saveXml method. /// encode method.
void SleighCompile::process(void) void SleighCompile::process(void)
{ {
@ -2546,7 +2547,8 @@ void SleighCompile::newSpace(SpaceQuality *qual)
} }
int4 delay = (qual->type == SpaceQuality::registertype) ? 0 : 1; int4 delay = (qual->type == SpaceQuality::registertype) ? 0 : 1;
AddrSpace *spc = new AddrSpace(this,this,IPTR_PROCESSOR,qual->name,qual->size,qual->wordsize,numSpaces(),AddrSpace::hasphysical,delay); AddrSpace *spc = new AddrSpace(this,this,IPTR_PROCESSOR,qual->name,isBigEndian(),
qual->size,qual->wordsize,numSpaces(),AddrSpace::hasphysical,delay,delay);
insertSpace(spc); insertSpace(spc);
if (qual->isdefault) { if (qual->isdefault) {
if (getDefaultCodeSpace() != (AddrSpace *)0) if (getDefaultCodeSpace() != (AddrSpace *)0)
@ -3594,13 +3596,23 @@ int4 SleighCompile::run_compilation(const string &filein,const string &fileout)
if (parseres==0) if (parseres==0)
process(); // Do all the post-processing process(); // Do all the post-processing
if ((parseres==0)&&(numErrors()==0)) { // If no errors if ((parseres==0)&&(numErrors()==0)) { // If no errors
ofstream s(fileout); ofstream s(fileout,ios::binary);
if (!s) { if (!s) {
ostringstream errs; ostringstream errs;
errs << "Unable to open output file: " << fileout; errs << "Unable to open output file: " << fileout;
throw SleighError(errs.str()); throw SleighError(errs.str());
} }
saveXml(s); // Dump output xml if (debugoutput) {
// If the debug output format was requested, use the XML encoder
XmlEncode encoder(s);
encode(encoder);
}
else {
// Use the standard .sla format encoder
sla::FormatEncode encoder(s,-1);
encode(encoder);
encoder.flush();
}
s.close(); s.close();
} }
else { else {
@ -3697,7 +3709,7 @@ static void findSlaSpecs(vector<string> &res, const string &dir, const string &s
void SleighCompile::setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning, void SleighCompile::setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning,
bool lenientConflict, bool allCollisionWarning, bool lenientConflict, bool allCollisionWarning,
bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord, bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord,
bool largeTemporaryWarning, bool caseSensitiveRegisterNames) bool largeTemporaryWarning, bool caseSensitiveRegisterNames,bool debugOutput)
{ {
map<string,string>::const_iterator iter = defines.begin(); map<string,string>::const_iterator iter = defines.begin();
for (iter = defines.begin(); iter != defines.end(); iter++) { for (iter = defines.begin(); iter != defines.end(); iter++) {
@ -3711,6 +3723,7 @@ void SleighCompile::setAllOptions(const map<string,string> &defines, bool unnece
setEnforceLocalKeyWord(enforceLocalKeyWord); setEnforceLocalKeyWord(enforceLocalKeyWord);
setLargeTemporaryWarning(largeTemporaryWarning); setLargeTemporaryWarning(largeTemporaryWarning);
setInsensitiveDuplicateError(!caseSensitiveRegisterNames); setInsensitiveDuplicateError(!caseSensitiveRegisterNames);
setDebugOutput(debugOutput);
} }
static void segvHandler(int sig) { static void segvHandler(int sig) {
@ -3736,6 +3749,7 @@ int main(int argc,char **argv)
cerr << "USAGE: sleigh [-x] [-dNAME=VALUE] inputfile [outputfile]" << endl; cerr << "USAGE: sleigh [-x] [-dNAME=VALUE] inputfile [outputfile]" << endl;
cerr << " -a scan for all slaspec files recursively where inputfile is a directory" << endl; cerr << " -a scan for all slaspec files recursively where inputfile is a directory" << endl;
cerr << " -x turns on parser debugging" << endl; cerr << " -x turns on parser debugging" << endl;
cerr << " -y write .sla using XML debug format" << endl;
cerr << " -u print warnings for unnecessary pcode instructions" << endl; cerr << " -u print warnings for unnecessary pcode instructions" << endl;
cerr << " -l report pattern conflicts" << endl; cerr << " -l report pattern conflicts" << endl;
cerr << " -n print warnings for all NOP constructors" << endl; cerr << " -n print warnings for all NOP constructors" << endl;
@ -3759,6 +3773,7 @@ int main(int argc,char **argv)
bool enforceLocalKeyWord = false; bool enforceLocalKeyWord = false;
bool largeTemporaryWarning = false; bool largeTemporaryWarning = false;
bool caseSensitiveRegisterNames = false; bool caseSensitiveRegisterNames = false;
bool debugOutput = false;
bool compileAll = false; bool compileAll = false;
@ -3794,6 +3809,8 @@ int main(int argc,char **argv)
largeTemporaryWarning = true; largeTemporaryWarning = true;
else if (argv[i][1] == 's') else if (argv[i][1] == 's')
caseSensitiveRegisterNames = true; caseSensitiveRegisterNames = true;
else if (argv[i][1] == 'y')
debugOutput = true;
#ifdef YYDEBUG #ifdef YYDEBUG
else if (argv[i][1] == 'x') else if (argv[i][1] == 'x')
sleighdebug = 1; // Debug option sleighdebug = 1; // Debug option
@ -3825,7 +3842,8 @@ int main(int argc,char **argv)
sla.replace(slaspec.length() - slaspecExtLen, slaspecExtLen, SLAEXT); sla.replace(slaspec.length() - slaspecExtLen, slaspecExtLen, SLAEXT);
SleighCompile compiler; SleighCompile compiler;
compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning, compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning,
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning, caseSensitiveRegisterNames); deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning, caseSensitiveRegisterNames,
debugOutput);
retval = compiler.run_compilation(slaspec,sla); retval = compiler.run_compilation(slaspec,sla);
if (retval != 0) { if (retval != 0) {
return retval; // stop on first error return retval; // stop on first error
@ -3861,7 +3879,8 @@ int main(int argc,char **argv)
SleighCompile compiler; SleighCompile compiler;
compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning, compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning,
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning,caseSensitiveRegisterNames); deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning,caseSensitiveRegisterNames,
debugOutput);
if (i < argc - 1) { if (i < argc - 1) {
string fileoutExamine(argv[i+1]); string fileoutExamine(argv[i+1]);

View file

@ -300,6 +300,7 @@ private:
bool warnalllocalcollisions; ///< \b true if local export collisions generate individual warnings bool warnalllocalcollisions; ///< \b true if local export collisions generate individual warnings
bool warnallnops; ///< \b true if pcode NOPs generate individual warnings bool warnallnops; ///< \b true if pcode NOPs generate individual warnings
bool failinsensitivedups; ///< \b true if case insensitive register duplicates cause error bool failinsensitivedups; ///< \b true if case insensitive register duplicates cause error
bool debugoutput; ///< \b true if output .sla is written in XML debug format
vector<string> noplist; ///< List of individual NOP warnings vector<string> noplist; ///< List of individual NOP warnings
mutable Location currentLocCache; ///< Location for (last) request of current location mutable Location currentLocCache; ///< Location for (last) request of current location
int4 errors; ///< Number of fatal errors encountered int4 errors; ///< Number of fatal errors encountered
@ -382,6 +383,11 @@ public:
/// \param val is \b true is duplicates cause an error. /// \param val is \b true is duplicates cause an error.
void setInsensitiveDuplicateError(bool val) { failinsensitivedups = val; } void setInsensitiveDuplicateError(bool val) { failinsensitivedups = val; }
/// \brief Set whether the output .sla file should be written in XML debug format
///
/// \param val is \b true if the XML debug format should be used
void setDebugOutput(bool val) { debugoutput = val; }
// Lexer functions // Lexer functions
void calcContextLayout(void); ///< Calculate the internal context field layout void calcContextLayout(void); ///< Calculate the internal context field layout
string grabCurrentFilePath(void) const; ///< Get the path to the current source file string grabCurrentFilePath(void) const; ///< Get the path to the current source file
@ -448,7 +454,7 @@ public:
void setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning, void setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning,
bool lenientConflict, bool allCollisionWarning, bool lenientConflict, bool allCollisionWarning,
bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord, bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord,
bool largeTemporaryWarning, bool caseSensitiveRegisterNames); bool largeTemporaryWarning, bool caseSensitiveRegisterNames,bool debugOutput);
int4 run_compilation(const string &filein,const string &fileout); int4 run_compilation(const string &filein,const string &fileout);
}; };

View file

@ -462,50 +462,50 @@ void PatternExpression::release(PatternExpression *p)
delete p; delete p;
} }
PatternExpression *PatternExpression::restoreExpression(const Element *el,Translate *trans) PatternExpression *PatternExpression::decodeExpression(Decoder &decoder,Translate *trans)
{ {
PatternExpression *res; PatternExpression *res;
const string &nm(el->getName()); uint4 el = decoder.peekElement();
if (nm == "tokenfield") if (el == sla::ELEM_TOKENFIELD)
res = new TokenField(); res = new TokenField();
else if (nm == "contextfield") else if (el == sla::ELEM_CONTEXTFIELD)
res = new ContextField(); res = new ContextField();
else if (nm == "intb") else if (el == sla::ELEM_INTB)
res = new ConstantValue(); res = new ConstantValue();
else if (nm == "operand_exp") else if (el == sla::ELEM_OPERAND_EXP)
res = new OperandValue(); res = new OperandValue();
else if (nm == "start_exp") else if (el == sla::ELEM_START_EXP)
res = new StartInstructionValue(); res = new StartInstructionValue();
else if (nm == "end_exp") else if (el == sla::ELEM_END_EXP)
res = new EndInstructionValue(); res = new EndInstructionValue();
else if (nm == "plus_exp") else if (el == sla::ELEM_PLUS_EXP)
res = new PlusExpression(); res = new PlusExpression();
else if (nm == "sub_exp") else if (el == sla::ELEM_SUB_EXP)
res = new SubExpression(); res = new SubExpression();
else if (nm == "mult_exp") else if (el == sla::ELEM_MULT_EXP)
res = new MultExpression(); res = new MultExpression();
else if (nm == "lshift_exp") else if (el == sla::ELEM_LSHIFT_EXP)
res = new LeftShiftExpression(); res = new LeftShiftExpression();
else if (nm == "rshift_exp") else if (el == sla::ELEM_RSHIFT_EXP)
res = new RightShiftExpression(); res = new RightShiftExpression();
else if (nm == "and_exp") else if (el == sla::ELEM_AND_EXP)
res = new AndExpression(); res = new AndExpression();
else if (nm == "or_exp") else if (el == sla::ELEM_OR_EXP)
res = new OrExpression(); res = new OrExpression();
else if (nm == "xor_exp") else if (el == sla::ELEM_XOR_EXP)
res = new XorExpression(); res = new XorExpression();
else if (nm == "div_exp") else if (el == sla::ELEM_DIV_EXP)
res = new DivExpression(); res = new DivExpression();
else if (nm == "minus_exp") else if (el == sla::ELEM_MINUS_EXP)
res = new MinusExpression(); res = new MinusExpression();
else if (nm == "not_exp") else if (el == sla::ELEM_NOT_EXP)
res = new NotExpression(); res = new NotExpression();
else else
return (PatternExpression *)0; return (PatternExpression *)0;
res->restoreXml(el,trans); res->decode(decoder,trans);
return res; return res;
} }
@ -597,58 +597,33 @@ TokenPattern TokenField::genPattern(intb val) const
return TokenPattern(tok,val,bitstart,bitend); return TokenPattern(tok,val,bitstart,bitend);
} }
void TokenField::saveXml(ostream &s) const void TokenField::encode(Encoder &encoder) const
{ {
s << "<tokenfield"; encoder.openElement(sla::ELEM_TOKENFIELD);
s << " bigendian=\""; encoder.writeBool(sla::ATTRIB_BIGENDIAN, bigendian);
if (bigendian) encoder.writeBool(sla::ATTRIB_SIGNBIT, signbit);
s << "true\""; encoder.writeSignedInteger(sla::ATTRIB_STARTBIT, bitstart);
else encoder.writeSignedInteger(sla::ATTRIB_ENDBIT, bitend);
s << "false\""; encoder.writeSignedInteger(sla::ATTRIB_STARTBYTE, bytestart);
s << " signbit=\""; encoder.writeSignedInteger(sla::ATTRIB_ENDBYTE, byteend);
if (signbit) encoder.writeSignedInteger(sla::ATTRIB_SHIFT, shift);
s << "true\""; encoder.closeElement(sla::ELEM_TOKENFIELD);
else
s << "false\"";
s << " bitstart=\"" << dec << bitstart << "\"";
s << " bitend=\"" << bitend << "\"";
s << " bytestart=\"" << bytestart << "\"";
s << " byteend=\"" << byteend << "\"";
s << " shift=\"" << shift << "\"/>\n";
} }
void TokenField::restoreXml(const Element *el,Translate *trans) void TokenField::decode(Decoder &decoder,Translate *trans)
{ {
uint4 el = decoder.openElement(sla::ELEM_TOKENFIELD);
tok = (Token *)0; tok = (Token *)0;
bigendian = xml_readbool(el->getAttributeValue("bigendian")); bigendian = decoder.readBool(sla::ATTRIB_BIGENDIAN);
signbit = xml_readbool(el->getAttributeValue("signbit")); signbit = decoder.readBool(sla::ATTRIB_SIGNBIT);
{ bitstart = decoder.readSignedInteger(sla::ATTRIB_STARTBIT);
istringstream s(el->getAttributeValue("bitstart")); bitend = decoder.readSignedInteger(sla::ATTRIB_ENDBIT);
s.unsetf(ios::dec | ios::hex | ios::oct); bytestart = decoder.readSignedInteger(sla::ATTRIB_STARTBYTE);
s >> bitstart; byteend = decoder.readSignedInteger(sla::ATTRIB_ENDBYTE);
} shift = decoder.readSignedInteger(sla::ATTRIB_SHIFT);
{ decoder.closeElement(el);
istringstream s(el->getAttributeValue("bitend"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> bitend;
}
{
istringstream s(el->getAttributeValue("bytestart"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> bytestart;
}
{
istringstream s(el->getAttributeValue("byteend"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> byteend;
}
{
istringstream s(el->getAttributeValue("shift"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> shift;
}
} }
ContextField::ContextField(bool s,int4 sbit,int4 ebit) ContextField::ContextField(bool s,int4 sbit,int4 ebit)
@ -680,65 +655,88 @@ TokenPattern ContextField::genPattern(intb val) const
return TokenPattern(val,startbit,endbit); return TokenPattern(val,startbit,endbit);
} }
void ContextField::saveXml(ostream &s) const void ContextField::encode(Encoder &encoder) const
{ {
s << "<contextfield"; encoder.openElement(sla::ELEM_CONTEXTFIELD);
s << " signbit=\""; encoder.writeBool(sla::ATTRIB_SIGNBIT, signbit);
if (signbit) encoder.writeSignedInteger(sla::ATTRIB_STARTBIT, startbit);
s << "true\""; encoder.writeSignedInteger(sla::ATTRIB_ENDBIT, endbit);
else encoder.writeSignedInteger(sla::ATTRIB_STARTBYTE, startbyte);
s << "false\""; encoder.writeSignedInteger(sla::ATTRIB_ENDBYTE, endbyte);
s << " startbit=\"" << dec << startbit << "\""; encoder.writeSignedInteger(sla::ATTRIB_SHIFT, shift);
s << " endbit=\"" << endbit << "\""; encoder.closeElement(sla::ELEM_CONTEXTFIELD);
s << " startbyte=\"" << startbyte << "\"";
s << " endbyte=\"" << endbyte << "\"";
s << " shift=\"" << shift << "\"/>\n";
} }
void ContextField::restoreXml(const Element *el,Translate *trans) void ContextField::decode(Decoder &decoder,Translate *trans)
{ {
signbit = xml_readbool(el->getAttributeValue("signbit")); uint4 el = decoder.openElement(sla::ELEM_CONTEXTFIELD);
{ signbit = decoder.readBool(sla::ATTRIB_SIGNBIT);
istringstream s(el->getAttributeValue("startbit")); startbit = decoder.readSignedInteger(sla::ATTRIB_STARTBIT);
s.unsetf(ios::dec | ios::hex | ios::oct); endbit = decoder.readSignedInteger(sla::ATTRIB_ENDBIT);
s >> startbit; startbyte = decoder.readSignedInteger(sla::ATTRIB_STARTBYTE);
} endbyte = decoder.readSignedInteger(sla::ATTRIB_ENDBYTE);
{ shift = decoder.readSignedInteger(sla::ATTRIB_SHIFT);
istringstream s(el->getAttributeValue("endbit")); decoder.closeElement(el);
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> endbit;
}
{
istringstream s(el->getAttributeValue("startbyte"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> startbyte;
}
{
istringstream s(el->getAttributeValue("endbyte"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> endbyte;
}
{
istringstream s(el->getAttributeValue("shift"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> shift;
}
} }
void ConstantValue::saveXml(ostream &s) const void ConstantValue::encode(Encoder &encoder) const
{ {
s << "<intb val=\"" << dec << val << "\"/>\n"; encoder.openElement(sla::ELEM_INTB);
encoder.writeSignedInteger(sla::ATTRIB_VAL, val);
encoder.closeElement(sla::ELEM_INTB);
} }
void ConstantValue::restoreXml(const Element *el,Translate *trans) void ConstantValue::decode(Decoder &decoder,Translate *trans)
{ {
istringstream s(el->getAttributeValue("val")); uint4 el = decoder.openElement(sla::ELEM_INTB);
s.unsetf(ios::dec | ios::hex | ios::oct); val = decoder.readSignedInteger(sla::ATTRIB_VAL);
s >> val; decoder.closeElement(el);
}
void StartInstructionValue::encode(Encoder &encoder) const
{
encoder.openElement(sla::ELEM_START_EXP);
encoder.closeElement(sla::ELEM_START_EXP);
}
void StartInstructionValue::decode(Decoder &decoder,Translate *trans)
{
uint4 el = decoder.openElement(sla::ELEM_START_EXP);
decoder.closeElement(el);
}
void EndInstructionValue::encode(Encoder &encoder) const
{
encoder.openElement(sla::ELEM_END_EXP);
encoder.closeElement(sla::ELEM_END_EXP);
}
void EndInstructionValue::decode(Decoder &decoder,Translate *trans)
{
uint4 el = decoder.openElement(sla::ELEM_END_EXP);
decoder.closeElement(el);
}
void Next2InstructionValue::encode(Encoder &encoder) const
{
encoder.openElement(sla::ELEM_NEXT2_EXP);
encoder.closeElement(sla::ELEM_NEXT2_EXP);
}
void Next2InstructionValue::decode(Decoder &decoder,Translate *trans)
{
uint4 el = decoder.openElement(sla::ELEM_NEXT2_EXP);
decoder.closeElement(el);
} }
TokenPattern OperandValue::genPattern(intb val) const TokenPattern OperandValue::genPattern(intb val) const
@ -809,37 +807,27 @@ const string &OperandValue::getName(void) const
return sym->getName(); return sym->getName();
} }
void OperandValue::saveXml(ostream &s) const void OperandValue::encode(Encoder &encoder) const
{ {
s << "<operand_exp"; encoder.openElement(sla::ELEM_OPERAND_EXP);
s << " index=\"" << dec << index << "\""; encoder.writeSignedInteger(sla::ATTRIB_INDEX, index);
s << " table=\"0x" << hex << ct->getParent()->getId() << "\""; encoder.writeUnsignedInteger(sla::ATTRIB_TABLE, ct->getParent()->getId());
s << " ct=\"0x" << ct->getId() << "\"/>\n"; // Save id of our constructor encoder.writeUnsignedInteger(sla::ATTRIB_CT, ct->getId()); // Save id of our constructor
encoder.closeElement(sla::ELEM_OPERAND_EXP);
} }
void OperandValue::restoreXml(const Element *el,Translate *trans) void OperandValue::decode(Decoder &decoder,Translate *trans)
{ {
uintm ctid,tabid; uint4 el = decoder.openElement(sla::ELEM_OPERAND_EXP);
{ index = decoder.readSignedInteger(sla::ATTRIB_INDEX);
istringstream s(el->getAttributeValue("index")); uintm tabid = decoder.readUnsignedInteger(sla::ATTRIB_TABLE);
s.unsetf(ios::dec | ios::hex | ios::oct); uintm ctid = decoder.readUnsignedInteger(sla::ATTRIB_CT);
s >> index;
}
{
istringstream s(el->getAttributeValue("table"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> tabid;
}
{
istringstream s(el->getAttributeValue("ct"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> ctid;
}
SleighBase *sleigh = (SleighBase *)trans; SleighBase *sleigh = (SleighBase *)trans;
SubtableSymbol *tab = dynamic_cast<SubtableSymbol *>(sleigh->findSymbol(tabid)); SubtableSymbol *tab = dynamic_cast<SubtableSymbol *>(sleigh->findSymbol(tabid));
ct = tab->getConstructor(ctid); ct = tab->getConstructor(ctid);
decoder.closeElement(el);
} }
BinaryExpression::BinaryExpression(PatternExpression *l,PatternExpression *r) BinaryExpression::BinaryExpression(PatternExpression *l,PatternExpression *r)
@ -858,24 +846,22 @@ BinaryExpression::~BinaryExpression(void)
PatternExpression::release(right); PatternExpression::release(right);
} }
void BinaryExpression::saveXml(ostream &s) const void BinaryExpression::encode(Encoder &encoder) const
{ // Outer tag is generated by derived classes { // Outer tag is generated by derived classes
left->saveXml(s); left->encode(encoder);
right->saveXml(s); right->encode(encoder);
} }
void BinaryExpression::restoreXml(const Element *el,Translate *trans) void BinaryExpression::decode(Decoder &decoder,Translate *trans)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement();
List::const_iterator iter; left = PatternExpression::decodeExpression(decoder,trans);
iter = list.begin(); right = PatternExpression::decodeExpression(decoder,trans);
left = PatternExpression::restoreExpression(*iter,trans);
++iter;
right = PatternExpression::restoreExpression(*iter,trans);
left->layClaim(); left->layClaim();
right->layClaim(); right->layClaim();
decoder.closeElement(el);
} }
UnaryExpression::UnaryExpression(PatternExpression *u) UnaryExpression::UnaryExpression(PatternExpression *u)
@ -891,20 +877,19 @@ UnaryExpression::~UnaryExpression(void)
PatternExpression::release(unary); PatternExpression::release(unary);
} }
void UnaryExpression::saveXml(ostream &s) const void UnaryExpression::encode(Encoder &encoder) const
{ // Outer tag is generated by derived classes { // Outer tag is generated by derived classes
unary->saveXml(s); unary->encode(encoder);
} }
void UnaryExpression::restoreXml(const Element *el,Translate *trans) void UnaryExpression::decode(Decoder &decoder,Translate *trans)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement();
List::const_iterator iter; unary = PatternExpression::decodeExpression(decoder,trans);
iter = list.begin();
unary = PatternExpression::restoreExpression(*iter,trans);
unary->layClaim(); unary->layClaim();
decoder.closeElement(el);
} }
intb PlusExpression::getValue(ParserWalker &walker) const intb PlusExpression::getValue(ParserWalker &walker) const
@ -923,12 +908,12 @@ intb PlusExpression::getSubValue(const vector<intb> &replace,int4 &listpos) cons
return leftval + rightval; return leftval + rightval;
} }
void PlusExpression::saveXml(ostream &s) const void PlusExpression::encode(Encoder &encoder) const
{ {
s << "<plus_exp>\n"; encoder.openElement(sla::ELEM_PLUS_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</plus_exp>\n"; encoder.closeElement(sla::ELEM_PLUS_EXP);
} }
intb SubExpression::getValue(ParserWalker &walker) const intb SubExpression::getValue(ParserWalker &walker) const
@ -947,12 +932,12 @@ intb SubExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
return leftval - rightval; return leftval - rightval;
} }
void SubExpression::saveXml(ostream &s) const void SubExpression::encode(Encoder &encoder) const
{ {
s << "<sub_exp>\n"; encoder.openElement(sla::ELEM_SUB_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</sub_exp>\n"; encoder.closeElement(sla::ELEM_SUB_EXP);
} }
intb MultExpression::getValue(ParserWalker &walker) const intb MultExpression::getValue(ParserWalker &walker) const
@ -971,12 +956,12 @@ intb MultExpression::getSubValue(const vector<intb> &replace,int4 &listpos) cons
return leftval * rightval; return leftval * rightval;
} }
void MultExpression::saveXml(ostream &s) const void MultExpression::encode(Encoder &encoder) const
{ {
s << "<mult_exp>\n"; encoder.openElement(sla::ELEM_MULT_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</mult_exp>\n"; encoder.closeElement(sla::ELEM_MULT_EXP);
} }
intb LeftShiftExpression::getValue(ParserWalker &walker) const intb LeftShiftExpression::getValue(ParserWalker &walker) const
@ -995,12 +980,12 @@ intb LeftShiftExpression::getSubValue(const vector<intb> &replace,int4 &listpos)
return leftval << rightval; return leftval << rightval;
} }
void LeftShiftExpression::saveXml(ostream &s) const void LeftShiftExpression::encode(Encoder &encoder) const
{ {
s << "<lshift_exp>\n"; encoder.openElement(sla::ELEM_LSHIFT_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</lshift_exp>\n"; encoder.closeElement(sla::ELEM_LSHIFT_EXP);
} }
intb RightShiftExpression::getValue(ParserWalker &walker) const intb RightShiftExpression::getValue(ParserWalker &walker) const
@ -1019,12 +1004,12 @@ intb RightShiftExpression::getSubValue(const vector<intb> &replace,int4 &listpos
return leftval >> rightval; return leftval >> rightval;
} }
void RightShiftExpression::saveXml(ostream &s) const void RightShiftExpression::encode(Encoder &encoder) const
{ {
s << "<rshift_exp>\n"; encoder.openElement(sla::ELEM_RSHIFT_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</rshift_exp>\n"; encoder.closeElement(sla::ELEM_RSHIFT_EXP);
} }
intb AndExpression::getValue(ParserWalker &walker) const intb AndExpression::getValue(ParserWalker &walker) const
@ -1043,12 +1028,12 @@ intb AndExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
return leftval & rightval; return leftval & rightval;
} }
void AndExpression::saveXml(ostream &s) const void AndExpression::encode(Encoder &encoder) const
{ {
s << "<and_exp>\n"; encoder.openElement(sla::ELEM_AND_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</and_exp>\n"; encoder.closeElement(sla::ELEM_AND_EXP);
} }
intb OrExpression::getValue(ParserWalker &walker) const intb OrExpression::getValue(ParserWalker &walker) const
@ -1067,12 +1052,12 @@ intb OrExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
return leftval | rightval; return leftval | rightval;
} }
void OrExpression::saveXml(ostream &s) const void OrExpression::encode(Encoder &encoder) const
{ {
s << "<or_exp>\n"; encoder.openElement(sla::ELEM_OR_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</or_exp>\n"; encoder.closeElement(sla::ELEM_OR_EXP);
} }
intb XorExpression::getValue(ParserWalker &walker) const intb XorExpression::getValue(ParserWalker &walker) const
@ -1091,12 +1076,12 @@ intb XorExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
return leftval ^ rightval; return leftval ^ rightval;
} }
void XorExpression::saveXml(ostream &s) const void XorExpression::encode(Encoder &encoder) const
{ {
s << "<xor_exp>\n"; encoder.openElement(sla::ELEM_XOR_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</xor_exp>\n"; encoder.closeElement(sla::ELEM_XOR_EXP);
} }
intb DivExpression::getValue(ParserWalker &walker) const intb DivExpression::getValue(ParserWalker &walker) const
@ -1115,12 +1100,12 @@ intb DivExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
return leftval / rightval; return leftval / rightval;
} }
void DivExpression::saveXml(ostream &s) const void DivExpression::encode(Encoder &encoder) const
{ {
s << "<div_exp>\n"; encoder.openElement(sla::ELEM_DIV_EXP);
BinaryExpression::saveXml(s); BinaryExpression::encode(encoder);
s << "</div_exp>\n"; encoder.closeElement(sla::ELEM_DIV_EXP);
} }
intb MinusExpression::getValue(ParserWalker &walker) const intb MinusExpression::getValue(ParserWalker &walker) const
@ -1137,12 +1122,12 @@ intb MinusExpression::getSubValue(const vector<intb> &replace,int4 &listpos) con
return -val; return -val;
} }
void MinusExpression::saveXml(ostream &s) const void MinusExpression::encode(Encoder &encoder) const
{ {
s << "<minus_exp>\n"; encoder.openElement(sla::ELEM_MINUS_EXP);
UnaryExpression::saveXml(s); UnaryExpression::encode(encoder);
s << "</minus_exp>\n"; encoder.closeElement(sla::ELEM_MINUS_EXP);
} }
intb NotExpression::getValue(ParserWalker &walker) const intb NotExpression::getValue(ParserWalker &walker) const
@ -1159,12 +1144,12 @@ intb NotExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
return ~val; return ~val;
} }
void NotExpression::saveXml(ostream &s) const void NotExpression::encode(Encoder &encoder) const
{ {
s << "<not_exp>\n"; encoder.openElement(sla::ELEM_NOT_EXP);
UnaryExpression::saveXml(s); UnaryExpression::encode(encoder);
s << "</not_exp>\n"; encoder.closeElement(sla::ELEM_NOT_EXP);
} }
static bool advance_combo(vector<intb> &val,const vector<intb> &min,vector<intb> &max) static bool advance_combo(vector<intb> &val,const vector<intb> &min,vector<intb> &max)

View file

@ -67,14 +67,14 @@ public:
virtual void listValues(vector<const PatternValue *> &list) const=0; virtual void listValues(vector<const PatternValue *> &list) const=0;
virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const=0; virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const=0;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const=0; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const=0;
virtual void saveXml(ostream &s) const=0; virtual void encode(Encoder &encoder) const=0;
virtual void restoreXml(const Element *el,Translate *trans)=0; virtual void decode(Decoder &decoder,Translate *trans)=0;
intb getSubValue(const vector<intb> &replace) { intb getSubValue(const vector<intb> &replace) {
int4 listpos = 0; int4 listpos = 0;
return getSubValue(replace,listpos); } return getSubValue(replace,listpos); }
void layClaim(void) { refcount += 1; } void layClaim(void) { refcount += 1; }
static void release(PatternExpression *p); static void release(PatternExpression *p);
static PatternExpression *restoreExpression(const Element *el,Translate *trans); static PatternExpression *decodeExpression(Decoder &decoder,Translate *trans);
}; };
class PatternValue : public PatternExpression { class PatternValue : public PatternExpression {
@ -96,15 +96,15 @@ class TokenField : public PatternValue {
int4 bytestart,byteend; // Bytes to read to get value int4 bytestart,byteend; // Bytes to read to get value
int4 shift; // Amount to shift to align value (bitstart % 8) int4 shift; // Amount to shift to align value (bitstart % 8)
public: public:
TokenField(void) {} // For use with restoreXml TokenField(void) {} // For use with decode
TokenField(Token *tk,bool s,int4 bstart,int4 bend); TokenField(Token *tk,bool s,int4 bstart,int4 bend);
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(tok); } virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(tok); }
virtual TokenPattern genPattern(intb val) const; virtual TokenPattern genPattern(intb val) const;
virtual intb minValue(void) const { return 0; } virtual intb minValue(void) const { return 0; }
virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,bitend-bitstart); } virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,bitend-bitstart); }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void decode(Decoder &decoder,Translate *trans);
}; };
class ContextField : public PatternValue { class ContextField : public PatternValue {
@ -113,7 +113,7 @@ class ContextField : public PatternValue {
int4 shift; int4 shift;
bool signbit; bool signbit;
public: public:
ContextField(void) {} // For use with restoreXml ContextField(void) {} // For use with decode
ContextField(bool s,int4 sbit,int4 ebit); ContextField(bool s,int4 sbit,int4 ebit);
int4 getStartBit(void) const { return startbit; } int4 getStartBit(void) const { return startbit; }
int4 getEndBit(void) const { return endbit; } int4 getEndBit(void) const { return endbit; }
@ -123,22 +123,22 @@ public:
virtual TokenPattern genPattern(intb val) const; virtual TokenPattern genPattern(intb val) const;
virtual intb minValue(void) const { return 0; } virtual intb minValue(void) const { return 0; }
virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,(endbit-startbit)); } virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,(endbit-startbit)); }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void decode(Decoder &decoder,Translate *trans);
}; };
class ConstantValue : public PatternValue { class ConstantValue : public PatternValue {
intb val; intb val;
public: public:
ConstantValue(void) {} // For use with restoreXml ConstantValue(void) {} // For use with decode
ConstantValue(intb v) { val = v; } ConstantValue(intb v) { val = v; }
virtual intb getValue(ParserWalker &walker) const { return val; } virtual intb getValue(ParserWalker &walker) const { return val; }
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); } virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); }
virtual TokenPattern genPattern(intb v) const { return TokenPattern(val==v); } virtual TokenPattern genPattern(intb v) const { return TokenPattern(val==v); }
virtual intb minValue(void) const { return val; } virtual intb minValue(void) const { return val; }
virtual intb maxValue(void) const { return val; } virtual intb maxValue(void) const { return val; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void decode(Decoder &decoder,Translate *trans);
}; };
class StartInstructionValue : public PatternValue { class StartInstructionValue : public PatternValue {
@ -150,8 +150,8 @@ public:
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); } virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
virtual intb minValue(void) const { return (intb)0; } virtual intb minValue(void) const { return (intb)0; }
virtual intb maxValue(void) const { return (intb)0; } virtual intb maxValue(void) const { return (intb)0; }
virtual void saveXml(ostream &s) const { s << "<start_exp/>"; } virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans) {} virtual void decode(Decoder &decoder,Translate *trans);
}; };
class EndInstructionValue : public PatternValue { class EndInstructionValue : public PatternValue {
@ -163,8 +163,8 @@ public:
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); } virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
virtual intb minValue(void) const { return (intb)0; } virtual intb minValue(void) const { return (intb)0; }
virtual intb maxValue(void) const { return (intb)0; } virtual intb maxValue(void) const { return (intb)0; }
virtual void saveXml(ostream &s) const { s << "<end_exp/>"; } virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans) {} virtual void decode(Decoder &decoder,Translate *trans);
}; };
class Next2InstructionValue : public PatternValue { class Next2InstructionValue : public PatternValue {
@ -176,8 +176,8 @@ public:
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); } virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
virtual intb minValue(void) const { return (intb)0; } virtual intb minValue(void) const { return (intb)0; }
virtual intb maxValue(void) const { return (intb)0; } virtual intb maxValue(void) const { return (intb)0; }
virtual void saveXml(ostream &s) const { s << "<next2_exp/>"; } virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans) {} virtual void decode(Decoder &decoder,Translate *trans);
}; };
class Constructor; // Forward declaration class Constructor; // Forward declaration
@ -186,7 +186,7 @@ class OperandValue : public PatternValue {
int4 index; // This is the defining field of expression int4 index; // This is the defining field of expression
Constructor *ct; // cached pointer to constructor Constructor *ct; // cached pointer to constructor
public: public:
OperandValue(void) { } // For use with restoreXml OperandValue(void) { } // For use with decode
OperandValue(int4 ind,Constructor *c) { index = ind; ct = c; } OperandValue(int4 ind,Constructor *c) { index = ind; ct = c; }
void changeIndex(int4 newind) { index = newind; } void changeIndex(int4 newind) { index = newind; }
bool isConstructorRelative(void) const; bool isConstructorRelative(void) const;
@ -197,8 +197,8 @@ public:
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual intb minValue(void) const; virtual intb minValue(void) const;
virtual intb maxValue(void) const; virtual intb maxValue(void) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void decode(Decoder &decoder,Translate *trans);
}; };
class BinaryExpression : public PatternExpression { class BinaryExpression : public PatternExpression {
@ -206,7 +206,7 @@ class BinaryExpression : public PatternExpression {
protected: protected:
virtual ~BinaryExpression(void); virtual ~BinaryExpression(void);
public: public:
BinaryExpression(void) { left = (PatternExpression *)0; right = (PatternExpression *)0; } // For use with restoreXml BinaryExpression(void) { left = (PatternExpression *)0; right = (PatternExpression *)0; } // For use with decode
BinaryExpression(PatternExpression *l,PatternExpression *r); BinaryExpression(PatternExpression *l,PatternExpression *r);
PatternExpression *getLeft(void) const { return left; } PatternExpression *getLeft(void) const { return left; }
PatternExpression *getRight(void) const { return right; } PatternExpression *getRight(void) const { return right; }
@ -215,8 +215,8 @@ public:
left->listValues(list); right->listValues(list); } left->listValues(list); right->listValues(list); }
virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const { virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const {
left->getMinMax(minlist,maxlist); right->getMinMax(minlist,maxlist); } left->getMinMax(minlist,maxlist); right->getMinMax(minlist,maxlist); }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void decode(Decoder &decoder,Translate *trans);
}; };
class UnaryExpression : public PatternExpression { class UnaryExpression : public PatternExpression {
@ -224,7 +224,7 @@ class UnaryExpression : public PatternExpression {
protected: protected:
virtual ~UnaryExpression(void); virtual ~UnaryExpression(void);
public: public:
UnaryExpression(void) { unary = (PatternExpression *)0; } // For use with restoreXml UnaryExpression(void) { unary = (PatternExpression *)0; } // For use with decode
UnaryExpression(PatternExpression *u); UnaryExpression(PatternExpression *u);
PatternExpression *getUnary(void) const { return unary; } PatternExpression *getUnary(void) const { return unary; }
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); } virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); }
@ -233,35 +233,35 @@ public:
virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const { virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const {
unary->getMinMax(minlist,maxlist); unary->getMinMax(minlist,maxlist);
} }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void decode(Decoder &decoder,Translate *trans);
}; };
class PlusExpression : public BinaryExpression { class PlusExpression : public BinaryExpression {
public: public:
PlusExpression(void) {} // For use by restoreXml PlusExpression(void) {} // For use by decode
PlusExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} PlusExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class SubExpression : public BinaryExpression { class SubExpression : public BinaryExpression {
public: public:
SubExpression(void) {} // For use with restoreXml SubExpression(void) {} // For use with decode
SubExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} SubExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class MultExpression : public BinaryExpression { class MultExpression : public BinaryExpression {
public: public:
MultExpression(void) {} // For use with restoreXml MultExpression(void) {} // For use with decode
MultExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} MultExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class LeftShiftExpression : public BinaryExpression { class LeftShiftExpression : public BinaryExpression {
@ -270,7 +270,7 @@ public:
LeftShiftExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} LeftShiftExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class RightShiftExpression : public BinaryExpression { class RightShiftExpression : public BinaryExpression {
@ -279,7 +279,7 @@ public:
RightShiftExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} RightShiftExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class AndExpression : public BinaryExpression { class AndExpression : public BinaryExpression {
@ -288,7 +288,7 @@ public:
AndExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} AndExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class OrExpression : public BinaryExpression { class OrExpression : public BinaryExpression {
@ -297,7 +297,7 @@ public:
OrExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} OrExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class XorExpression : public BinaryExpression { class XorExpression : public BinaryExpression {
@ -306,7 +306,7 @@ public:
XorExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} XorExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class DivExpression : public BinaryExpression { class DivExpression : public BinaryExpression {
@ -315,7 +315,7 @@ public:
DivExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {} DivExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class MinusExpression : public UnaryExpression { class MinusExpression : public UnaryExpression {
@ -324,7 +324,7 @@ public:
MinusExpression(PatternExpression *u) : UnaryExpression(u) {} MinusExpression(PatternExpression *u) : UnaryExpression(u) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
class NotExpression : public UnaryExpression { class NotExpression : public UnaryExpression {
@ -333,7 +333,7 @@ public:
NotExpression(PatternExpression *u) : UnaryExpression(u) {} NotExpression(PatternExpression *u) : UnaryExpression(u) {}
virtual intb getValue(ParserWalker &walker) const; virtual intb getValue(ParserWalker &walker) const;
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const; virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
}; };
struct OperandResolve { struct OperandResolve {

View file

@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include "slghpattern.hh" #include "slghpattern.hh"
#include "slaformat.hh"
namespace ghidra { namespace ghidra {
@ -137,17 +138,18 @@ bool DisjointPattern::resolvesIntersect(const DisjointPattern *op1,const Disjoin
return resolveIntersectBlock(op1->getBlock(true),op2->getBlock(true),getBlock(true)); return resolveIntersectBlock(op1->getBlock(true),op2->getBlock(true),getBlock(true));
} }
DisjointPattern *DisjointPattern::restoreDisjoint(const Element *el) DisjointPattern *DisjointPattern::decodeDisjoint(Decoder &decoder)
{ // DisjointPattern factory { // DisjointPattern factory
DisjointPattern *res; DisjointPattern *res;
if (el->getName() == "instruct_pat") uint4 el = decoder.peekElement();
if (el == sla::ELEM_INSTRUCT_PAT)
res = new InstructionPattern(); res = new InstructionPattern();
else if (el->getName() == "context_pat") else if (el == sla::ELEM_CONTEXT_PAT)
res = new ContextPattern(); res = new ContextPattern();
else else
res = new CombinePattern(); res = new CombinePattern();
res->restoreXml(el); res->decode(decoder);
return res; return res;
} }
@ -485,54 +487,37 @@ bool PatternBlock::isContextMatch(ParserWalker &walker) const
return true; return true;
} }
void PatternBlock::saveXml(ostream &s) const void PatternBlock::encode(Encoder &encoder) const
{ {
s << "<pat_block "; encoder.openElement(sla::ELEM_PAT_BLOCK);
s << "offset=\"" << dec << offset << "\" "; encoder.writeSignedInteger(sla::ATTRIB_OFF, offset);
s << "nonzero=\"" << nonzerosize << "\">\n"; encoder.writeSignedInteger(sla::ATTRIB_NONZERO, nonzerosize);
for(int4 i=0;i<maskvec.size();++i) { for(int4 i=0;i<maskvec.size();++i) {
s << " <mask_word "; encoder.openElement(sla::ELEM_MASK_WORD);
s << "mask=\"0x" << hex << maskvec[i] << "\" "; encoder.writeUnsignedInteger(sla::ATTRIB_MASK, maskvec[i]);
s << "val=\"0x" << valvec[i] << "\"/>\n"; encoder.writeUnsignedInteger(sla::ATTRIB_VAL, valvec[i]);
encoder.closeElement(sla::ELEM_MASK_WORD);
} }
s << "</pat_block>\n"; encoder.closeElement(sla::ELEM_PAT_BLOCK);
} }
void PatternBlock::restoreXml(const Element *el) void PatternBlock::decode(Decoder &decoder)
{ {
{ uint4 el = decoder.openElement(sla::ELEM_PAT_BLOCK);
istringstream s(el->getAttributeValue("offset")); offset = decoder.readSignedInteger(sla::ATTRIB_OFF);
s.unsetf(ios::dec | ios::hex | ios::oct); nonzerosize = decoder.readSignedInteger(sla::ATTRIB_NONZERO);
s >> offset; while(decoder.peekElement() != 0) {
} uint4 subel = decoder.openElement(sla::ELEM_MASK_WORD);
{ uintm mask = decoder.readUnsignedInteger(sla::ATTRIB_MASK);
istringstream s(el->getAttributeValue("nonzero")); uintm val = decoder.readUnsignedInteger(sla::ATTRIB_VAL);
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> nonzerosize;
}
const List &list(el->getChildren());
List::const_iterator iter;
iter = list.begin();
uintm mask,val;
while(iter != list.end()) {
Element *subel = *iter;
{
istringstream s(subel->getAttributeValue("mask"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> mask;
}
{
istringstream s(subel->getAttributeValue("val"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> val;
}
maskvec.push_back(mask); maskvec.push_back(mask);
valvec.push_back(val); valvec.push_back(val);
++iter; decoder.closeElement(subel);
} }
normalize(); normalize();
decoder.closeElement(el);
} }
Pattern *InstructionPattern::doAnd(const Pattern *b,int4 sa) const Pattern *InstructionPattern::doAnd(const Pattern *b,int4 sa) const
@ -623,22 +608,21 @@ Pattern *InstructionPattern::doOr(const Pattern *b,int4 sa) const
return new OrPattern(res1,res2); return new OrPattern(res1,res2);
} }
void InstructionPattern::saveXml(ostream &s) const void InstructionPattern::encode(Encoder &encoder) const
{ {
s << "<instruct_pat>\n"; encoder.openElement(sla::ELEM_INSTRUCT_PAT);
maskvalue->saveXml(s); maskvalue->encode(encoder);
s << "</instruct_pat>\n"; encoder.closeElement(sla::ELEM_INSTRUCT_PAT);
} }
void InstructionPattern::restoreXml(const Element *el) void InstructionPattern::decode(Decoder &decoder)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement(sla::ELEM_INSTRUCT_PAT);
List::const_iterator iter;
iter = list.begin();
maskvalue = new PatternBlock(true); maskvalue = new PatternBlock(true);
maskvalue->restoreXml(*iter); maskvalue->decode(decoder);
decoder.closeElement(el);
} }
Pattern *ContextPattern::doOr(const Pattern *b,int4 sa) const Pattern *ContextPattern::doOr(const Pattern *b,int4 sa) const
@ -673,22 +657,21 @@ Pattern *ContextPattern::commonSubPattern(const Pattern *b,int4 sa) const
return new ContextPattern(resblock); return new ContextPattern(resblock);
} }
void ContextPattern::saveXml(ostream &s) const void ContextPattern::encode(Encoder &encoder) const
{ {
s << "<context_pat>\n"; encoder.openElement(sla::ELEM_CONTEXT_PAT);
maskvalue->saveXml(s); maskvalue->encode(encoder);
s << "</context_pat>\n"; encoder.closeElement(sla::ELEM_CONTEXT_PAT);
} }
void ContextPattern::restoreXml(const Element *el) void ContextPattern::decode(Decoder &decoder)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement(sla::ELEM_CONTEXT_PAT);
List::const_iterator iter;
iter = list.begin();
maskvalue = new PatternBlock(true); maskvalue = new PatternBlock(true);
maskvalue->restoreXml(*iter); maskvalue->decode(decoder);
decoder.closeElement(el);
} }
CombinePattern::~CombinePattern(void) CombinePattern::~CombinePattern(void)
@ -804,26 +787,24 @@ Pattern *CombinePattern::simplifyClone(void) const
(InstructionPattern *)instr->simplifyClone()); (InstructionPattern *)instr->simplifyClone());
} }
void CombinePattern::saveXml(ostream &s) const void CombinePattern::encode(Encoder &encoder) const
{ {
s << "<combine_pat>\n"; encoder.openElement(sla::ELEM_COMBINE_PAT);
context->saveXml(s); context->encode(encoder);
instr->saveXml(s); instr->encode(encoder);
s << "</combine_pat>\n"; encoder.closeElement(sla::ELEM_COMBINE_PAT);
} }
void CombinePattern::restoreXml(const Element *el) void CombinePattern::decode(Decoder &decoder)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement(sla::ELEM_COMBINE_PAT);
List::const_iterator iter;
iter = list.begin();
context = new ContextPattern(); context = new ContextPattern();
context->restoreXml(*iter); context->decode(decoder);
++iter;
instr = new InstructionPattern(); instr = new InstructionPattern();
instr->restoreXml(*iter); instr->decode(decoder);
decoder.closeElement(el);
} }
OrPattern::OrPattern(DisjointPattern *a,DisjointPattern *b) OrPattern::OrPattern(DisjointPattern *a,DisjointPattern *b)
@ -995,26 +976,24 @@ Pattern *OrPattern::simplifyClone(void) const
return new OrPattern(newlist); return new OrPattern(newlist);
} }
void OrPattern::saveXml(ostream &s) const void OrPattern::encode(Encoder &encoder) const
{ {
s << "<or_pat>\n"; encoder.openElement(sla::ELEM_OR_PAT);
for(int4 i=0;i<orlist.size();++i) for(int4 i=0;i<orlist.size();++i)
orlist[i]->saveXml(s); orlist[i]->encode(encoder);
s << "</or_pat>\n"; encoder.closeElement(sla::ELEM_OR_PAT);
} }
void OrPattern::restoreXml(const Element *el) void OrPattern::decode(Decoder &decoder)
{ {
const List &list(el->getChildren()); uint4 el = decoder.openElement(sla::ELEM_OR_PAT);
List::const_iterator iter; while(decoder.peekElement() != 0) {
iter = list.begin(); DisjointPattern *pat = DisjointPattern::decodeDisjoint(decoder);
while(iter != list.end()) {
DisjointPattern *pat = DisjointPattern::restoreDisjoint(*iter);
orlist.push_back(pat); orlist.push_back(pat);
++iter;
} }
decoder.closeElement(el);
} }
} // End namespace ghidra } // End namespace ghidra

View file

@ -45,8 +45,8 @@ public:
bool alwaysFalse(void) const { return (nonzerosize==-1); } bool alwaysFalse(void) const { return (nonzerosize==-1); }
bool isInstructionMatch(ParserWalker &walker) const; bool isInstructionMatch(ParserWalker &walker) const;
bool isContextMatch(ParserWalker &walker) const; bool isContextMatch(ParserWalker &walker) const;
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el); void decode(Decoder &decoder);
}; };
class DisjointPattern; class DisjointPattern;
@ -64,8 +64,8 @@ public:
virtual bool alwaysTrue(void) const=0; virtual bool alwaysTrue(void) const=0;
virtual bool alwaysFalse(void) const=0; virtual bool alwaysFalse(void) const=0;
virtual bool alwaysInstructionTrue(void) const=0; virtual bool alwaysInstructionTrue(void) const=0;
virtual void saveXml(ostream &s) const=0; virtual void encode(Encoder &encoder) const=0;
virtual void restoreXml(const Element *el)=0; virtual void decode(Decoder &decoder)=0;
}; };
class DisjointPattern : public Pattern { // A pattern with no ORs in it class DisjointPattern : public Pattern { // A pattern with no ORs in it
@ -79,14 +79,14 @@ public:
bool specializes(const DisjointPattern *op2) const; bool specializes(const DisjointPattern *op2) const;
bool identical(const DisjointPattern *op2) const; bool identical(const DisjointPattern *op2) const;
bool resolvesIntersect(const DisjointPattern *op1,const DisjointPattern *op2) const; bool resolvesIntersect(const DisjointPattern *op1,const DisjointPattern *op2) const;
static DisjointPattern *restoreDisjoint(const Element *el); static DisjointPattern *decodeDisjoint(Decoder &decoder);
}; };
class InstructionPattern : public DisjointPattern { // Matches the instruction bitstream class InstructionPattern : public DisjointPattern { // Matches the instruction bitstream
PatternBlock *maskvalue; PatternBlock *maskvalue;
virtual PatternBlock *getBlock(bool context) const { return context ? (PatternBlock *)0 : maskvalue; } virtual PatternBlock *getBlock(bool context) const { return context ? (PatternBlock *)0 : maskvalue; }
public: public:
InstructionPattern(void) { maskvalue = (PatternBlock *)0; } // For use with restoreXml InstructionPattern(void) { maskvalue = (PatternBlock *)0; } // For use with decode
InstructionPattern(PatternBlock *mv) { maskvalue = mv; } InstructionPattern(PatternBlock *mv) { maskvalue = mv; }
InstructionPattern(bool tf) { maskvalue = new PatternBlock(tf); } InstructionPattern(bool tf) { maskvalue = new PatternBlock(tf); }
PatternBlock *getBlock(void) { return maskvalue; } PatternBlock *getBlock(void) { return maskvalue; }
@ -100,15 +100,15 @@ public:
virtual bool alwaysTrue(void) const { return maskvalue->alwaysTrue(); } virtual bool alwaysTrue(void) const { return maskvalue->alwaysTrue(); }
virtual bool alwaysFalse(void) const { return maskvalue->alwaysFalse(); } virtual bool alwaysFalse(void) const { return maskvalue->alwaysFalse(); }
virtual bool alwaysInstructionTrue(void) const { return maskvalue->alwaysTrue(); } virtual bool alwaysInstructionTrue(void) const { return maskvalue->alwaysTrue(); }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el); virtual void decode(Decoder &decoder);
}; };
class ContextPattern : public DisjointPattern { // Matches the context bitstream class ContextPattern : public DisjointPattern { // Matches the context bitstream
PatternBlock *maskvalue; PatternBlock *maskvalue;
virtual PatternBlock *getBlock(bool context) const { return context ? maskvalue : (PatternBlock *)0; } virtual PatternBlock *getBlock(bool context) const { return context ? maskvalue : (PatternBlock *)0; }
public: public:
ContextPattern(void) { maskvalue = (PatternBlock *)0; } // For use with restoreXml ContextPattern(void) { maskvalue = (PatternBlock *)0; } // For use with decode
ContextPattern(PatternBlock *mv) { maskvalue = mv; } ContextPattern(PatternBlock *mv) { maskvalue = mv; }
PatternBlock *getBlock(void) { return maskvalue; } PatternBlock *getBlock(void) { return maskvalue; }
virtual ~ContextPattern(void) { if (maskvalue != (PatternBlock *)0) delete maskvalue; } virtual ~ContextPattern(void) { if (maskvalue != (PatternBlock *)0) delete maskvalue; }
@ -121,8 +121,8 @@ public:
virtual bool alwaysTrue(void) const { return maskvalue->alwaysTrue(); } virtual bool alwaysTrue(void) const { return maskvalue->alwaysTrue(); }
virtual bool alwaysFalse(void) const { return maskvalue->alwaysFalse(); } virtual bool alwaysFalse(void) const { return maskvalue->alwaysFalse(); }
virtual bool alwaysInstructionTrue(void) const { return true; } virtual bool alwaysInstructionTrue(void) const { return true; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el); virtual void decode(Decoder &decoder);
}; };
// A pattern with a context piece and an instruction piece // A pattern with a context piece and an instruction piece
@ -144,14 +144,14 @@ public:
virtual Pattern *doOr(const Pattern *b,int4 sa) const; virtual Pattern *doOr(const Pattern *b,int4 sa) const;
virtual Pattern *doAnd(const Pattern *b,int4 sa) const; virtual Pattern *doAnd(const Pattern *b,int4 sa) const;
virtual Pattern *commonSubPattern(const Pattern *b,int4 sa) const; virtual Pattern *commonSubPattern(const Pattern *b,int4 sa) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el); virtual void decode(Decoder &decoder);
}; };
class OrPattern : public Pattern { class OrPattern : public Pattern {
vector<DisjointPattern *> orlist; vector<DisjointPattern *> orlist;
public: public:
OrPattern(void) {} // For use with restoreXml OrPattern(void) {} // For use with decode
OrPattern(DisjointPattern *a,DisjointPattern *b); OrPattern(DisjointPattern *a,DisjointPattern *b);
OrPattern(const vector<DisjointPattern *> &list); OrPattern(const vector<DisjointPattern *> &list);
virtual ~OrPattern(void); virtual ~OrPattern(void);
@ -166,8 +166,8 @@ public:
virtual Pattern *doOr(const Pattern *b,int4 sa) const; virtual Pattern *doOr(const Pattern *b,int4 sa) const;
virtual Pattern *doAnd(const Pattern *b,int4 sa) const; virtual Pattern *doAnd(const Pattern *b,int4 sa) const;
virtual Pattern *commonSubPattern(const Pattern *b,int4 sa) const; virtual Pattern *commonSubPattern(const Pattern *b,int4 sa) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el); virtual void decode(Decoder &decoder);
}; };
} // End namespace ghidra } // End namespace ghidra

File diff suppressed because it is too large Load diff

View file

@ -35,16 +35,16 @@ private:
uintm id; // Unique id across all symbols uintm id; // Unique id across all symbols
uintm scopeid; // Unique id of scope this symbol is in uintm scopeid; // Unique id of scope this symbol is in
public: public:
SleighSymbol(void) {} // For use with restoreXml SleighSymbol(void) {} // For use with decode
SleighSymbol(const string &nm) { name = nm; id = 0; } SleighSymbol(const string &nm) { name = nm; id = 0; }
virtual ~SleighSymbol(void) {} virtual ~SleighSymbol(void) {}
const string &getName(void) const { return name; } const string &getName(void) const { return name; }
uintm getId(void) const { return id; } uintm getId(void) const { return id; }
virtual symbol_type getType(void) const { return dummy_symbol; } virtual symbol_type getType(void) const { return dummy_symbol; }
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
void restoreXmlHeader(const Element *el); void decodeHeader(Decoder &decoder);
virtual void saveXml(ostream &s) const {} virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans) {} virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
struct SymbolCompare { struct SymbolCompare {
@ -92,9 +92,9 @@ public:
SleighSymbol *findGlobalSymbol(const string &nm) const { return findSymbolInternal(table[0],nm); } SleighSymbol *findGlobalSymbol(const string &nm) const { return findSymbolInternal(table[0],nm); }
SleighSymbol *findSymbol(uintm id) const { return symbollist[id]; } SleighSymbol *findSymbol(uintm id) const { return symbollist[id]; }
void replaceSymbol(SleighSymbol *a,SleighSymbol *b); void replaceSymbol(SleighSymbol *a,SleighSymbol *b);
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,SleighBase *trans); void decode(Decoder &decoder,SleighBase *trans);
void restoreSymbolHeader(const Element *el); void decodeSymbolHeader(Decoder &decoder);
void purge(void); void purge(void);
}; };
@ -127,20 +127,19 @@ public:
int4 getDefineCount(void) const { return define_count; } int4 getDefineCount(void) const { return define_count; }
int4 getRefCount(void) const { return ref_count; } int4 getRefCount(void) const { return ref_count; }
virtual symbol_type getType(void) const { return section_symbol; } virtual symbol_type getType(void) const { return section_symbol; }
// Not saved or restored
}; };
class UserOpSymbol : public SleighSymbol { // A user-defined pcode-op class UserOpSymbol : public SleighSymbol { // A user-defined pcode-op
uint4 index; uint4 index;
public: public:
UserOpSymbol(void) {} // For use with restoreXml UserOpSymbol(void) {} // For use with decode
UserOpSymbol(const string &nm) : SleighSymbol(nm) { index = 0; } UserOpSymbol(const string &nm) : SleighSymbol(nm) { index = 0; }
void setIndex(uint4 ind) { index = ind; } void setIndex(uint4 ind) { index = ind; }
uint4 getIndex(void) const { return index; } uint4 getIndex(void) const { return index; }
virtual symbol_type getType(void) const { return userop_symbol; } virtual symbol_type getType(void) const { return userop_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class Constructor; // Forward declaration class Constructor; // Forward declaration
@ -174,33 +173,31 @@ public:
class PatternlessSymbol : public SpecificSymbol { // Behaves like constant 0 pattern class PatternlessSymbol : public SpecificSymbol { // Behaves like constant 0 pattern
ConstantValue *patexp; ConstantValue *patexp;
public: public:
PatternlessSymbol(void); // For use with restoreXml PatternlessSymbol(void); // For use with decode
PatternlessSymbol(const string &nm); PatternlessSymbol(const string &nm);
virtual ~PatternlessSymbol(void); virtual ~PatternlessSymbol(void);
virtual PatternExpression *getPatternExpression(void) const { return patexp; } virtual PatternExpression *getPatternExpression(void) const { return patexp; }
virtual void saveXml(ostream &s) const {}
virtual void restoreXml(const Element *el,SleighBase *trans) {}
}; };
class EpsilonSymbol : public PatternlessSymbol { // Another name for zero pattern/value class EpsilonSymbol : public PatternlessSymbol { // Another name for zero pattern/value
AddrSpace *const_space; AddrSpace *const_space;
public: public:
EpsilonSymbol(void) {} // For use with restoreXml EpsilonSymbol(void) {} // For use with decode
EpsilonSymbol(const string &nm,AddrSpace *spc) : PatternlessSymbol(nm) { const_space=spc; } EpsilonSymbol(const string &nm,AddrSpace *spc) : PatternlessSymbol(nm) { const_space=spc; }
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return epsilon_symbol; } virtual symbol_type getType(void) const { return epsilon_symbol; }
virtual VarnodeTpl *getVarnode(void) const; virtual VarnodeTpl *getVarnode(void) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class ValueSymbol : public FamilySymbol { class ValueSymbol : public FamilySymbol {
protected: protected:
PatternValue *patval; PatternValue *patval;
public: public:
ValueSymbol(void) { patval = (PatternValue *)0; } // For use with restoreXml ValueSymbol(void) { patval = (PatternValue *)0; } // For use with decode
ValueSymbol(const string &nm,PatternValue *pv); ValueSymbol(const string &nm,PatternValue *pv);
virtual ~ValueSymbol(void); virtual ~ValueSymbol(void);
virtual PatternValue *getPatternValue(void) const { return patval; } virtual PatternValue *getPatternValue(void) const { return patval; }
@ -208,9 +205,9 @@ public:
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return value_symbol; } virtual symbol_type getType(void) const { return value_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class ValueMapSymbol : public ValueSymbol { class ValueMapSymbol : public ValueSymbol {
@ -218,15 +215,15 @@ class ValueMapSymbol : public ValueSymbol {
bool tableisfilled; bool tableisfilled;
void checkTableFill(void); void checkTableFill(void);
public: public:
ValueMapSymbol(void) {} // For use with restoreXml ValueMapSymbol(void) {} // For use with decode
ValueMapSymbol(const string &nm,PatternValue *pv,const vector<intb> &vt) : ValueSymbol(nm,pv) { valuetable=vt; checkTableFill(); } ValueMapSymbol(const string &nm,PatternValue *pv,const vector<intb> &vt) : ValueSymbol(nm,pv) { valuetable=vt; checkTableFill(); }
virtual Constructor *resolve(ParserWalker &walker); virtual Constructor *resolve(ParserWalker &walker);
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return valuemap_symbol; } virtual symbol_type getType(void) const { return valuemap_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class NameSymbol : public ValueSymbol { class NameSymbol : public ValueSymbol {
@ -234,21 +231,21 @@ class NameSymbol : public ValueSymbol {
bool tableisfilled; bool tableisfilled;
void checkTableFill(void); void checkTableFill(void);
public: public:
NameSymbol(void) {} // For use with restoreXml NameSymbol(void) {} // For use with decode
NameSymbol(const string &nm,PatternValue *pv,const vector<string> &nt) : ValueSymbol(nm,pv) { nametable=nt; checkTableFill(); } NameSymbol(const string &nm,PatternValue *pv,const vector<string> &nt) : ValueSymbol(nm,pv) { nametable=nt; checkTableFill(); }
virtual Constructor *resolve(ParserWalker &walker); virtual Constructor *resolve(ParserWalker &walker);
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return name_symbol; } virtual symbol_type getType(void) const { return name_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class VarnodeSymbol : public PatternlessSymbol { // A global varnode class VarnodeSymbol : public PatternlessSymbol { // A global varnode
VarnodeData fix; VarnodeData fix;
bool context_bits; bool context_bits;
public: public:
VarnodeSymbol(void) {} // For use with restoreXml VarnodeSymbol(void) {} // For use with decode
VarnodeSymbol(const string &nm,AddrSpace *base,uintb offset,int4 size); VarnodeSymbol(const string &nm,AddrSpace *base,uintb offset,int4 size);
void markAsContext(void) { context_bits = true; } void markAsContext(void) { context_bits = true; }
const VarnodeData &getFixedVarnode(void) const { return fix; } const VarnodeData &getFixedVarnode(void) const { return fix; }
@ -259,9 +256,9 @@ public:
s << getName(); } s << getName(); }
virtual void collectLocalValues(vector<uintb> &results) const; virtual void collectLocalValues(vector<uintb> &results) const;
virtual symbol_type getType(void) const { return varnode_symbol; } virtual symbol_type getType(void) const { return varnode_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class BitrangeSymbol : public SleighSymbol { // A smaller bitrange within a varnode class BitrangeSymbol : public SleighSymbol { // A smaller bitrange within a varnode
@ -269,7 +266,7 @@ class BitrangeSymbol : public SleighSymbol { // A smaller bitrange within a varn
uint4 bitoffset; // least significant bit of range uint4 bitoffset; // least significant bit of range
uint4 numbits; // number of bits in the range uint4 numbits; // number of bits in the range
public: public:
BitrangeSymbol(void) {} // For use with restoreXml BitrangeSymbol(void) {} // For use with decode
BitrangeSymbol(const string &nm,VarnodeSymbol *sym,uint4 bitoff,uint4 num) BitrangeSymbol(const string &nm,VarnodeSymbol *sym,uint4 bitoff,uint4 num)
: SleighSymbol(nm) { varsym=sym; bitoffset=bitoff; numbits=num; } : SleighSymbol(nm) { varsym=sym; bitoffset=bitoff; numbits=num; }
VarnodeSymbol *getParentSymbol(void) const { return varsym; } VarnodeSymbol *getParentSymbol(void) const { return varsym; }
@ -283,16 +280,16 @@ class ContextSymbol : public ValueSymbol {
uint4 low,high; // into a varnode uint4 low,high; // into a varnode
bool flow; bool flow;
public: public:
ContextSymbol(void) {} // For use with restoreXml ContextSymbol(void) {} // For use with decode
ContextSymbol(const string &nm,ContextField *pate,VarnodeSymbol *v,uint4 l,uint4 h,bool flow); ContextSymbol(const string &nm,ContextField *pate,VarnodeSymbol *v,uint4 l,uint4 h,bool flow);
VarnodeSymbol *getVarnode(void) const { return vn; } VarnodeSymbol *getVarnode(void) const { return vn; }
uint4 getLow(void) const { return low; } uint4 getLow(void) const { return low; }
uint4 getHigh(void) const { return high; } uint4 getHigh(void) const { return high; }
bool getFlow(void) const { return flow; } bool getFlow(void) const { return flow; }
virtual symbol_type getType(void) const { return context_symbol; } virtual symbol_type getType(void) const { return context_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class VarnodeListSymbol : public ValueSymbol { class VarnodeListSymbol : public ValueSymbol {
@ -300,16 +297,16 @@ class VarnodeListSymbol : public ValueSymbol {
bool tableisfilled; bool tableisfilled;
void checkTableFill(void); void checkTableFill(void);
public: public:
VarnodeListSymbol(void) {} // For use with restoreXml VarnodeListSymbol(void) {} // For use with decode
VarnodeListSymbol(const string &nm,PatternValue *pv,const vector<SleighSymbol *> &vt); VarnodeListSymbol(const string &nm,PatternValue *pv,const vector<SleighSymbol *> &vt);
virtual Constructor *resolve(ParserWalker &walker); virtual Constructor *resolve(ParserWalker &walker);
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual int4 getSize(void) const; virtual int4 getSize(void) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return varnodelist_symbol; } virtual symbol_type getType(void) const { return varnodelist_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class OperandSymbol : public SpecificSymbol { class OperandSymbol : public SpecificSymbol {
@ -329,7 +326,7 @@ private:
void setVariableLength(void) { flags |= variable_len; } void setVariableLength(void) { flags |= variable_len; }
bool isVariableLength(void) const { return ((flags&variable_len)!=0); } bool isVariableLength(void) const { return ((flags&variable_len)!=0); }
public: public:
OperandSymbol(void) {} // For use with restoreXml OperandSymbol(void) {} // For use with decode
OperandSymbol(const string &nm,int4 index,Constructor *ct); OperandSymbol(const string &nm,int4 index,Constructor *ct);
uint4 getRelativeOffset(void) const { return reloffset; } uint4 getRelativeOffset(void) const { return reloffset; }
int4 getOffsetBase(void) const { return offsetbase; } int4 getOffsetBase(void) const { return offsetbase; }
@ -354,16 +351,16 @@ public:
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual void collectLocalValues(vector<uintb> &results) const; virtual void collectLocalValues(vector<uintb> &results) const;
virtual symbol_type getType(void) const { return operand_symbol; } virtual symbol_type getType(void) const { return operand_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class StartSymbol : public SpecificSymbol { class StartSymbol : public SpecificSymbol {
AddrSpace *const_space; AddrSpace *const_space;
PatternExpression *patexp; PatternExpression *patexp;
public: public:
StartSymbol(void) { patexp = (PatternExpression *)0; } // For use with restoreXml StartSymbol(void) { patexp = (PatternExpression *)0; } // For use with decode
StartSymbol(const string &nm,AddrSpace *cspc); StartSymbol(const string &nm,AddrSpace *cspc);
virtual ~StartSymbol(void); virtual ~StartSymbol(void);
virtual VarnodeTpl *getVarnode(void) const; virtual VarnodeTpl *getVarnode(void) const;
@ -371,16 +368,16 @@ public:
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return start_symbol; } virtual symbol_type getType(void) const { return start_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class EndSymbol : public SpecificSymbol { class EndSymbol : public SpecificSymbol {
AddrSpace *const_space; AddrSpace *const_space;
PatternExpression *patexp; PatternExpression *patexp;
public: public:
EndSymbol(void) { patexp = (PatternExpression *)0; } // For use with restoreXml EndSymbol(void) { patexp = (PatternExpression *)0; } // For use with decode
EndSymbol(const string &nm,AddrSpace *cspc); EndSymbol(const string &nm,AddrSpace *cspc);
virtual ~EndSymbol(void); virtual ~EndSymbol(void);
virtual VarnodeTpl *getVarnode(void) const; virtual VarnodeTpl *getVarnode(void) const;
@ -388,16 +385,16 @@ public:
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return end_symbol; } virtual symbol_type getType(void) const { return end_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class Next2Symbol : public SpecificSymbol { class Next2Symbol : public SpecificSymbol {
AddrSpace *const_space; AddrSpace *const_space;
PatternExpression *patexp; PatternExpression *patexp;
public: public:
Next2Symbol(void) { patexp = (PatternExpression *)0; } // For use with restoreXml Next2Symbol(void) { patexp = (PatternExpression *)0; } // For use with decode
Next2Symbol(const string &nm,AddrSpace *cspc); Next2Symbol(const string &nm,AddrSpace *cspc);
virtual ~Next2Symbol(void); virtual ~Next2Symbol(void);
virtual VarnodeTpl *getVarnode(void) const; virtual VarnodeTpl *getVarnode(void) const;
@ -405,47 +402,41 @@ public:
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return next2_symbol; } virtual symbol_type getType(void) const { return next2_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class FlowDestSymbol : public SpecificSymbol { class FlowDestSymbol : public SpecificSymbol {
AddrSpace *const_space; AddrSpace *const_space;
public: public:
FlowDestSymbol(void) {} // For use with restoreXml FlowDestSymbol(void) {} // For use with decode
FlowDestSymbol(const string &nm,AddrSpace *cspc); FlowDestSymbol(const string &nm,AddrSpace *cspc);
virtual VarnodeTpl *getVarnode(void) const; virtual VarnodeTpl *getVarnode(void) const;
virtual PatternExpression *getPatternExpression(void) const { throw SleighError("Cannot use symbol in pattern"); } virtual PatternExpression *getPatternExpression(void) const { throw SleighError("Cannot use symbol in pattern"); }
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return start_symbol; } virtual symbol_type getType(void) const { return start_symbol; }
virtual void saveXml(ostream &s) const;
virtual void saveXmlHeader(ostream &s) const;
virtual void restoreXml(const Element *el,SleighBase *trans);
}; };
class FlowRefSymbol : public SpecificSymbol { class FlowRefSymbol : public SpecificSymbol {
AddrSpace *const_space; AddrSpace *const_space;
public: public:
FlowRefSymbol(void) {} // For use with restoreXml FlowRefSymbol(void) {} // For use with decode
FlowRefSymbol(const string &nm,AddrSpace *cspc); FlowRefSymbol(const string &nm,AddrSpace *cspc);
virtual VarnodeTpl *getVarnode(void) const; virtual VarnodeTpl *getVarnode(void) const;
virtual PatternExpression *getPatternExpression(void) const { throw SleighError("Cannot use symbol in pattern"); } virtual PatternExpression *getPatternExpression(void) const { throw SleighError("Cannot use symbol in pattern"); }
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const; virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
virtual void print(ostream &s,ParserWalker &walker) const; virtual void print(ostream &s,ParserWalker &walker) const;
virtual symbol_type getType(void) const { return start_symbol; } virtual symbol_type getType(void) const { return start_symbol; }
virtual void saveXml(ostream &s) const;
virtual void saveXmlHeader(ostream &s) const;
virtual void restoreXml(const Element *el,SleighBase *trans);
}; };
class ContextChange { // Change to context command class ContextChange { // Change to context command
public: public:
virtual ~ContextChange(void) {} virtual ~ContextChange(void) {}
virtual void validate(void) const=0; virtual void validate(void) const=0;
virtual void saveXml(ostream &s) const=0; virtual void encode(Encoder &encoder) const=0;
virtual void restoreXml(const Element *el,SleighBase *trans)=0; virtual void decode(Decoder &decoder,SleighBase *trans)=0;
virtual void apply(ParserWalkerChange &walker) const=0; virtual void apply(ParserWalkerChange &walker) const=0;
virtual ContextChange *clone(void) const=0; virtual ContextChange *clone(void) const=0;
}; };
@ -457,11 +448,11 @@ class ContextOp : public ContextChange {
int4 shift; // Number of bits to shift value into place int4 shift; // Number of bits to shift value into place
public: public:
ContextOp(int4 startbit,int4 endbit,PatternExpression *pe); ContextOp(int4 startbit,int4 endbit,PatternExpression *pe);
ContextOp(void) {} // For use with restoreXml ContextOp(void) {} // For use with decode
virtual ~ContextOp(void) { PatternExpression::release(patexp); } virtual ~ContextOp(void) { PatternExpression::release(patexp); }
virtual void validate(void) const; virtual void validate(void) const;
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
virtual void apply(ParserWalkerChange &walker) const; virtual void apply(ParserWalkerChange &walker) const;
virtual ContextChange *clone(void) const; virtual ContextChange *clone(void) const;
}; };
@ -472,11 +463,11 @@ class ContextCommit : public ContextChange {
uintm mask; // mask of bits in word being committed uintm mask; // mask of bits in word being committed
bool flow; // Whether the context "flows" from the point of change bool flow; // Whether the context "flows" from the point of change
public: public:
ContextCommit(void) {} // For use with restoreXml ContextCommit(void) {} // For use with decode
ContextCommit(TripleSymbol *s,int4 sbit,int4 ebit,bool fl); ContextCommit(TripleSymbol *s,int4 sbit,int4 ebit,bool fl);
virtual void validate(void) const {} virtual void validate(void) const {}
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
virtual void apply(ParserWalkerChange &walker) const; virtual void apply(ParserWalkerChange &walker) const;
virtual ContextChange *clone(void) const; virtual ContextChange *clone(void) const;
}; };
@ -500,7 +491,7 @@ class Constructor { // This is NOT a symbol
mutable bool inerror; // An error is associated with this Constructor mutable bool inerror; // An error is associated with this Constructor
void orderOperands(void); void orderOperands(void);
public: public:
Constructor(void); // For use with restoreXml Constructor(void); // For use with decode
Constructor(SubtableSymbol *p); Constructor(SubtableSymbol *p);
~Constructor(void); ~Constructor(void);
TokenPattern *buildPattern(ostream &s); TokenPattern *buildPattern(ostream &s);
@ -542,8 +533,8 @@ public:
void setError(bool val) const { inerror = val; } void setError(bool val) const { inerror = val; }
bool isError(void) const { return inerror; } bool isError(void) const { return inerror; }
bool isRecursive(void) const; bool isRecursive(void) const;
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,SleighBase *trans); void decode(Decoder &decoder,SleighBase *trans);
}; };
class DecisionProperties { class DecisionProperties {
@ -569,15 +560,15 @@ class DecisionNode {
int4 getMaximumLength(bool context); int4 getMaximumLength(bool context);
void consistentValues(vector<uint4> &bins,DisjointPattern *pat); void consistentValues(vector<uint4> &bins,DisjointPattern *pat);
public: public:
DecisionNode(void) {} // For use with restoreXml DecisionNode(void) {} // For use with decode
DecisionNode(DecisionNode *p); DecisionNode(DecisionNode *p);
~DecisionNode(void); ~DecisionNode(void);
Constructor *resolve(ParserWalker &walker) const; Constructor *resolve(ParserWalker &walker) const;
void addConstructorPair(const DisjointPattern *pat,Constructor *ct); void addConstructorPair(const DisjointPattern *pat,Constructor *ct);
void split(DecisionProperties &props); void split(DecisionProperties &props);
void orderPatterns(DecisionProperties &props); void orderPatterns(DecisionProperties &props);
void saveXml(ostream &s) const; void encode(Encoder &encoder) const;
void restoreXml(const Element *el,DecisionNode *par,SubtableSymbol *sub); void decode(Decoder &decoder,DecisionNode *par,SubtableSymbol *sub);
}; };
class SubtableSymbol : public TripleSymbol { class SubtableSymbol : public TripleSymbol {
@ -586,7 +577,7 @@ class SubtableSymbol : public TripleSymbol {
vector<Constructor *> construct; // All the Constructors in this table vector<Constructor *> construct; // All the Constructors in this table
DecisionNode *decisiontree; DecisionNode *decisiontree;
public: public:
SubtableSymbol(void) { pattern = (TokenPattern *)0; decisiontree = (DecisionNode *)0; } // For use with restoreXml SubtableSymbol(void) { pattern = (TokenPattern *)0; decisiontree = (DecisionNode *)0; } // For use with decode
SubtableSymbol(const string &nm); SubtableSymbol(const string &nm);
virtual ~SubtableSymbol(void); virtual ~SubtableSymbol(void);
bool isBeingBuilt(void) const { return beingbuilt; } bool isBeingBuilt(void) const { return beingbuilt; }
@ -606,9 +597,9 @@ public:
throw SleighError("Cannot use subtable in expression"); } throw SleighError("Cannot use subtable in expression"); }
virtual void collectLocalValues(vector<uintb> &results) const; virtual void collectLocalValues(vector<uintb> &results) const;
virtual symbol_type getType(void) const { return subtable_symbol; } virtual symbol_type getType(void) const { return subtable_symbol; }
virtual void saveXml(ostream &s) const; virtual void encode(Encoder &encoder) const;
virtual void saveXmlHeader(ostream &s) const; virtual void encodeHeader(Encoder &encoder) const;
virtual void restoreXml(const Element *el,SleighBase *trans); virtual void decode(Decoder &decoder,SleighBase *trans);
}; };
class MacroSymbol : public SleighSymbol { // A user-defined pcode-macro class MacroSymbol : public SleighSymbol { // A user-defined pcode-macro

View file

@ -45,13 +45,15 @@ void AddrSpace::calcScaleMask(void)
/// \param t is the processor translator associated with the new space /// \param t is the processor translator associated with the new space
/// \param tp is the type of the new space (PROCESSOR, CONSTANT, INTERNAL,...) /// \param tp is the type of the new space (PROCESSOR, CONSTANT, INTERNAL,...)
/// \param nm is the name of the new space /// \param nm is the name of the new space
/// \param bigEnd is \b true for big endian encoding
/// \param size is the (offset encoding) size of the new space /// \param size is the (offset encoding) size of the new space
/// \param ws is the number of bytes in an addressable unit /// \param ws is the number of bytes in an addressable unit
/// \param ind is the integer identifier for the new space /// \param ind is the integer identifier for the new space
/// \param fl can be 0 or AddrSpace::hasphysical /// \param fl can be 0 or AddrSpace::hasphysical
/// \param dl is the number of rounds to delay heritage for the new space /// \param dl is the number of rounds to delay heritage for the new space
AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const string &nm, /// \param dead is the number of rounds to delay before dead code removal
uint4 size,uint4 ws, int4 ind,uint4 fl,int4 dl) AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const string &nm,bool bigEnd,
uint4 size,uint4 ws, int4 ind,uint4 fl,int4 dl,int4 dead)
{ {
refcount = 0; // No references to this space yet refcount = 0; // No references to this space yet
manage = m; manage = m;
@ -62,13 +64,13 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
wordsize = ws; wordsize = ws;
index = ind; index = ind;
delay = dl; delay = dl;
deadcodedelay = dl; // Deadcode delay initially starts the same as heritage delay deadcodedelay = dead;
minimumPointerSize = 0; // (initially) assume pointers must match the space size exactly minimumPointerSize = 0; // (initially) assume pointers must match the space size exactly
shortcut = ' '; // Placeholder meaning shortcut is unassigned shortcut = ' '; // Placeholder meaning shortcut is unassigned
// These are the flags we allow to be set from constructor // These are the flags we allow to be set from constructor
flags = (fl & hasphysical); flags = (fl & hasphysical);
if (t->isBigEndian()) if (bigEnd)
flags |= big_endian; flags |= big_endian;
flags |= (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor flags |= (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
@ -94,24 +96,6 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp)
// We let big_endian get set by attribute // We let big_endian get set by attribute
} }
/// Save the \e name, \e index, \e bigendian, \e delay,
/// \e size, \e wordsize, and \e physical attributes which
/// are common with all address spaces derived from AddrSpace
/// \param s the stream where the attributes are written
void AddrSpace::saveBasicAttributes(ostream &s) const
{
a_v(s,"name",name);
a_v_i(s,"index",index);
a_v_b(s,"bigendian",isBigEndian());
a_v_i(s,"delay",delay);
if (delay != deadcodedelay)
a_v_i(s,"deadcodedelay",deadcodedelay);
a_v_i(s,"size",addressSize);
if (wordsize > 1) a_v_i(s,"wordsize",wordsize);
a_v_b(s,"physical",hasPhysical());
}
/// The logical form of the space is truncated from its actual size /// The logical form of the space is truncated from its actual size
/// Pointers may refer to this original size put the most significant bytes are ignored /// Pointers may refer to this original size put the most significant bytes are ignored
/// \param newsize is the size (in bytes) of the truncated (logical) space /// \param newsize is the size (in bytes) of the truncated (logical) space
@ -310,17 +294,6 @@ uintb AddrSpace::read(const string &s,int4 &size) const
return offset; return offset;
} }
/// Write a tag fully describing the details of this space
/// suitable for later recovery via decode.
/// \param s is the stream being written
void AddrSpace::saveXml(ostream &s) const
{
s << "<space"; // This implies type=processor
saveBasicAttributes(s);
s << "/>\n";
}
/// Walk attributes of the current element and recover all the properties defining /// Walk attributes of the current element and recover all the properties defining
/// this space. The processor translator, \e trans, and the /// this space. The processor translator, \e trans, and the
/// \e type must already be filled in. /// \e type must already be filled in.
@ -378,7 +351,7 @@ const int4 ConstantSpace::INDEX = 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
ConstantSpace::ConstantSpace(AddrSpaceManager *m,const Translate *t) ConstantSpace::ConstantSpace(AddrSpaceManager *m,const Translate *t)
: AddrSpace(m,t,IPTR_CONSTANT,NAME,sizeof(uintb),1,INDEX,0,0) : AddrSpace(m,t,IPTR_CONSTANT,NAME,false,sizeof(uintb),1,INDEX,0,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
@ -399,14 +372,6 @@ void ConstantSpace::printRaw(ostream &s,uintb offset) const
s << "0x" << hex << offset; s << "0x" << hex << offset;
} }
/// The ConstantSpace should never be explicitly saved as it is
/// always built automatically
void ConstantSpace::saveXml(ostream &s) const
{
throw LowlevelError("Should never save the constant space as XML");
}
/// As the ConstantSpace is never saved, it should never get /// As the ConstantSpace is never saved, it should never get
/// decoded either. /// decoded either.
void ConstantSpace::decode(Decoder &decoder) void ConstantSpace::decode(Decoder &decoder)
@ -426,7 +391,7 @@ const int4 OtherSpace::INDEX = 1;
/// \param t is the associated processor translator /// \param t is the associated processor translator
/// \param ind is the integer identifier /// \param ind is the integer identifier
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t,int4 ind) OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
: AddrSpace(m,t,IPTR_PROCESSOR,NAME,sizeof(uintb),1,INDEX,0,0) : AddrSpace(m,t,IPTR_PROCESSOR,NAME,false,sizeof(uintb),1,INDEX,0,0,0)
{ {
clearFlags(heritaged|does_deadcode); clearFlags(heritaged|does_deadcode);
setFlags(is_otherspace); setFlags(is_otherspace);
@ -445,14 +410,6 @@ void OtherSpace::printRaw(ostream &s,uintb offset) const
s << "0x" << hex << offset; s << "0x" << hex << offset;
} }
void OtherSpace::saveXml(ostream &s) const
{
s << "<space_other";
saveBasicAttributes(s);
s << "/>\n";
}
const string UniqueSpace::NAME = "unique"; const string UniqueSpace::NAME = "unique";
const uint4 UniqueSpace::SIZE = 4; const uint4 UniqueSpace::SIZE = 4;
@ -465,7 +422,7 @@ const uint4 UniqueSpace::SIZE = 4;
/// \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,int4 ind,uint4 fl) UniqueSpace::UniqueSpace(AddrSpaceManager *m,const Translate *t,int4 ind,uint4 fl)
: AddrSpace(m,t,IPTR_INTERNAL,NAME,SIZE,1,ind,fl,0) : AddrSpace(m,t,IPTR_INTERNAL,NAME,t->isBigEndian(),SIZE,1,ind,fl,0,0)
{ {
setFlags(hasphysical); setFlags(hasphysical);
} }
@ -476,14 +433,6 @@ UniqueSpace::UniqueSpace(AddrSpaceManager *m,const Translate *t)
setFlags(hasphysical); setFlags(hasphysical);
} }
void UniqueSpace::saveXml(ostream &s) const
{
s << "<space_unique";
saveBasicAttributes(s);
s << "/>\n";
}
const string JoinSpace::NAME = "join"; 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
@ -492,7 +441,7 @@ const string JoinSpace::NAME = "join";
/// \param t is the associated processor translator /// \param t is the associated processor translator
/// \param ind is the integer identifier /// \param ind is the integer identifier
JoinSpace::JoinSpace(AddrSpaceManager *m,const Translate *t,int4 ind) JoinSpace::JoinSpace(AddrSpaceManager *m,const Translate *t,int4 ind)
: AddrSpace(m,t,IPTR_JOIN,NAME,sizeof(uintm),1,ind,0,0) : AddrSpace(m,t,IPTR_JOIN,NAME,t->isBigEndian(),sizeof(uintm),1,ind,0,0,0)
{ {
// This is a virtual space // This is a virtual space
// setFlags(hasphysical); // setFlags(hasphysical);
@ -691,12 +640,6 @@ uintb JoinSpace::read(const string &s,int4 &size) const
return rec->getUnified().offset; return rec->getUnified().offset;
} }
void JoinSpace::saveXml(ostream &s) const
{
throw LowlevelError("Should never save join space to XML");
}
void JoinSpace::decode(Decoder &decoder) void JoinSpace::decode(Decoder &decoder)
{ {
@ -712,16 +655,6 @@ OverlaySpace::OverlaySpace(AddrSpaceManager *m,const Translate *t)
setFlags(overlay); setFlags(overlay);
} }
void OverlaySpace::saveXml(ostream &s) const
{
s << "<space_overlay";
a_v(s,"name",name);
a_v_i(s,"index",index);
a_v(s,"base",baseSpace->getName());
s << "/>\n";
}
void OverlaySpace::decode(Decoder &decoder) void OverlaySpace::decode(Decoder &decoder)
{ {

View file

@ -117,11 +117,11 @@ protected:
void calcScaleMask(void); ///< Calculate scale and mask void calcScaleMask(void); ///< Calculate scale and mask
void setFlags(uint4 fl); ///< Set a cached attribute void setFlags(uint4 fl); ///< Set a cached attribute
void clearFlags(uint4 fl); ///< Clear a cached attribute void clearFlags(uint4 fl); ///< Clear a cached attribute
void saveBasicAttributes(ostream &s) const; ///< Write the XML attributes of this space
void decodeBasicAttributes(Decoder &decoder); ///< Read attributes for \b this space from an open XML element void decodeBasicAttributes(Decoder &decoder); ///< Read attributes for \b this space from an open XML element
void truncateSpace(uint4 newsize); void truncateSpace(uint4 newsize);
public: public:
AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const string &nm,uint4 size,uint4 ws,int4 ind,uint4 fl,int4 dl); AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const string &nm,bool bigEnd,
uint4 size,uint4 ws,int4 ind,uint4 fl,int4 dl,int4 dead);
AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp); ///< For use with decode AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp); ///< For use with decode
virtual ~AddrSpace(void) {} ///< The address space destructor virtual ~AddrSpace(void) {} ///< The address space destructor
const string &getName(void) const; ///< Get the name const string &getName(void) const; ///< Get the name
@ -163,8 +163,7 @@ public:
virtual uintb decodeAttributes(Decoder &decoder,uint4 &size) const; ///< Recover an offset and size virtual uintb decodeAttributes(Decoder &decoder,uint4 &size) const; ///< Recover an offset and size
virtual void printRaw(ostream &s,uintb offset) const; ///< Write an address in this space to a stream virtual void printRaw(ostream &s,uintb offset) const; ///< Write an address in this space to a stream
virtual uintb read(const string &s,int4 &size) const; ///< Read in an address (and possible size) from a string virtual uintb read(const string &s,int4 &size) const; ///< Read in an address (and possible size) from a string
virtual void saveXml(ostream &s) const; ///< Write the details of this space as XML virtual void decode(Decoder &decoder); ///< Recover the details of this space from a stream
virtual void decode(Decoder &decoder); ///< Recover the details of this space from XML
static uintb addressToByte(uintb val,uint4 ws); ///< Scale from addressable units to byte units static uintb addressToByte(uintb val,uint4 ws); ///< Scale from addressable units to byte units
static uintb byteToAddress(uintb val,uint4 ws); ///< Scale from byte units to addressable units static uintb byteToAddress(uintb val,uint4 ws); ///< Scale from byte units to addressable units
@ -190,7 +189,6 @@ public:
ConstantSpace(AddrSpaceManager *m,const Translate *t); ///< Only constructor ConstantSpace(AddrSpaceManager *m,const Translate *t); ///< Only constructor
virtual int4 overlapJoin(uintb offset,int4 size,AddrSpace *pointSpace,uintb pointOff,int4 pointSkip) const; virtual int4 overlapJoin(uintb offset,int4 size,AddrSpace *pointSpace,uintb pointOff,int4 pointSkip) 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 decode(Decoder &decoder); virtual void decode(Decoder &decoder);
static const string NAME; ///< Reserved name for the address space static const string NAME; ///< Reserved name for the address space
static const int4 INDEX; ///< Reserved index for constant space static const int4 INDEX; ///< Reserved index for constant space
@ -202,7 +200,6 @@ public:
OtherSpace(AddrSpaceManager *m, const Translate *t, int4 ind); ///< Constructor OtherSpace(AddrSpaceManager *m, const Translate *t, int4 ind); ///< Constructor
OtherSpace(AddrSpaceManager *m, const Translate *t); ///< For use with decode OtherSpace(AddrSpaceManager *m, const Translate *t); ///< For use with decode
virtual void printRaw(ostream &s, uintb offset) const; virtual void printRaw(ostream &s, uintb offset) const;
virtual void saveXml(ostream &s) const;
static const string NAME; ///< Reserved name for the address space static const string NAME; ///< Reserved name for the address space
static const int4 INDEX; ///< Reserved index for the other space static const int4 INDEX; ///< Reserved index for the other space
}; };
@ -220,7 +217,6 @@ class UniqueSpace : public AddrSpace {
public: public:
UniqueSpace(AddrSpaceManager *m,const Translate *t,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 decode UniqueSpace(AddrSpaceManager *m,const Translate *t); ///< For use with decode
virtual void saveXml(ostream &s) const;
static const string NAME; ///< Reserved name for the unique space static const string NAME; ///< Reserved name for the unique space
static const uint4 SIZE; ///< Fixed size (in bytes) for unique space offsets static const uint4 SIZE; ///< Fixed size (in bytes) for unique space offsets
}; };
@ -243,7 +239,6 @@ public:
virtual uintb decodeAttributes(Decoder &decoder,uint4 &size) const; virtual uintb decodeAttributes(Decoder &decoder,uint4 &size) const;
virtual void printRaw(ostream &s,uintb offset) const; virtual void printRaw(ostream &s,uintb offset) const;
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 decode(Decoder &decoder); virtual void decode(Decoder &decoder);
static const string NAME; ///< Reserved name for the join space static const string NAME; ///< Reserved name for the join space
}; };
@ -261,7 +256,6 @@ class OverlaySpace : public AddrSpace {
public: public:
OverlaySpace(AddrSpaceManager *m,const Translate *t); ///< Constructor OverlaySpace(AddrSpaceManager *m,const Translate *t); ///< Constructor
virtual AddrSpace *getContain(void) const { return baseSpace; } virtual AddrSpace *getContain(void) const { return baseSpace; }
virtual void saveXml(ostream &s) const;
virtual void decode(Decoder &decoder); virtual void decode(Decoder &decoder);
}; };

View file

@ -56,7 +56,7 @@ void TruncationTag::decode(Decoder &decoder)
/// \param isFormal is the formal stack space indicator /// \param isFormal is the formal stack space indicator
SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz, SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz,
AddrSpace *base,int4 dl,bool isFormal) AddrSpace *base,int4 dl,bool isFormal)
: AddrSpace(m,t,IPTR_SPACEBASE,nm,sz,base->getWordSize(),ind,0,dl) : AddrSpace(m,t,IPTR_SPACEBASE,nm,t->isBigEndian(),sz,base->getWordSize(),ind,0,dl,dl)
{ {
contain = base; contain = base;
hasbaseregister = false; // No base register assigned yet hasbaseregister = false; // No base register assigned yet
@ -123,15 +123,6 @@ const VarnodeData &SpacebaseSpace::getSpacebaseFull(int4 i) const
return baseOrig; return baseOrig;
} }
void SpacebaseSpace::saveXml(ostream &s) const
{
s << "<space_base";
saveBasicAttributes(s);
a_v(s,"contain",contain->getName());
s << "/>\n";
}
void SpacebaseSpace::decode(Decoder &decoder) void SpacebaseSpace::decode(Decoder &decoder)
{ {

View file

@ -185,7 +185,6 @@ public:
virtual const VarnodeData &getSpacebaseFull(int4 i) const; virtual const VarnodeData &getSpacebaseFull(int4 i) const;
virtual bool stackGrowsNegative(void) const { return isNegativeStack; } virtual bool stackGrowsNegative(void) const { return isNegativeStack; }
virtual AddrSpace *getContain(void) const { return contain; } ///< Return containing space virtual AddrSpace *getContain(void) const { return contain; } ///< Return containing space
virtual void saveXml(ostream &s) const;
virtual void decode(Decoder &decoder); virtual void decode(Decoder &decoder);
}; };
@ -235,7 +234,7 @@ class AddrSpaceManager {
vector<JoinRecord *> splitlist; ///< JoinRecords indexed by join address vector<JoinRecord *> splitlist; ///< JoinRecords indexed by join address
protected: protected:
AddrSpace *decodeSpace(Decoder &decoder,const Translate *trans); ///< Add a space to the model based an on XML tag AddrSpace *decodeSpace(Decoder &decoder,const Translate *trans); ///< Add a space to the model based an on XML tag
void decodeSpaces(Decoder &decoder,const Translate *trans); ///< Restore address spaces in the model from an XML tag void decodeSpaces(Decoder &decoder,const Translate *trans); ///< Restore address spaces in the model from a stream
void setDefaultCodeSpace(int4 index); ///< Set the default address space (for code) void setDefaultCodeSpace(int4 index); ///< Set the default address space (for code)
void setDefaultDataSpace(int4 index); ///< Set the default address space for data void setDefaultDataSpace(int4 index); ///< Set the default address space for data
void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this space void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this space

View file

@ -598,8 +598,8 @@ const TypeField *Datatype::resolveTruncation(int8 offset,PcodeOp *op,int4 slot,i
return (const TypeField *)0; return (const TypeField *)0;
} }
/// Restore the basic properties (name,size,id) of a data-type from an XML element /// Restore the basic properties (name,size,id) of a data-type from a stream.
/// Properties are read from the attributes of the element /// Properties are read from the attributes of the element.
/// \param decoder is the stream decoder /// \param decoder is the stream decoder
void Datatype::decodeBasic(Decoder &decoder) void Datatype::decodeBasic(Decoder &decoder)

View file

@ -34,7 +34,7 @@ public:
static FuncProtoTestEnvironment theEnviron; static FuncProtoTestEnvironment theEnviron;
static Architecture *glb; static Architecture *glb = (Architecture *)0;
FuncProtoTestEnvironment::FuncProtoTestEnvironment(void) FuncProtoTestEnvironment::FuncProtoTestEnvironment(void)
@ -46,7 +46,11 @@ FuncProtoTestEnvironment::FuncProtoTestEnvironment(void)
void FuncProtoTestEnvironment::build(void) void FuncProtoTestEnvironment::build(void)
{ {
if (theEnviron.g != (Architecture *)0) return; if (theEnviron.g != (Architecture *)0) {
if (glb == (Architecture *)0)
throw LowlevelError("Architecture did not load");
return;
}
ArchitectureCapability *xmlCapability = ArchitectureCapability::getCapability("xml"); ArchitectureCapability *xmlCapability = ArchitectureCapability::getCapability("xml");
istringstream s( istringstream s(
"<binaryimage arch=\"Toy:LE:32:default:default\"></binaryimage>" "<binaryimage arch=\"Toy:LE:32:default:default\"></binaryimage>"

View file

@ -49,7 +49,7 @@ static MarshalTestEnvironment theEnviron;
TestAddrSpaceManager::TestAddrSpaceManager(Translate *t) TestAddrSpaceManager::TestAddrSpaceManager(Translate *t)
: AddrSpaceManager() : AddrSpaceManager()
{ {
insertSpace(new AddrSpace(this,t,IPTR_PROCESSOR,"ram",8,1,3,AddrSpace::hasphysical,1)); insertSpace(new AddrSpace(this,t,IPTR_PROCESSOR,"ram",t->isBigEndian(),8,1,3,AddrSpace::hasphysical,1,1));
} }
MarshalTestEnvironment::MarshalTestEnvironment(void) MarshalTestEnvironment::MarshalTestEnvironment(void)

View file

@ -0,0 +1,10 @@
The source files in this directory are copied from the zlib compression library, version 1.3.1
available from https://www.zlib.net/ .
The source files here are only a subset of the complete zlib library. The files have not been
changed except for the addition of a comment at the top of each file, noting its association
with the zlib license and the version number.
Within Ghidra, the zlib license is available (in both the source repository and distributions)
in licenses/zlib_License.txt. Additionally the license appears at the top of zlib.h in this
directory.

View file

@ -0,0 +1,168 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2011, 2016 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zutil.h"
#define BASE 65521U /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware --
try it both ways to see which is faster */
#ifdef NO_DIVIDE
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
(thank you to John Reiser for pointing this out) */
# define CHOP(a) \
do { \
unsigned long tmp = a >> 16; \
a &= 0xffffUL; \
a += (tmp << 4) - tmp; \
} while (0)
# define MOD28(a) \
do { \
CHOP(a); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD(a) \
do { \
CHOP(a); \
MOD28(a); \
} while (0)
# define MOD63(a) \
do { /* this assumes a is not negative */ \
z_off64_t tmp = a >> 32; \
a &= 0xffffffffL; \
a += (tmp << 8) - (tmp << 5) + tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD28(a) a %= BASE
# define MOD63(a) a %= BASE
#endif
/* ========================================================================= */
uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
unsigned long sum2;
unsigned n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD28(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
return adler32_z(adler, buf, len);
}
/* ========================================================================= */
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* for negative len, return invalid adler32 as a clue for debugging */
if (len2 < 0)
return 0xffffffffUL;
/* the derivation of this formula is left as an exercise for the reader */
MOD63(len2); /* assumes len2 >= 0 */
rem = (unsigned)len2;
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 >= BASE) sum1 -= BASE;
if (sum1 >= BASE) sum1 -= BASE;
if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
if (sum2 >= BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
return adler32_combine_(adler1, adler2, len2);
}
uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
return adler32_combine_(adler1, adler2, len2);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,381 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* deflate.h -- internal compression state
* Copyright (C) 1995-2024 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef DEFLATE_H
#define DEFLATE_H
#include "zutil.h"
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip encoding
should be left enabled. */
#ifndef NO_GZIP
# define GZIP
#endif
/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
the cost of a larger memory footprint */
/* #define LIT_MEM */
/* ===========================================================================
* Internal compression state.
*/
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define Buf_size 16
/* size of bit buffer in bi_buf */
#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
#ifdef GZIP
# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
#endif
#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
#define FINISH_STATE 666 /* stream complete */
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} FAR ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
const static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;
typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct internal_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */
ulg pending; /* nb of bytes in the pending buffer */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
gz_headerp gzhead; /* gzip header information to write */
ulg gzindex; /* where in extra, name, or comment */
Byte method; /* can only be DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Bytef *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Posf *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Posf *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to suppress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
#ifdef LIT_MEM
# define LIT_BUFS 5
ushf *d_buf; /* buffer for distances */
uchf *l_buf; /* buffer for literals/lengths */
#else
# define LIT_BUFS 4
uchf *sym_buf; /* buffer for distances and literals/lengths */
#endif
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt sym_next; /* running index in symbol buffer */
uInt sym_end; /* symbol table full when sym_next reaches this */
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
uInt matches; /* number of string matches in current block */
uInt insert; /* bytes at end of window left to insert */
#ifdef ZLIB_DEBUG
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
ulg high_water;
/* High water mark offset in window for initialized bytes -- bytes above
* this are set to zero in order to avoid memory check warnings when
* longest match routines access bytes past the input. This is then
* updated to the new high water mark.
*/
} FAR deflate_state;
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
#define WIN_INIT MAX_MATCH
/* Number of bytes after end of data in window to initialize in order to avoid
memory checker errors from longest match routines */
/* in trees.c */
void ZLIB_INTERNAL _tr_init(deflate_state *s);
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc);
void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
ulg stored_len, int last);
void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s);
void ZLIB_INTERNAL _tr_align(deflate_state *s);
void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
ulg stored_len, int last);
#define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
* must not have side effects. _dist_code[256] and _dist_code[257] are never
* used.
*/
#ifndef ZLIB_DEBUG
/* Inline versions of _tr_tally for speed: */
#if defined(GEN_TREES_H) || !defined(STDC)
extern uch ZLIB_INTERNAL _length_code[];
extern uch ZLIB_INTERNAL _dist_code[];
#else
extern const uch ZLIB_INTERNAL _length_code[];
extern const uch ZLIB_INTERNAL _dist_code[];
#endif
#ifdef LIT_MEM
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->d_buf[s->sym_next] = 0; \
s->l_buf[s->sym_next++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \
ush dist = (ush)(distance); \
s->d_buf[s->sym_next] = dist; \
s->l_buf[s->sym_next++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
#else
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->sym_buf[s->sym_next++] = 0; \
s->sym_buf[s->sym_next++] = 0; \
s->sym_buf[s->sym_next++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \
ush dist = (ush)(distance); \
s->sym_buf[s->sym_next++] = (uch)dist; \
s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
s->sym_buf[s->sym_next++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
#endif
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
flush = _tr_tally(s, distance, length)
#endif
#endif /* DEFLATE_H */

View file

@ -0,0 +1,218 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* gzguts.h -- zlib internal header definitions for gz* operations
* Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#ifdef _LARGEFILE64_SOURCE
# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE 1
# endif
# undef _FILE_OFFSET_BITS
# undef _TIME_BITS
#endif
#ifdef HAVE_HIDDEN
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
#endif
#include <stdio.h>
#include "zlib.h"
#ifdef STDC
# include <string.h>
# include <stdlib.h>
# include <limits.h>
#endif
#ifndef _POSIX_SOURCE
# define _POSIX_SOURCE
#endif
#include <fcntl.h>
#ifdef _WIN32
# include <stddef.h>
#endif
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
# include <io.h>
#endif
#if defined(_WIN32)
# define WIDECHAR
#endif
#ifdef WINAPI_FAMILY
# define open _open
# define read _read
# define write _write
# define close _close
#endif
#ifdef NO_DEFLATE /* for compatibility with old definition */
# define NO_GZCOMPRESS
#endif
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(__CYGWIN__)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#ifndef HAVE_VSNPRINTF
# ifdef MSDOS
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
but for now we just assume it doesn't. */
# define NO_vsnprintf
# endif
# ifdef __TURBOC__
# define NO_vsnprintf
# endif
# ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
# define vsnprintf _vsnprintf
# endif
# endif
# endif
# ifdef __SASC
# define NO_vsnprintf
# endif
# ifdef VMS
# define NO_vsnprintf
# endif
# ifdef __OS400__
# define NO_vsnprintf
# endif
# ifdef __MVS__
# define NO_vsnprintf
# endif
#endif
/* unlike snprintf (which is required in C99), _snprintf does not guarantee
null termination of the result -- however this is only used in gzlib.c where
the result is assured to fit in the space provided */
#if defined(_MSC_VER) && _MSC_VER < 1900
# define snprintf _snprintf
#endif
#ifndef local
# define local static
#endif
/* since "static" is used to mean two completely different things in C, we
define "local" for the non-static meaning of "static", for readability
(compile with -Dlocal if your debugger can't find static symbols) */
/* gz* functions always use library allocation functions */
#ifndef STDC
extern voidp malloc(uInt size);
extern void free(voidpf ptr);
#endif
/* get errno and strerror definition */
#if defined UNDER_CE
# include <windows.h>
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
#else
# ifndef NO_STRERROR
# include <errno.h>
# define zstrerror() strerror(errno)
# else
# define zstrerror() "stdio error (consult errno)"
# endif
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
#endif
/* default memLevel */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default i/o buffer size -- double this for output when reading (this and
twice this must be able to fit in an unsigned type) */
#define GZBUFSIZE 8192
/* gzip modes, also provide a little integrity check on the passed structure */
#define GZ_NONE 0
#define GZ_READ 7247
#define GZ_WRITE 31153
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
/* values for gz_state how */
#define LOOK 0 /* look for a gzip header */
#define COPY 1 /* copy input directly */
#define GZIP 2 /* decompress a gzip stream */
/* internal gzip file state data structure */
typedef struct {
/* exposed contents for gzgetc() macro */
struct gzFile_s x; /* "x" for exposed */
/* x.have: number of bytes available at x.next */
/* x.next: next output data to deliver or write */
/* x.pos: current position in uncompressed data */
/* used for both reading and writing */
int mode; /* see gzip modes above */
int fd; /* file descriptor */
char *path; /* path or fd for error messages */
unsigned size; /* buffer size, zero if not allocated yet */
unsigned want; /* requested buffer size, default is GZBUFSIZE */
unsigned char *in; /* input buffer (double-sized when writing) */
unsigned char *out; /* output buffer (double-sized when reading) */
int direct; /* 0 if processing gzip, 1 if transparent */
/* just for reading */
int how; /* 0: get header, 1: copy, 2: decompress */
z_off64_t start; /* where the gzip data started, for rewinding */
int eof; /* true if end of input file reached */
int past; /* true if read requested past end */
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
int reset; /* true if a reset is pending after a Z_FINISH */
/* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */
/* error information */
int err; /* error code */
char *msg; /* error message */
/* zlib inflate or deflate stream */
z_stream strm; /* stream structure in-place (not a pointer) */
} gz_state;
typedef gz_state FAR *gz_statep;
/* shared functions */
void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
#if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
#endif
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
unsigned ZLIB_INTERNAL gz_intmax(void);
#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())

View file

@ -0,0 +1,324 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* inffast.c -- fast decoding
* Copyright (C) 1995-2017 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#ifdef ASMINF
# pragma message("Assembler code may have bugs -- use at your own risk")
#else
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
struct inflate_state FAR *state;
z_const unsigned char FAR *in; /* local strm->next_in */
z_const unsigned char FAR *last; /* have enough input while in < last */
unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned wnext; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */
code const FAR *lcode; /* local strm->lencode */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
code const *here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
unsigned char FAR *from; /* where to copy match from */
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
in = strm->next_in;
last = in + (strm->avail_in - 5);
out = strm->next_out;
beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
wsize = state->wsize;
whave = state->whave;
wnext = state->wnext;
window = state->window;
hold = state->hold;
bits = state->bits;
lcode = state->lencode;
dcode = state->distcode;
lmask = (1U << state->lenbits) - 1;
dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
do {
if (bits < 15) {
hold += (unsigned long)(*in++) << bits;
bits += 8;
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
here = lcode + (hold & lmask);
dolen:
op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
op = (unsigned)(here->op);
if (op == 0) { /* literal */
Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", here->val));
*out++ = (unsigned char)(here->val);
}
else if (op & 16) { /* length base */
len = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
len += (unsigned)hold & ((1U << op) - 1);
hold >>= op;
bits -= op;
}
Tracevv((stderr, "inflate: length %u\n", len));
if (bits < 15) {
hold += (unsigned long)(*in++) << bits;
bits += 8;
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
here = dcode + (hold & dmask);
dodist:
op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
op = (unsigned)(here->op);
if (op & 16) { /* distance base */
dist = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(*in++) << bits;
bits += 8;
if (bits < op) {
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
}
dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
hold >>= op;
bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist));
op = (unsigned)(out - beg); /* max distance in output */
if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state->sane) {
strm->msg =
(char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
if (len <= op - whave) {
do {
*out++ = 0;
} while (--len);
continue;
}
len -= op - whave;
do {
*out++ = 0;
} while (--op > whave);
if (op == 0) {
from = out - dist;
do {
*out++ = *from++;
} while (--len);
continue;
}
#endif
}
from = window;
if (wnext == 0) { /* very common case */
from += wsize - op;
if (op < len) { /* some from window */
len -= op;
do {
*out++ = *from++;
} while (--op);
from = out - dist; /* rest from output */
}
}
else if (wnext < op) { /* wrap around window */
from += wsize + wnext - op;
op -= wnext;
if (op < len) { /* some from end of window */
len -= op;
do {
*out++ = *from++;
} while (--op);
from = window;
if (wnext < len) { /* some from start of window */
op = wnext;
len -= op;
do {
*out++ = *from++;
} while (--op);
from = out - dist; /* rest from output */
}
}
}
else { /* contiguous in window */
from += wnext - op;
if (op < len) { /* some from window */
len -= op;
do {
*out++ = *from++;
} while (--op);
from = out - dist; /* rest from output */
}
}
while (len > 2) {
*out++ = *from++;
*out++ = *from++;
*out++ = *from++;
len -= 3;
}
if (len) {
*out++ = *from++;
if (len > 1)
*out++ = *from++;
}
}
else {
from = out - dist; /* copy direct from output */
do { /* minimum length is three */
*out++ = *from++;
*out++ = *from++;
*out++ = *from++;
len -= 3;
} while (len > 2);
if (len) {
*out++ = *from++;
if (len > 1)
*out++ = *from++;
}
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
here = dcode + here->val + (hold & ((1U << op) - 1));
goto dodist;
}
else {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
here = lcode + here->val + (hold & ((1U << op) - 1));
goto dolen;
}
else if (op & 32) { /* end-of-block */
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
else {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
} while (in < last && out < end);
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3;
in -= len;
bits -= len << 3;
hold &= (1U << bits) - 1;
/* update state and return */
strm->next_in = in;
strm->next_out = out;
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
strm->avail_out = (unsigned)(out < end ?
257 + (end - out) : 257 - (out - end));
state->hold = hold;
state->bits = bits;
return;
}
/*
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
- Using bit fields for code structure
- Different op definition to avoid & for extra bits (do & for table bits)
- Three separate decoding do-loops for direct, window, and wnext == 0
- Special case for distance > 1 copies to do overlapped load and store copy
- Explicit branch predictions (based on measured branch probabilities)
- Deferring match copy and interspersed it with decoding subsequent codes
- Swapping literal/length else
- Swapping window/direct else
- Larger unrolled copy loops (three is about right)
- Moving len -= 3 statement into middle of loop
*/
#endif /* !ASMINF */

View file

@ -0,0 +1,15 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2003, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);

View file

@ -0,0 +1,98 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by makefixed().
*/
/* WARNING: this file should *not* be used by applications.
It is part of the implementation of this library and is
subject to change. Applications should only use zlib.h.
*/
static const code lenfix[512] = {
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
{0,9,255}
};
static const code distfix[32] = {
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
{22,5,193},{64,5,0}
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,130 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip decoding
should be left enabled. */
#ifndef NO_GZIP
# define GUNZIP
#endif
/* Possible inflate modes between inflate() calls */
typedef enum {
HEAD = 16180, /* i: waiting for magic header */
FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */
EXLEN, /* i: waiting for extra length (gzip) */
EXTRA, /* i: waiting for extra bytes (gzip) */
NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */
DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */
COPY_, /* i/o: same as COPY below, but only first time in */
COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN_, /* i: same as LEN below, but only first time in */
LEN, /* i: waiting for length/lit/eob code */
LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */
MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */
LENGTH, /* i: waiting for 32-bit length (gzip) */
DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */
SYNC /* looking for synchronization bytes to restart inflate() */
} inflate_mode;
/*
State transitions between above modes -
(most modes can go to BAD or MEM on error -- not shown for clarity)
Process header:
HEAD -> (gzip) or (zlib) or (raw)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
HCRC -> TYPE
(zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE
(raw) -> TYPEDO
Read deflate blocks:
TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
STORED -> COPY_ -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN_
LEN_ -> LEN
Read deflate codes in fixed or dynamic block:
LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN
Process trailer:
CHECK -> LENGTH -> DONE
*/
/* State maintained between inflate() calls -- approximately 7K bytes, not
including the allocated sliding window, which is up to 32K bytes. */
struct inflate_state {
z_streamp strm; /* pointer back to this zlib stream */
inflate_mode mode; /* current inflate mode */
int last; /* true if processing last block */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
bit 2 true to validate check value */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags, 0 if zlib, or
-1 if raw or no header yet */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
gz_headerp head; /* where to save gzip header information */
/* sliding window */
unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned wnext; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if needed */
/* bit accumulator */
unsigned long hold; /* input bit accumulator */
unsigned bits; /* number of bits in "in" */
/* for string and stored block copying */
unsigned length; /* literal or length of data to copy */
unsigned offset; /* distance back to copy string from */
/* for table and code decoding */
unsigned extra; /* extra bits needed */
/* fixed and dynamic code tables */
code const FAR *lencode; /* starting table for length/literal codes */
code const FAR *distcode; /* starting table for distance codes */
unsigned lenbits; /* index bits for lencode */
unsigned distbits; /* index bits for distcode */
/* dynamic table building */
unsigned ncode; /* number of code length code lengths */
unsigned nlen; /* number of length code lengths */
unsigned ndist; /* number of distance code lengths */
unsigned have; /* number of code lengths in lens[] */
code FAR *next; /* next available space in codes[] */
unsigned short lens[320]; /* temporary storage for code lengths */
unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */
int sane; /* if false, allow invalid distance too far */
int back; /* bits back of last unprocessed length/lit */
unsigned was; /* initial length of match */
};

View file

@ -0,0 +1,303 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
/*
Build a set of tables to decode the provided canonical Huffman code.
The code lengths are lens[0..codes-1]. The result starts at *table,
whose indices are 0..2^bits-1. work is a writable array of at least
lens shorts, which is used as a work area. type is the type of code
to be generated, CODES, LENS, or DISTS. On return, zero is success,
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
on return points to the next available entry's address. bits is the
requested root table index bits, and on return it is the actual root
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work) {
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
unsigned root; /* number of index bits for root table */
unsigned curr; /* number of index bits for current table */
unsigned drop; /* code bits to drop for sub-table */
int left; /* number of prefix codes available */
unsigned used; /* code entries in table used */
unsigned huff; /* Huffman code */
unsigned incr; /* for incrementing code, index */
unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */
code here; /* table entry for duplication */
code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */
unsigned match; /* use base and extra for symbol >= match */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0};
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64};
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++)
count[len] = 0;
for (sym = 0; sym < codes; sym++)
count[lens[sym]]++;
/* bound code lengths, force root to be within code lengths */
root = *bits;
for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break;
if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)1;
here.val = (unsigned short)0;
*(*table)++ = here; /* make a table to force an error */
*(*table)++ = here;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min < max; min++)
if (count[min] != 0) break;
if (root < min) root = min;
/* check for an over-subscribed or incomplete set of lengths */
left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= count[len];
if (left < 0) return -1; /* over-subscribed */
}
if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + count[len];
/* sort symbols by length, by symbol order within each length */
for (sym = 0; sym < codes; sym++)
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/*
Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr,
those top drop + curr - len bits are incremented through all values to
fill the table with replicated entries.
root is the number of index bits for the root table. When len exceeds
root, sub-tables are created pointed to by the root entry with an index
of the low root bits of huff. This is saved in low to check for when a
new sub-table should be started. drop is zero when the root table is
being filled, and drop is root when sub-tables are being filled.
When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length
counts are used for this, and so count[] is decremented as codes are
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked for LENS and DIST tables against
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the initial root table size constants. See the comments in inftrees.h
for more information.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers.
*/
/* set up for code type */
switch (type) {
case CODES:
base = extra = work; /* dummy value--not used */
match = 20;
break;
case LENS:
base = lbase;
extra = lext;
match = 257;
break;
default: /* DISTS */
base = dbase;
extra = dext;
match = 0;
}
/* initialize state for loop */
huff = 0; /* starting code */
sym = 0; /* starting code symbol */
len = min; /* starting code length */
next = *table; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = (unsigned)(-1); /* trigger new sub-table when len > root */
used = 1U << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
/* check available table space */
if ((type == LENS && used > ENOUGH_LENS) ||
(type == DISTS && used > ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
for (;;) {
/* create table entry */
here.bits = (unsigned char)(len - drop);
if (work[sym] + 1U < match) {
here.op = (unsigned char)0;
here.val = work[sym];
}
else if (work[sym] >= match) {
here.op = (unsigned char)(extra[work[sym] - match]);
here.val = base[work[sym] - match];
}
else {
here.op = (unsigned char)(32 + 64); /* end of block */
here.val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = here;
} while (fill != 0);
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* go to next symbol, update count, len */
sym++;
if (--(count[len]) == 0) {
if (len == max) break;
len = lens[work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) != low) {
/* if first time, transition to sub-tables */
if (drop == 0)
drop = root;
/* increment past last table */
next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
left = (int)(1 << curr);
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) break;
curr++;
left <<= 1;
}
/* check for enough space */
used += 1U << curr;
if ((type == LENS && used > ENOUGH_LENS) ||
(type == DISTS && used > ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */
low = huff & mask;
(*table)[low].op = (unsigned char)curr;
(*table)[low].bits = (unsigned char)root;
(*table)[low].val = (unsigned short)(next - *table);
}
}
/* fill in remaining table entry if code is incomplete (guaranteed to have
at most one remaining entry, since if the code is incomplete, the
maximum code length that was allowed to get this far is one bit) */
if (huff != 0) {
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)(len - drop);
here.val = (unsigned short)0;
next[huff] = here;
}
/* set return parameters */
*table += used;
*bits = root;
return 0;
}

View file

@ -0,0 +1,66 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Structure for decoding tables. Each entry provides either the
information needed to do the operation requested by the code that
indexed that table entry, or it provides a pointer to another
table that indexes more bits of the code. op indicates whether
the entry is a pointer to another table, a literal, a length or
distance, an end-of-block, or an invalid code. For a table
pointer, the low four bits of op is the number of index bits of
that table. For a length or distance, the low four bits of op
is the number of extra bits to get after the code. bits is
the number of bits in this code or part of the code to drop off
of the bit buffer. val is the actual byte to output in the case
of a literal, the base length or distance, or the offset from
the current table to the next table. Each entry is four bytes. */
typedef struct {
unsigned char op; /* operation, extra bits, table bits */
unsigned char bits; /* bits in this part of the code */
unsigned short val; /* offset in table or code value */
} code;
/* op values as set by inflate_table():
00000000 - literal
0000tttt - table link, tttt != 0 is the number of table index bits
0001eeee - length or distance, eeee is the number of extra bits
01100000 - end of block
01000000 - invalid code
*/
/* Maximum size of the dynamic table. The maximum number of code structures is
1444, which is the sum of 852 for literal/length codes and 592 for distance
codes. These values were found by exhaustive searches using the program
examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns 852, and "enough 30 6 15" for distance codes returns 592. The
initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 592
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
/* Type of code to build for inflate_table() */
typedef enum {
CODES,
LENS,
DISTS
} codetype;
int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,132 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* header created automatically with -DGEN_TREES_H */
local const ct_data static_ltree[L_CODES+2] = {
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
};
local const ct_data static_dtree[D_CODES] = {
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
};
const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
local const int base_length[LENGTH_CODES] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};
local const int base_dist[D_CODES] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};

View file

@ -0,0 +1,547 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
* Even better than compiling with -DZ_PREFIX would be to use configure to set
* this permanently in zconf.h using "./configure --zprefix".
*/
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
# define Z_PREFIX_SET
/* all linked symbols and init macros */
# define _dist_code z__dist_code
# define _length_code z__length_code
# define _tr_align z__tr_align
# define _tr_flush_bits z__tr_flush_bits
# define _tr_flush_block z__tr_flush_block
# define _tr_init z__tr_init
# define _tr_stored_block z__tr_stored_block
# define _tr_tally z__tr_tally
# define adler32 z_adler32
# define adler32_combine z_adler32_combine
# define adler32_combine64 z_adler32_combine64
# define adler32_z z_adler32_z
# ifndef Z_SOLO
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# endif
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
# define crc32_combine_gen z_crc32_combine_gen
# define crc32_combine_gen64 z_crc32_combine_gen64
# define crc32_combine_op z_crc32_combine_op
# define crc32_z z_crc32_z
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateGetDictionary z_deflateGetDictionary
# define deflateInit z_deflateInit
# define deflateInit2 z_deflateInit2
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePending z_deflatePending
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateResetKeep z_deflateResetKeep
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table
# ifndef Z_SOLO
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzfread z_gzfread
# define gzfwrite z_gzfwrite
# define gzgetc z_gzgetc
# define gzgetc_ z_gzgetc_
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# ifdef _WIN32
# define gzopen_w z_gzopen_w
# endif
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzvprintf z_gzvprintf
# define gzwrite z_gzwrite
# endif
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define inflateBackInit z_inflateBackInit
# define inflateBackInit_ z_inflateBackInit_
# define inflateCodesUsed z_inflateCodesUsed
# define inflateCopy z_inflateCopy
# define inflateEnd z_inflateEnd
# define inflateGetDictionary z_inflateGetDictionary
# define inflateGetHeader z_inflateGetHeader
# define inflateInit z_inflateInit
# define inflateInit2 z_inflateInit2
# define inflateInit2_ z_inflateInit2_
# define inflateInit_ z_inflateInit_
# define inflateMark z_inflateMark
# define inflatePrime z_inflatePrime
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateResetKeep z_inflateResetKeep
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflateValidate z_inflateValidate
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# ifndef Z_SOLO
# define uncompress z_uncompress
# define uncompress2 z_uncompress2
# endif
# define zError z_zError
# ifndef Z_SOLO
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# endif
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
/* all zlib typedefs in zlib.h and zconf.h */
# define Byte z_Byte
# define Bytef z_Bytef
# define alloc_func z_alloc_func
# define charf z_charf
# define free_func z_free_func
# ifndef Z_SOLO
# define gzFile z_gzFile
# endif
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
# define intf z_intf
# define out_func z_out_func
# define uInt z_uInt
# define uIntf z_uIntf
# define uLong z_uLong
# define uLongf z_uLongf
# define voidp z_voidp
# define voidpc z_voidpc
# define voidpf z_voidpf
/* all zlib structs in zlib.h and zconf.h */
# define gz_header_s z_gz_header_s
# define internal_state z_internal_state
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
#if defined(ZLIB_CONST) && !defined(z_const)
# define z_const const
#else
# define z_const
#endif
#ifdef Z_SOLO
# ifdef _WIN64
typedef unsigned long long z_size_t;
# else
typedef unsigned long z_size_t;
# endif
#else
# define z_longlong long long
# if defined(NO_SIZE_T)
typedef unsigned NO_SIZE_T z_size_t;
# elif defined(STDC)
# include <stddef.h>
typedef size_t z_size_t;
# else
typedef unsigned long z_size_t;
# endif
# undef z_longlong
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
# include <limits.h>
# if (UINT_MAX == 0xffffffffUL)
# define Z_U4 unsigned
# elif (ULONG_MAX == 0xffffffffUL)
# define Z_U4 unsigned long
# elif (USHRT_MAX == 0xffffffffUL)
# define Z_U4 unsigned short
# endif
#endif
#ifdef Z_U4
typedef Z_U4 z_crc_t;
#else
typedef unsigned long z_crc_t;
#endif
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_STDARG_H
#endif
#ifdef STDC
# ifndef Z_SOLO
# include <sys/types.h> /* for off_t */
# endif
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
# include <stdarg.h> /* for va_list */
# endif
#endif
#ifdef _WIN32
# ifndef Z_SOLO
# include <stddef.h> /* for wchar_t */
# endif
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#ifndef Z_HAVE_UNISTD_H
# ifdef __WATCOMC__
# define Z_HAVE_UNISTD_H
# endif
#endif
#ifndef Z_HAVE_UNISTD_H
# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
# define Z_HAVE_UNISTD_H
# endif
#endif
#ifndef Z_SOLO
# if defined(Z_HAVE_UNISTD_H)
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
# endif
# endif
#endif
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
# define Z_LFS64
#endif
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
# define Z_LARGE64
#endif
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
# define Z_WANT64
#endif
#if !defined(SEEK_SET) && !defined(Z_SOLO)
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if !defined(_WIN32) && defined(Z_LARGE64)
# define z_off64_t off64_t
#else
# if defined(_WIN32) && !defined(__GNUC__)
# define z_off64_t __int64
# else
# define z_off64_t z_off_t
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
#pragma map(deflateInit_,"DEIN")
#pragma map(deflateInit2_,"DEIN2")
#pragma map(deflateEnd,"DEEND")
#pragma map(deflateBound,"DEBND")
#pragma map(inflateInit_,"ININ")
#pragma map(inflateInit2_,"ININ2")
#pragma map(inflateEnd,"INEND")
#pragma map(inflateSync,"INSY")
#pragma map(inflateSetDictionary,"INSEDI")
#pragma map(compressBound,"CMBND")
#pragma map(inflate_table,"INTABL")
#pragma map(inflate_fast,"INFA")
#pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,303 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2017 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zutil.h"
#ifndef Z_SOLO
# include "gzguts.h"
#endif
z_const char * const z_errmsg[10] = {
(z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
(z_const char *)"stream end", /* Z_STREAM_END 1 */
(z_const char *)"", /* Z_OK 0 */
(z_const char *)"file error", /* Z_ERRNO (-1) */
(z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
(z_const char *)"data error", /* Z_DATA_ERROR (-3) */
(z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
(z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
(z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
(z_const char *)""
};
const char * ZEXPORT zlibVersion(void) {
return ZLIB_VERSION;
}
uLong ZEXPORT zlibCompileFlags(void) {
uLong flags;
flags = 0;
switch ((int)(sizeof(uInt))) {
case 2: break;
case 4: flags += 1; break;
case 8: flags += 2; break;
default: flags += 3;
}
switch ((int)(sizeof(uLong))) {
case 2: break;
case 4: flags += 1 << 2; break;
case 8: flags += 2 << 2; break;
default: flags += 3 << 2;
}
switch ((int)(sizeof(voidpf))) {
case 2: break;
case 4: flags += 1 << 4; break;
case 8: flags += 2 << 4; break;
default: flags += 3 << 4;
}
switch ((int)(sizeof(z_off_t))) {
case 2: break;
case 4: flags += 1 << 6; break;
case 8: flags += 2 << 6; break;
default: flags += 3 << 6;
}
#ifdef ZLIB_DEBUG
flags += 1 << 8;
#endif
/*
#if defined(ASMV) || defined(ASMINF)
flags += 1 << 9;
#endif
*/
#ifdef ZLIB_WINAPI
flags += 1 << 10;
#endif
#ifdef BUILDFIXED
flags += 1 << 12;
#endif
#ifdef DYNAMIC_CRC_TABLE
flags += 1 << 13;
#endif
#ifdef NO_GZCOMPRESS
flags += 1L << 16;
#endif
#ifdef NO_GZIP
flags += 1L << 17;
#endif
#ifdef PKZIP_BUG_WORKAROUND
flags += 1L << 20;
#endif
#ifdef FASTEST
flags += 1L << 21;
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifdef NO_vsnprintf
flags += 1L << 25;
# ifdef HAS_vsprintf_void
flags += 1L << 26;
# endif
# else
# ifdef HAS_vsnprintf_void
flags += 1L << 26;
# endif
# endif
#else
flags += 1L << 24;
# ifdef NO_snprintf
flags += 1L << 25;
# ifdef HAS_sprintf_void
flags += 1L << 26;
# endif
# else
# ifdef HAS_snprintf_void
flags += 1L << 26;
# endif
# endif
#endif
return flags;
}
#ifdef ZLIB_DEBUG
#include <stdlib.h>
# ifndef verbose
# define verbose 0
# endif
int ZLIB_INTERNAL z_verbose = verbose;
void ZLIB_INTERNAL z_error(char *m) {
fprintf(stderr, "%s\n", m);
exit(1);
}
#endif
/* exported to allow conversion of error code to string for compress() and
* uncompress()
*/
const char * ZEXPORT zError(int err) {
return ERR_MSG(err);
}
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
/* The older Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used.
*/
int errno = 0;
#endif
#ifndef HAVE_MEMCPY
void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
if (len == 0) return;
do {
*dest++ = *source++; /* ??? to be unrolled */
} while (--len != 0);
}
int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
uInt j;
for (j = 0; j < len; j++) {
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
}
return 0;
}
void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
if (len == 0) return;
do {
*dest++ = 0; /* ??? to be unrolled */
} while (--len != 0);
}
#endif
#ifndef Z_SOLO
#ifdef SYS16BIT
#ifdef __TURBOC__
/* Turbo C in 16-bit mode */
# define MY_ZCALLOC
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
* and farmalloc(64K) returns a pointer with an offset of 8, so we
* must fix the pointer. Warning: the pointer must be put back to its
* original form in order to free it, use zcfree().
*/
#define MAX_PTR 10
/* 10*64K = 640K */
local int next_ptr = 0;
typedef struct ptr_table_s {
voidpf org_ptr;
voidpf new_ptr;
} ptr_table;
local ptr_table table[MAX_PTR];
/* This table is used to remember the original form of pointers
* to large buffers (64K). Such pointers are normalized with a zero offset.
* Since MSDOS is not a preemptive multitasking OS, this table is not
* protected from concurrent access. This hack doesn't work anyway on
* a protected system like OS/2. Use Microsoft C instead.
*/
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
voidpf buf;
ulg bsize = (ulg)items*size;
(void)opaque;
/* If we allocate less than 65520 bytes, we assume that farmalloc
* will return a usable pointer which doesn't have to be normalized.
*/
if (bsize < 65520L) {
buf = farmalloc(bsize);
if (*(ush*)&buf != 0) return buf;
} else {
buf = farmalloc(bsize + 16L);
}
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
table[next_ptr].org_ptr = buf;
/* Normalize the pointer to seg:0 */
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
*(ush*)&buf = 0;
table[next_ptr++].new_ptr = buf;
return buf;
}
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
int n;
(void)opaque;
if (*(ush*)&ptr != 0) { /* object < 64K */
farfree(ptr);
return;
}
/* Find the original pointer */
for (n = 0; n < next_ptr; n++) {
if (ptr != table[n].new_ptr) continue;
farfree(table[n].org_ptr);
while (++n < next_ptr) {
table[n-1] = table[n];
}
next_ptr--;
return;
}
Assert(0, "zcfree: ptr not found");
}
#endif /* __TURBOC__ */
#ifdef M_I86
/* Microsoft C in 16-bit mode */
# define MY_ZCALLOC
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
# define _halloc halloc
# define _hfree hfree
#endif
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
(void)opaque;
return _halloc((long)items, size);
}
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
(void)opaque;
_hfree(ptr);
}
#endif /* M_I86 */
#endif /* SYS16BIT */
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
#ifndef STDC
extern voidp malloc(uInt size);
extern voidp calloc(uInt items, uInt size);
extern void free(voidpf ptr);
#endif
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
(void)opaque;
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
(voidpf)calloc(items, size);
}
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
(void)opaque;
free(ptr);
}
#endif /* MY_ZCALLOC */
#endif /* !Z_SOLO */

View file

@ -0,0 +1,258 @@
/* ###
* IP: zlib License
* NOTE: from zlib 1.3.1
*/
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef ZUTIL_H
#define ZUTIL_H
#ifdef HAVE_HIDDEN
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
#endif
#include "zlib.h"
#if defined(STDC) && !defined(Z_SOLO)
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
# include <stddef.h>
# endif
# include <string.h>
# include <stdlib.h>
#endif
#ifndef local
# define local static
#endif
/* since "static" is used to mean two completely different things in C, we
define "local" for the non-static meaning of "static", for readability
(compile with -Dlocal if your debugger can't find static symbols) */
typedef unsigned char uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
# include <limits.h>
# if (ULONG_MAX == 0xffffffffffffffff)
# define Z_U8 unsigned long
# elif (ULLONG_MAX == 0xffffffffffffffff)
# define Z_U8 unsigned long long
# elif (UINT_MAX == 0xffffffffffffffff)
# define Z_U8 unsigned
# endif
#endif
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00
# ifndef Z_SOLO
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
# endif
#endif
#ifdef AMIGA
# define OS_CODE 1
#endif
#if defined(VAXC) || defined(VMS)
# define OS_CODE 2
# define F_OPEN(name, mode) \
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
#ifdef __370__
# if __TARGET_LIB__ < 0x20000000
# define OS_CODE 4
# elif __TARGET_LIB__ < 0x40000000
# define OS_CODE 11
# else
# define OS_CODE 8
# endif
#endif
#if defined(ATARI) || defined(atarist)
# define OS_CODE 5
#endif
#ifdef OS2
# define OS_CODE 6
# if defined(M_I86) && !defined(Z_SOLO)
# include <malloc.h>
# endif
#endif
#if defined(MACOS)
# define OS_CODE 7
#endif
#ifdef __acorn
# define OS_CODE 13
#endif
#if defined(WIN32) && !defined(__CYGWIN__)
# define OS_CODE 10
#endif
#ifdef _BEOS_
# define OS_CODE 16
#endif
#ifdef __TOS_OS400__
# define OS_CODE 18
#endif
#ifdef __APPLE__
# define OS_CODE 19
#endif
#if defined(__BORLANDC__) && !defined(MSDOS)
#pragma warn -8004
#pragma warn -8008
#pragma warn -8066
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_WIN32) && \
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
#endif
/* common defaults */
#ifndef OS_CODE
# define OS_CODE 3 /* assume Unix */
#endif
#ifndef F_OPEN
# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
#if defined(pyr) || defined(Z_SOLO)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
/* Use our own functions for small and medium model with MSC <= 5.0.
* You may have to use the same strategy for Borland C (untested).
* The __SC__ check is for Symantec.
*/
# define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
# define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
# define zmemcpy _fmemcpy
# define zmemcmp _fmemcmp
# define zmemzero(dest, len) _fmemset(dest, 0, len)
# else
# define zmemcpy memcpy
# define zmemcmp memcmp
# define zmemzero(dest, len) memset(dest, 0, len)
# endif
#else
void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len);
void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len);
#endif
/* Diagnostic functions */
#ifdef ZLIB_DEBUG
# include <stdio.h>
extern int ZLIB_INTERNAL z_verbose;
extern void ZLIB_INTERNAL z_error(char *m);
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
#ifndef Z_SOLO
voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items,
unsigned size);
void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr);
#endif
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
/* Reverse the bytes in a 32-bit value */
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
#endif /* ZUTIL_H */

View file

@ -84,10 +84,10 @@ public class DecompInterface {
public static class EncodeDecodeSet { public static class EncodeDecodeSet {
public OverlayAddressSpace overlay; // Active overlay space or null public OverlayAddressSpace overlay; // Active overlay space or null
public Encoder mainQuery; // Encoder for main query to decompiler process public CachedEncoder mainQuery; // Encoder for main query to decompiler process
public PackedDecode mainResponse; // Decoder for main response from the decompiler process public PackedDecode mainResponse; // Decoder for main response from the decompiler process
public PackedDecode callbackQuery; // Decoder for queries from the decompiler process public PackedDecode callbackQuery; // Decoder for queries from the decompiler process
public PackedEncode callbackResponse; // Encode for response to decompiler queries public PatchPackedEncode callbackResponse; // Encode for response to decompiler queries
/** /**
* Set up encoders and decoders for functions that are not in overlay address spaces * Set up encoders and decoders for functions that are not in overlay address spaces
@ -95,10 +95,10 @@ public class DecompInterface {
*/ */
public EncodeDecodeSet(Program program) { public EncodeDecodeSet(Program program) {
overlay = null; overlay = null;
mainQuery = new PackedEncode(); mainQuery = new PatchPackedEncode();
mainResponse = new PackedDecode(program.getAddressFactory()); mainResponse = new PackedDecode(program.getAddressFactory());
callbackQuery = new PackedDecode(program.getAddressFactory()); callbackQuery = new PackedDecode(program.getAddressFactory());
callbackResponse = new PackedEncode(); callbackResponse = new PatchPackedEncode();
} }
/** /**
@ -272,7 +272,7 @@ public class DecompInterface {
decompProcess = DecompileProcessFactory.get(); decompProcess = DecompileProcessFactory.get();
} }
long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage); long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage);
XmlEncode xmlEncode = new XmlEncode(); XmlEncode xmlEncode = new XmlEncode(false);
pcodelanguage.encodeTranslator(xmlEncode, program.getAddressFactory(), uniqueBase); pcodelanguage.encodeTranslator(xmlEncode, program.getAddressFactory(), uniqueBase);
String tspec = xmlEncode.toString(); String tspec = xmlEncode.toString();
xmlEncode.clear(); xmlEncode.clear();

View file

@ -208,7 +208,7 @@ public class DecompileCallback {
* @param addr is the given address * @param addr is the given address
* @param resultEncoder will contain the generated p-code ops * @param resultEncoder will contain the generated p-code ops
*/ */
public void getPcode(Address addr, PackedEncode resultEncoder) { public void getPcode(Address addr, PatchEncoder resultEncoder) {
try { try {
Instruction instr = getInstruction(addr); Instruction instr = getInstruction(addr);
if (instr == null) { if (instr == null) {

View file

@ -77,7 +77,7 @@ public class DecompileProcess {
private int maxResultSizeMBYtes = 50; // maximum result size in MBytes to allow from decompiler private int maxResultSizeMBYtes = 50; // maximum result size in MBytes to allow from decompiler
private PackedDecode paramDecoder; // Decoder to use for queries from the decompiler private PackedDecode paramDecoder; // Decoder to use for queries from the decompiler
private PackedEncode resultEncoder; // Encoder to use for query responses private PatchPackedEncode resultEncoder; // Encoder to use for query responses
private StringIngest stringDecoder; // Ingest of exception and status messages private StringIngest stringDecoder; // Ingest of exception and status messages
public enum DisposeState { public enum DisposeState {
@ -202,7 +202,7 @@ public class DecompileProcess {
private int readToBuffer(ByteIngest buf) throws IOException { private int readToBuffer(ByteIngest buf) throws IOException {
int cur; int cur;
for (;;) { for (;;) {
buf.ingestStream(nativeIn); buf.ingestStreamToNextTerminator(nativeIn);
do { do {
cur = nativeIn.read(); cur = nativeIn.read();
} }
@ -239,7 +239,7 @@ public class DecompileProcess {
write(string_end); write(string_end);
} }
private void writeString(Encoder byteResult) throws IOException { private void writeString(CachedEncoder byteResult) throws IOException {
if (nativeOut == null) { if (nativeOut == null) {
return; return;
} }
@ -426,7 +426,7 @@ public class DecompileProcess {
// Decompiler process may callback during the registerProgram operation // Decompiler process may callback during the registerProgram operation
// so provide query/reponse decoding/encoding // so provide query/reponse decoding/encoding
paramDecoder = new PackedDecode(program.getAddressFactory()); paramDecoder = new PackedDecode(program.getAddressFactory());
resultEncoder = new PackedEncode(); resultEncoder = new PatchPackedEncode();
StringIngest response = new StringIngest(); // Don't use stringDecoder StringIngest response = new StringIngest(); // Don't use stringDecoder
@ -605,8 +605,8 @@ public class DecompileProcess {
* @throws IOException for problems with the pipe to the decompiler process * @throws IOException for problems with the pipe to the decompiler process
* @throws DecompileException for problems executing the command * @throws DecompileException for problems executing the command
*/ */
public synchronized void sendCommand1Param(String command, Encoder param1, ByteIngest response) public synchronized void sendCommand1Param(String command, CachedEncoder param1,
throws IOException, DecompileException { ByteIngest response) throws IOException, DecompileException {
if (!statusGood) { if (!statusGood) {
throw new IOException(command + " called on bad process"); throw new IOException(command + " called on bad process");
} }

View file

@ -15,20 +15,19 @@
*/ */
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertNotNull;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
import org.antlr.runtime.RecognitionException; import org.antlr.runtime.RecognitionException;
import org.jdom.JDOMException;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher; import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.pcode.DecoderException;
import ghidra.util.Msg; import ghidra.util.Msg;
import resources.ResourceManager; import resources.ResourceManager;
@ -42,7 +41,7 @@ public class SleighLanguageHelper {
} }
public static SleighLanguage getMockBE64Language() public static SleighLanguage getMockBE64Language()
throws UnknownInstructionException, SAXException, IOException { throws DecoderException, UnknownInstructionException, SAXException, IOException {
ResourceFile cSpecFile = getResourceFile("mock.cpsec"); ResourceFile cSpecFile = getResourceFile("mock.cpsec");
CompilerSpecDescription cSpecDesc = CompilerSpecDescription cSpecDesc =
@ -59,7 +58,7 @@ public class SleighLanguageHelper {
assertEquals("Failed to compile mock.slaspec", 0, assertEquals("Failed to compile mock.slaspec", 0,
SleighCompileLauncher.runMain(new String[] { slaSpecFile.getAbsolutePath() })); SleighCompileLauncher.runMain(new String[] { slaSpecFile.getAbsolutePath() }));
} }
catch (JDOMException | IOException | RecognitionException e) { catch (IOException | RecognitionException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
slaFile = getResourceFile("mock.sla"); slaFile = getResourceFile("mock.sla");
@ -67,19 +66,15 @@ public class SleighLanguageHelper {
} }
SleighLanguageDescription langDesc = new SleighLanguageDescription( SleighLanguageDescription langDesc = new SleighLanguageDescription(
new LanguageID("Mock:BE:64:default"), new LanguageID("Mock:BE:64:default"), "Mock language (64-bit BE)",
"Mock language (64-bit BE)", Processor.findOrPossiblyCreateProcessor("Mock"), Endian.BIG, // endian
Processor.findOrPossiblyCreateProcessor("Mock"),
Endian.BIG, // endian
Endian.BIG, // instructionEndian Endian.BIG, // instructionEndian
64, 64, "default", // variant
"default", // variant
0, // major version 0, // major version
0, // minor version 0, // minor version
false, // deprecated false, // deprecated
new HashMap<>(), // truncatedSpaceMap new HashMap<>(), // truncatedSpaceMap
new ArrayList<>(List.of(cSpecDesc)), new ArrayList<>(List.of(cSpecDesc)), new HashMap<>() // externalNames
new HashMap<>() // externalNames
); );
langDesc.setDefsFile(lDefsFile); langDesc.setDefsFile(lDefsFile);
langDesc.setSpecFile(pSpecFile); langDesc.setSpecFile(pSpecFile);

View file

@ -19,21 +19,18 @@
*/ */
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import static ghidra.pcode.utils.SlaFormat.*;
import java.util.*; import java.util.*;
import ghidra.app.plugin.processors.sleigh.symbol.*; import ghidra.app.plugin.processors.sleigh.symbol.*;
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl; import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.app.plugin.processors.sleigh.template.HandleTpl; import ghidra.app.plugin.processors.sleigh.template.HandleTpl;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.Msg; import ghidra.program.model.pcode.Decoder;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* The primary sleigh concept representing a semantic action * The primary sleigh concept representing a semantic action
* taking operands (semantic values) as input * taking operands (semantic values) as input
* producing a semantic value as output * producing a semantic value as output
@ -313,65 +310,59 @@ public class Constructor implements Comparable<Constructor> {
return null; return null;
} }
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
throws UnknownInstructionException { int el = decoder.openElement(ELEM_CONSTRUCTOR);
XmlElement el = parser.start("constructor");
SymbolTable symtab = sleigh.getSymbolTable(); SymbolTable symtab = sleigh.getSymbolTable();
int myId = SpecXmlUtils.decodeInt(el.getAttribute("parent")); int myId = (int) decoder.readUnsignedInteger(ATTRIB_PARENT);
parent = (SubtableSymbol) symtab.findSymbol(myId); parent = (SubtableSymbol) symtab.findSymbol(myId);
firstwhitespace = SpecXmlUtils.decodeInt(el.getAttribute("first")); firstwhitespace = (int) decoder.readSignedInteger(ATTRIB_FIRST);
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("length")); minimumlength = (int) decoder.readSignedInteger(ATTRIB_LENGTH);
String sourceAndLine = el.getAttribute("line"); int srcLine = (int) decoder.readSignedInteger(ATTRIB_SOURCE);
String[] parts = sourceAndLine.split(":"); lineno = (int) decoder.readSignedInteger(ATTRIB_LINE);
if (parts.length != 2) { sourceFile = sleigh.getSourceFileIndexer().getFileName(srcLine);
Msg.error(this, "Bad line attribute in .sla file");
lineno = -1;
sourceFile = "UNKNOWN";
}
else {
lineno = Integer.parseInt(parts[1].trim());
sourceFile = sleigh.getSourceFileIndexer().getFileName(Integer.parseInt(parts[0].trim()));
}
ArrayList<Object> oplist = new ArrayList<>(); ArrayList<Object> oplist = new ArrayList<>();
ArrayList<Object> piecelist = new ArrayList<>(); ArrayList<Object> piecelist = new ArrayList<>();
ArrayList<Object> coplist = new ArrayList<>(); ArrayList<Object> coplist = new ArrayList<>();
XmlElement subel = parser.peek(); int subel = decoder.peekElement();
while (!subel.getName().equals("constructor")) { while (subel != 0) {
if (subel.getName().equals("oper")) { if (subel == ELEM_OPER.id()) {
myId = SpecXmlUtils.decodeInt(subel.getAttribute("id")); decoder.openElement();
myId = (int) decoder.readUnsignedInteger(ATTRIB_ID);
oplist.add(symtab.findSymbol(myId)); oplist.add(symtab.findSymbol(myId));
parser.discardSubTree(); decoder.closeElementSkipping(subel);
} }
else if (subel.getName().equals("print")) { else if (subel == ELEM_PRINT.id()) {
piecelist.add(subel.getAttribute("piece")); decoder.openElement();
parser.discardSubTree(); piecelist.add(decoder.readString(ATTRIB_PIECE));
decoder.closeElementSkipping(subel);
} }
else if (subel.getName().equals("opprint")) { else if (subel == ELEM_OPPRINT.id()) {
myId = SpecXmlUtils.decodeInt(subel.getAttribute("id")); decoder.openElement();
myId = (int) decoder.readSignedInteger(ATTRIB_ID);
String operstring = "\n"; String operstring = "\n";
char ind = (char) ('A' + myId); char ind = (char) ('A' + myId);
operstring += ind; operstring += ind;
piecelist.add(operstring); piecelist.add(operstring);
parser.discardSubTree(); decoder.closeElementSkipping(subel);
} }
else if (subel.getName().equals("context_op")) { else if (subel == ELEM_CONTEXT_OP.id()) {
ContextOp c_op = new ContextOp(); ContextOp c_op = new ContextOp();
c_op.restoreXml(parser, sleigh); c_op.decode(decoder, sleigh);
coplist.add(c_op); coplist.add(c_op);
} }
else if (subel.getName().equals("commit")) { else if (subel == ELEM_COMMIT.id()) {
ContextCommit c_op = new ContextCommit(); ContextCommit c_op = new ContextCommit();
c_op.restoreXml(parser, sleigh); c_op.decode(decoder, sleigh);
coplist.add(c_op); coplist.add(c_op);
} }
else { else {
ConstructTpl curtempl = new ConstructTpl(); ConstructTpl curtempl = new ConstructTpl();
int sectionid = curtempl.restoreXml(parser, sleigh.getAddressFactory()); int sectionid = curtempl.decode(decoder);
if (sectionid < 0) { if (sectionid < 0) {
if (templ != null) { if (templ != null) {
throw new UnknownInstructionException("Duplicate main template section"); throw new DecoderException("Duplicate main template section");
} }
templ = curtempl; templ = curtempl;
} }
@ -383,12 +374,12 @@ public class Constructor implements Comparable<Constructor> {
namedtempl.add(null); namedtempl.add(null);
} }
if (namedtempl.get(sectionid) != null) { if (namedtempl.get(sectionid) != null) {
throw new UnknownInstructionException("Duplicate named template section"); throw new DecoderException("Duplicate named template section");
} }
namedtempl.set(sectionid, curtempl); namedtempl.set(sectionid, curtempl);
} }
} }
subel = parser.peek(); subel = decoder.peekElement();
} }
operands = new OperandSymbol[oplist.size()]; operands = new OperandSymbol[oplist.size()];
separators = new String[operands.length + 1]; separators = new String[operands.length + 1];
@ -404,7 +395,7 @@ public class Constructor implements Comparable<Constructor> {
else { else {
flowthruindex = -1; flowthruindex = -1;
} }
parser.end(el); decoder.closeElement(el);
} }
/** /**
@ -432,10 +423,6 @@ public class Constructor implements Comparable<Constructor> {
return res; return res;
} }
/* ***************************** *
* Get these working as map keys *
* ***************************** */
@Override @Override
public int compareTo(Constructor that) { public int compareTo(Constructor that) {
int result; int result;

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,9 +16,11 @@
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
public interface ContextChange { public interface ContextChange {
void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException; void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException;
void restoreXml(XmlPullParser parser,SleighLanguage lang);
void decode(Decoder decoder, SleighLanguage lang) throws DecoderException;
} }

View file

@ -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,11 +15,12 @@
*/ */
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol; import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
public class ContextCommit implements ContextChange { public class ContextCommit implements ContextChange {
@ -32,6 +32,7 @@ public class ContextCommit implements ContextChange {
sym = null; sym = null;
} }
@Override
public void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException { public void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException {
walker.getParserContext().addCommit(walker.getState(), sym, num, mask); walker.getParserContext().addCommit(walker.getState(), sym, num, mask);
if (debug != null) { if (debug != null) {
@ -40,13 +41,14 @@ public class ContextCommit implements ContextChange {
} }
} }
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { @Override
XmlElement el = parser.start("commit"); public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
int id = SpecXmlUtils.decodeInt(el.getAttribute("id")); int el = decoder.openElement(ELEM_COMMIT);
int id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
sym = (TripleSymbol) lang.getSymbolTable().findSymbol(id); sym = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
num = SpecXmlUtils.decodeInt(el.getAttribute("num")); num = (int) decoder.readSignedInteger(ATTRIB_NUMBER);
mask = SpecXmlUtils.decodeInt(el.getAttribute("mask")); mask = (int) decoder.readUnsignedInteger(ATTRIB_MASK);
parser.end(el); decoder.closeElement(el);
} }
} }

View file

@ -19,16 +19,15 @@
*/ */
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression; import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
import ghidra.util.NumericUtilities; import ghidra.util.NumericUtilities;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* An operation on the context (bit-packed form) of an instruction * An operation on the context (bit-packed form) of an instruction
*/ */
public class ContextOp implements ContextChange { public class ContextOp implements ContextChange {
@ -51,13 +50,13 @@ public class ContextOp implements ContextChange {
} }
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start("context_op"); int el = decoder.openElement(ELEM_CONTEXT_OP);
num = SpecXmlUtils.decodeInt(el.getAttribute("i")); num = (int) decoder.readSignedInteger(ATTRIB_I);
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift")); shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
mask = SpecXmlUtils.decodeInt(el.getAttribute("mask")); mask = (int) decoder.readUnsignedInteger(ATTRIB_MASK);
patexp = PatternExpression.restoreExpression(parser, lang); patexp = PatternExpression.decodeExpression(decoder, lang);
parser.end(el); decoder.closeElement(el);
} }
public PatternExpression getPatternExpression() { public PatternExpression getPatternExpression() {

View file

@ -19,11 +19,9 @@
*/ */
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import java.util.ArrayList; import static ghidra.pcode.utils.SlaFormat.*;
import java.util.Arrays;
import java.util.Collections; import java.util.*;
import java.util.Comparator;
import java.util.List;
import ghidra.app.plugin.processors.sleigh.pattern.DisjointPattern; import ghidra.app.plugin.processors.sleigh.pattern.DisjointPattern;
import ghidra.app.plugin.processors.sleigh.pattern.PatternBlock; import ghidra.app.plugin.processors.sleigh.pattern.PatternBlock;
@ -31,13 +29,10 @@ import ghidra.app.plugin.processors.sleigh.symbol.SubtableSymbol;
import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.lang.UnknownInstructionException;
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.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* A node in the decision tree for resolving a Constructor in * A node in the decision tree for resolving a Constructor in
* a SubtableSymbol based on the InstructionContext * a SubtableSymbol based on the InstructionContext
*/ */
@ -224,33 +219,33 @@ public class DecisionNode {
// } // }
// } // }
public void restoreXml(XmlPullParser parser, DecisionNode par, SubtableSymbol sub) { public void decode(Decoder decoder, DecisionNode par, SubtableSymbol sub)
XmlElement el = parser.start("decision"); throws DecoderException {
// parent = par; int el = decoder.openElement(ELEM_DECISION);
// num = SpecXmlUtils.decodeInt(el.getAttributeValue("number"));
contextdecision = SpecXmlUtils.decodeBoolean(el.getAttribute("context")); contextdecision = decoder.readBool(ATTRIB_CONTEXT);
startbit = SpecXmlUtils.decodeInt(el.getAttribute("start")); startbit = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
bitsize = SpecXmlUtils.decodeInt(el.getAttribute("size")); bitsize = (int) decoder.readSignedInteger(ATTRIB_SIZE);
ArrayList<Object> patlist = new ArrayList<>(); ArrayList<Object> patlist = new ArrayList<>();
ArrayList<Object> conlist = new ArrayList<>(); ArrayList<Object> conlist = new ArrayList<>();
ArrayList<Object> childlist = new ArrayList<>(); ArrayList<Object> childlist = new ArrayList<>();
// num = 0; // num = 0;
XmlElement subel = parser.peek(); int subel = decoder.peekElement();
while (!subel.isEnd()) { while (subel != 0) {
if (subel.getName().equals("pair")) { if (subel == ELEM_PAIR.id()) {
XmlElement start = parser.start(); decoder.openElement();
int id = SpecXmlUtils.decodeInt(subel.getAttribute("id")); int id = (int) decoder.readSignedInteger(ATTRIB_ID);
conlist.add(sub.getConstructor(id)); conlist.add(sub.getConstructor(id));
patlist.add(DisjointPattern.restoreDisjoint(parser)); patlist.add(DisjointPattern.decodeDisjoint(decoder));
parser.end(start); decoder.closeElement(subel);
} }
else if (subel.getName().equals("decision")) { else if (subel == ELEM_DECISION.id()) {
DecisionNode subnode = new DecisionNode(); DecisionNode subnode = new DecisionNode();
subnode.restoreXml(parser, this, sub); subnode.decode(decoder, this, sub);
childlist.add(subnode); childlist.add(subnode);
} }
subel = parser.peek(); subel = decoder.peekElement();
} }
patternlist = new DisjointPattern[patlist.size()]; patternlist = new DisjointPattern[patlist.size()];
patlist.toArray(patternlist); patlist.toArray(patternlist);
@ -258,7 +253,7 @@ public class DecisionNode {
conlist.toArray(constructlist); conlist.toArray(constructlist);
children = new DecisionNode[childlist.size()]; children = new DecisionNode[childlist.size()];
childlist.toArray(children); childlist.toArray(children);
parser.end(el); decoder.closeElement(el);
unmodifiablePatternList = Collections.unmodifiableList(Arrays.asList(patternlist)); unmodifiablePatternList = Collections.unmodifiableList(Arrays.asList(patternlist));
unmodifiableConstructorList = Collections.unmodifiableList(Arrays.asList(constructlist)); unmodifiableConstructorList = Collections.unmodifiableList(Arrays.asList(constructlist));

View file

@ -15,8 +15,7 @@
*/ */
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import static ghidra.program.model.pcode.AttributeId.*; import static ghidra.pcode.utils.SlaFormat.*;
import static ghidra.program.model.pcode.ElementId.*;
import java.io.*; import java.io.*;
import java.math.BigInteger; import java.math.BigInteger;
@ -26,7 +25,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.antlr.runtime.RecognitionException; import org.antlr.runtime.RecognitionException;
import org.jdom.JDOMException;
import org.xml.sax.*; import org.xml.sax.*;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
@ -36,15 +34,14 @@ import ghidra.app.plugin.processors.sleigh.expression.ContextField;
import ghidra.app.plugin.processors.sleigh.expression.PatternValue; import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
import ghidra.app.plugin.processors.sleigh.symbol.*; import ghidra.app.plugin.processors.sleigh.symbol.*;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.pcodeCPort.sleighbase.SleighBase; import ghidra.pcode.utils.SlaFormat;
import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher; import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.DefaultProgramContext; import ghidra.program.model.listing.DefaultProgramContext;
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.ElementId; import ghidra.program.model.pcode.*;
import ghidra.program.model.pcode.Encoder;
import ghidra.program.model.util.ProcessorSymbolType; import ghidra.program.model.util.ProcessorSymbolType;
import ghidra.sleigh.grammar.SleighPreprocessor; import ghidra.sleigh.grammar.SleighPreprocessor;
import ghidra.sleigh.grammar.SourceFileIndexer; import ghidra.sleigh.grammar.SourceFileIndexer;
@ -57,15 +54,6 @@ import utilities.util.FileUtilities;
public class SleighLanguage implements Language { public class SleighLanguage implements Language {
/**
* SLA_FORMAT_VERSION will be incremented whenever the format of the .sla
* files change.
* <p>
* Version 3: January 2021: added source file information for each constructor. <br>
* Version 2: April 2019: Changed numbering of Overlay spaces.<br>
* Version 1: Initial version.<br>
*/
public static final int SLA_FORMAT_VERSION = SleighBase.SLA_FORMAT_VERSION;
private Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions; private Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions;
private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs; private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
private List<InjectPayloadSleigh> additionalInject = null; private List<InjectPayloadSleigh> additionalInject = null;
@ -112,7 +100,7 @@ public class SleighLanguage implements Language {
SortedMap<String, ManualEntry> manual = null; SortedMap<String, ManualEntry> manual = null;
SleighLanguage(SleighLanguageDescription description) SleighLanguage(SleighLanguageDescription description)
throws SAXException, IOException, UnknownInstructionException { throws DecoderException, SAXException, IOException {
initialize(description); initialize(description);
} }
@ -124,7 +112,7 @@ public class SleighLanguage implements Language {
} }
private void initialize(SleighLanguageDescription langDescription) private void initialize(SleighLanguageDescription langDescription)
throws SAXException, IOException, UnknownInstructionException { throws DecoderException, SAXException, IOException {
this.defaultSymbols = new ArrayList<>(); this.defaultSymbols = new ArrayList<>();
this.compilerSpecDescriptions = new LinkedHashMap<>(); this.compilerSpecDescriptions = new LinkedHashMap<>();
for (CompilerSpecDescription compilerSpecDescription : langDescription for (CompilerSpecDescription compilerSpecDescription : langDescription
@ -151,7 +139,8 @@ public class SleighLanguage implements Language {
} }
// Read in the sleigh specification // Read in the sleigh specification
readSpecification(slaFile); PackedDecode decoder = SlaFormat.buildDecoder(slaFile);
decode(decoder);
registerBuilder = new RegisterBuilder(); registerBuilder = new RegisterBuilder();
loadRegisters(registerBuilder); loadRegisters(registerBuilder);
@ -177,42 +166,12 @@ public class SleighLanguage implements Language {
} }
private boolean isSLAWrongVersion(ResourceFile slaFile) { private boolean isSLAWrongVersion(ResourceFile slaFile) {
XmlPullParser parser = null; try (InputStream stream = slaFile.getInputStream()) {
try { return !SlaFormat.isSlaFormat(stream);
parser = XmlPullParserFactory.create(slaFile, new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
// ignore
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void error(SAXParseException exception) throws SAXException {
throw exception;
}
}, false);
XmlElement e = parser.peek();
if (!"sleigh".equals(e.getName())) {
return true;
}
int version = SpecXmlUtils.decodeInt(e.getAttribute("version"));
return (version != SLA_FORMAT_VERSION);
} }
catch (SAXException | IOException e) { catch (Exception e) {
return true; return true;
} }
finally {
if (parser != null) {
parser.dispose();
}
}
} }
private boolean isSLAStale(ResourceFile slaFile) { private boolean isSLAStale(ResourceFile slaFile) {
@ -521,9 +480,6 @@ public class SleighLanguage implements Language {
" -- please check log messages for details"); " -- please check log messages for details");
} }
} }
catch (JDOMException e) {
throw new IOException("JDOMException error recompiling: " + e.getMessage());
}
catch (RecognitionException e) { catch (RecognitionException e) {
throw new IOException("RecognitionException error recompiling: " + e.getMessage()); throw new IOException("RecognitionException error recompiling: " + e.getMessage());
} }
@ -533,10 +489,10 @@ public class SleighLanguage implements Language {
try { try {
initialize(description); initialize(description);
} }
catch (SAXException e) { catch (DecoderException e) {
throw new IOException(e.getMessage()); throw new IOException(e.getMessage());
} }
catch (UnknownInstructionException e) { catch (SAXException e) {
throw new IOException(e.getMessage()); throw new IOException(e.getMessage());
} }
} }
@ -907,96 +863,104 @@ public class SleighLanguage implements Language {
} }
} }
private void readSpecification(final ResourceFile sleighfile) private void decode(Decoder decoder) throws DecoderException {
throws SAXException, IOException, UnknownInstructionException { int el = decoder.openElement(ELEM_SLEIGH);
ErrorHandler errHandler = new ErrorHandler() { int version = 0;
@Override uniqueBase = 0;
public void error(SAXParseException exception) throws SAXException { alignment = 1;
Msg.error(SleighLanguage.this, "Error parsing " + sleighfile, exception); uniqueAllocateMask = 0; // Default mask is 0
numSections = 0;
boolean isBigEndian = false;
int attrib = decoder.getNextAttributeId();
while (attrib != 0) {
if (attrib == ATTRIB_VERSION.id()) {
version = (int) decoder.readSignedInteger();
} }
else if (attrib == ATTRIB_BIGENDIAN.id()) {
@Override isBigEndian = decoder.readBool();
public void fatalError(SAXParseException exception) throws SAXException {
Msg.error(SleighLanguage.this, "Fatal error parsing " + sleighfile, exception);
} }
else if (attrib == ATTRIB_UNIQBASE.id()) {
@Override uniqueBase = decoder.readUnsignedInteger();
public void warning(SAXParseException exception) throws SAXException {
Msg.warn(SleighLanguage.this, "Warning parsing " + sleighfile, exception);
} }
}; else if (attrib == ATTRIB_ALIGN.id()) {
XmlPullParser parser = XmlPullParserFactory.create(sleighfile, errHandler, false); alignment = (int) decoder.readSignedInteger();
try { }
restoreXml(parser); else if (attrib == ATTRIB_UNIQMASK.id()) {
uniqueAllocateMask = (int) decoder.readUnsignedInteger();
}
else if (attrib == ATTRIB_NUMSECTIONS.id()) {
numSections = (int) decoder.readUnsignedInteger();
}
attrib = decoder.getNextAttributeId();
} }
finally { if (version != FORMAT_VERSION) {
parser.dispose();
}
}
private void restoreXml(XmlPullParser parser) throws UnknownInstructionException {
XmlElement el = parser.start("sleigh");
int version = SpecXmlUtils.decodeInt(el.getAttribute("version"));
if (version != SLA_FORMAT_VERSION) {
throw new SleighException(".sla file for " + getLanguageID() + " has the wrong format"); throw new SleighException(".sla file for " + getLanguageID() + " has the wrong format");
} }
String endianAttr = el.getAttribute("bigendian"); Endian slaEndian = isBigEndian ? Endian.BIG : Endian.LITTLE;
Endian slaEndian = SpecXmlUtils.decodeBoolean(endianAttr) ? Endian.BIG : Endian.LITTLE;
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 " + ldefEndian + throw new SleighException(".ldefs says " + getLanguageID() + " is " + ldefEndian +
" but .sla says " + slaEndian); " but .sla says " + slaEndian);
} }
uniqueBase = SpecXmlUtils.decodeLong(el.getAttribute("uniqbase"));
alignment = SpecXmlUtils.decodeInt(el.getAttribute("align"));
uniqueAllocateMask = 0; // Default mask is 0
String uniqmaskstr = el.getAttribute("uniqmask");
if (uniqmaskstr != null) {
uniqueAllocateMask = SpecXmlUtils.decodeInt(uniqmaskstr);
}
String numsecstr = el.getAttribute("numsections");
if (numsecstr != null) {
numSections = SpecXmlUtils.decodeInt(numsecstr);
}
indexer = new SourceFileIndexer(); indexer = new SourceFileIndexer();
indexer.restoreXml(parser); indexer.decode(decoder);
parseSpaces(parser); parseSpaces(decoder);
symtab = new SymbolTable(); symtab = new SymbolTable();
symtab.restoreXml(parser, this); symtab.decode(decoder, this);
root = root =
((SubtableSymbol) symtab.getGlobalScope().findSymbol("instruction")).getDecisionNode(); ((SubtableSymbol) symtab.getGlobalScope().findSymbol("instruction")).getDecisionNode();
parser.end(el); decoder.closeElement(el);
} }
private void parseSpaces(XmlPullParser parser) { private void parseSpaces(Decoder decoder) throws DecoderException {
Set<String> truncatedSpaceNames = description.getTruncatedSpaceNames(); Set<String> truncatedSpaceNames = description.getTruncatedSpaceNames();
int truncatedSpaceCnt = truncatedSpaceNames.size(); int truncatedSpaceCnt = truncatedSpaceNames.size();
XmlElement el = parser.start("spaces"); int el = decoder.openElement(ELEM_SPACES);
String defname = el.getAttribute("defaultspace"); String defname = decoder.readString(ATTRIB_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(SpaceNames.CONSTANT_SPACE_NAME, 64, AddressSpace constspc = new GenericAddressSpace(SpaceNames.CONSTANT_SPACE_NAME, 64,
AddressSpace.TYPE_CONSTANT, SpaceNames.CONSTANT_SPACE_INDEX); AddressSpace.TYPE_CONSTANT, SpaceNames.CONSTANT_SPACE_INDEX);
spacetable.put(SpaceNames.CONSTANT_SPACE_NAME, constspc); spacetable.put(SpaceNames.CONSTANT_SPACE_NAME, constspc);
default_space = null; default_space = null;
XmlElement subel = parser.peek(); int subel = decoder.peekElement();
if (subel.getName().equals("space_other")) { // tag must be present if (subel == ELEM_SPACE_OTHER.id()) { // tag must be present
parser.discardSubTree(); // We don't process it decoder.openElement();
decoder.closeElementSkipping(subel); // We don't process it
// Instead the ProgramAddressFactory maps in the static OTHER_SPACE automatically // Instead the ProgramAddressFactory maps in the static OTHER_SPACE automatically
} }
else { else {
throw new SleighException(".sla file missing required OTHER space tag"); throw new SleighException(".sla file missing required OTHER space tag");
} }
while ((subel = parser.softStart("space", "space_unique")) != null) { while (decoder.peekElement() != 0) {
String name = subel.getAttribute("name"); int wordsize = 1;
int index = SpecXmlUtils.decodeInt(subel.getAttribute("index")); String name = null;
String typename = subel.getName(); int index = 0;
int delay = SpecXmlUtils.decodeInt(subel.getAttribute("delay")); int delay = -1;
int size = SpecXmlUtils.decodeInt(subel.getAttribute("size")); int size = 0;
subel = decoder.openElement();
int type = AddressSpace.TYPE_UNKNOWN; int attrib = decoder.getNextAttributeId();
if (typename.equals("space")) { while (attrib != 0) {
if (attrib == ATTRIB_NAME.id()) {
name = decoder.readString();
}
else if (attrib == ATTRIB_INDEX.id()) {
index = (int) decoder.readSignedInteger();
}
else if (attrib == ATTRIB_DELAY.id()) {
delay = (int) decoder.readSignedInteger();
}
else if (attrib == ATTRIB_SIZE.id()) {
size = (int) decoder.readSignedInteger();
}
else if (attrib == ATTRIB_WORDSIZE.id()) {
wordsize = (int) decoder.readSignedInteger();
}
attrib = decoder.getNextAttributeId();
}
int type;
if (subel == ELEM_SPACE.id()) {
if (delay > 0) { if (delay > 0) {
type = AddressSpace.TYPE_RAM; type = AddressSpace.TYPE_RAM;
} }
@ -1004,19 +968,13 @@ public class SleighLanguage implements Language {
type = AddressSpace.TYPE_REGISTER; type = AddressSpace.TYPE_REGISTER;
} }
} }
else if (typename.equals("space_unique")) { else if (subel == ELEM_SPACE_UNIQUE.id()) {
type = AddressSpace.TYPE_UNIQUE; type = AddressSpace.TYPE_UNIQUE;
} }
if (type == AddressSpace.TYPE_UNKNOWN) { else {
throw new SleighException("Sleigh cannot match new space definition to old type"); throw new SleighException("Sleigh cannot match new space definition to old type");
} }
String wSizeString = subel.getAttribute("wordsize");
int wordsize = 1;
if (wSizeString != null) {
wordsize = SpecXmlUtils.decodeInt(wSizeString);
}
boolean truncateSpace = truncatedSpaceNames.contains(name); boolean truncateSpace = truncatedSpaceNames.contains(name);
if (truncateSpace && type != AddressSpace.TYPE_RAM) { if (truncateSpace && type != AddressSpace.TYPE_RAM) {
throw new SleighException("Non-ram space does not support truncation: " + name); throw new SleighException("Non-ram space does not support truncation: " + name);
@ -1048,7 +1006,7 @@ public class SleighLanguage implements Language {
spc = new GenericAddressSpace(name, 8 * size, wordsize, type, index); spc = new GenericAddressSpace(name, 8 * size, wordsize, type, index);
} }
spacetable.put(name, spc); spacetable.put(name, spc);
parser.end(subel); decoder.closeElement(subel);
} }
if (truncatedSpaceCnt > 0) { if (truncatedSpaceCnt > 0) {
throw new SleighException( throw new SleighException(
@ -1058,7 +1016,8 @@ public class SleighLanguage implements Language {
defaultDataSpace = default_space; defaultDataSpace = default_space;
defaultPointerWordSize = defaultDataSpace.getAddressableUnitSize(); defaultPointerWordSize = defaultDataSpace.getAddressableUnitSize();
buildAddressSpaceFactory(); buildAddressSpaceFactory();
parser.end(el); decoder.closeElement(el);
decoder.setAddressFactory(addressFactory);
} }
void buildAddressSpaceFactory() { void buildAddressSpaceFactory() {
@ -1454,11 +1413,16 @@ public class SleighLanguage implements Language {
throws IOException { throws IOException {
AddressSpace[] spclist = factory.getAllAddressSpaces(); AddressSpace[] spclist = factory.getAllAddressSpaces();
encoder.openElement(ELEM_SLEIGH); // WARNING
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian()); // ELEM_ and ATTRIB_ symbols in this method all come from the AttributeId and ElementId
encoder.writeUnsignedInteger(ATTRIB_UNIQBASE, uniqueOffset); // namespace, some of which conflict with other ELEM_ and ATTRIB_ symbols used in this file
encoder.openElement(ELEM_SPACES);
encoder.writeString(ATTRIB_DEFAULTSPACE, factory.getDefaultAddressSpace().getName()); encoder.openElement(ElementId.ELEM_SLEIGH);
encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
encoder.writeUnsignedInteger(AttributeId.ATTRIB_UNIQBASE, uniqueOffset);
encoder.openElement(ElementId.ELEM_SPACES);
encoder.writeString(AttributeId.ATTRIB_DEFAULTSPACE,
factory.getDefaultAddressSpace().getName());
ElementId tag; ElementId tag;
int delay; int delay;
@ -1467,31 +1431,31 @@ public class SleighLanguage implements Language {
for (AddressSpace element : spclist) { for (AddressSpace element : spclist) {
if ((element instanceof OverlayAddressSpace)) { if ((element instanceof OverlayAddressSpace)) {
OverlayAddressSpace ospace = (OverlayAddressSpace) element; OverlayAddressSpace ospace = (OverlayAddressSpace) element;
encoder.openElement(ELEM_SPACE_OVERLAY); encoder.openElement(ElementId.ELEM_SPACE_OVERLAY);
encoder.writeString(ATTRIB_NAME, ospace.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, ospace.getName());
encoder.writeSignedInteger(ATTRIB_INDEX, ospace.getUnique()); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, ospace.getUnique());
encoder.writeSpace(ATTRIB_BASE, ospace.getOverlayedSpace()); encoder.writeSpace(AttributeId.ATTRIB_BASE, ospace.getOverlayedSpace());
encoder.closeElement(ELEM_SPACE_OVERLAY); encoder.closeElement(ElementId.ELEM_SPACE_OVERLAY);
continue; continue;
} }
switch (element.getType()) { switch (element.getType()) {
case AddressSpace.TYPE_RAM: case AddressSpace.TYPE_RAM:
tag = ELEM_SPACE; tag = ElementId.ELEM_SPACE;
delay = 1; delay = 1;
physical = true; physical = true;
break; break;
case AddressSpace.TYPE_REGISTER: case AddressSpace.TYPE_REGISTER:
tag = ELEM_SPACE; tag = ElementId.ELEM_SPACE;
delay = 0; delay = 0;
physical = true; physical = true;
break; break;
case AddressSpace.TYPE_UNIQUE: case AddressSpace.TYPE_UNIQUE:
tag = ELEM_SPACE_UNIQUE; tag = ElementId.ELEM_SPACE_UNIQUE;
delay = 0; delay = 0;
physical = true; physical = true;
break; break;
case AddressSpace.TYPE_OTHER: case AddressSpace.TYPE_OTHER:
tag = ELEM_SPACE_OTHER; tag = ElementId.ELEM_SPACE_OTHER;
delay = 0; delay = 0;
physical = true; physical = true;
break; break;
@ -1499,8 +1463,8 @@ public class SleighLanguage implements Language {
continue; continue;
} }
encoder.openElement(tag); encoder.openElement(tag);
encoder.writeString(ATTRIB_NAME, element.getName()); encoder.writeString(AttributeId.ATTRIB_NAME, element.getName());
encoder.writeSignedInteger(ATTRIB_INDEX, element.getUnique()); encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, element.getUnique());
int size = element.getSize(); // Size in bits int size = element.getSize(); // Size in bits
if (element instanceof SegmentedAddressSpace) { if (element instanceof SegmentedAddressSpace) {
@ -1511,18 +1475,19 @@ public class SleighLanguage implements Language {
size = 64; size = 64;
} }
int bytesize = (size + 7) / 8; // Convert bits to bytes int bytesize = (size + 7) / 8; // Convert bits to bytes
encoder.writeSignedInteger(ATTRIB_SIZE, bytesize); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, bytesize);
if (element.getAddressableUnitSize() > 1) { if (element.getAddressableUnitSize() > 1) {
encoder.writeUnsignedInteger(ATTRIB_WORDSIZE, element.getAddressableUnitSize()); encoder.writeUnsignedInteger(AttributeId.ATTRIB_WORDSIZE,
element.getAddressableUnitSize());
} }
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian()); encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
encoder.writeSignedInteger(ATTRIB_DELAY, delay); encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, delay);
encoder.writeBool(ATTRIB_PHYSICAL, physical); encoder.writeBool(AttributeId.ATTRIB_PHYSICAL, physical);
encoder.closeElement(tag); encoder.closeElement(tag);
} }
encoder.closeElement(ELEM_SPACES); encoder.closeElement(ElementId.ELEM_SPACES);
SleighLanguageDescription sleighDescription = SleighLanguageDescription sleighDescription =
(SleighLanguageDescription) getLanguageDescription(); (SleighLanguageDescription) getLanguageDescription();
@ -1530,13 +1495,13 @@ public class SleighLanguage implements Language {
if (!truncatedSpaceNames.isEmpty()) { if (!truncatedSpaceNames.isEmpty()) {
for (String spaceName : truncatedSpaceNames) { for (String spaceName : truncatedSpaceNames) {
int sz = sleighDescription.getTruncatedSpaceSize(spaceName); int sz = sleighDescription.getTruncatedSpaceSize(spaceName);
encoder.openElement(ELEM_TRUNCATE_SPACE); encoder.openElement(ElementId.ELEM_TRUNCATE_SPACE);
encoder.writeString(ATTRIB_SPACE, spaceName); encoder.writeString(AttributeId.ATTRIB_SPACE, spaceName);
encoder.writeSignedInteger(ATTRIB_SIZE, sz); encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz);
encoder.closeElement(ELEM_TRUNCATE_SPACE); encoder.closeElement(ElementId.ELEM_TRUNCATE_SPACE);
} }
} }
encoder.closeElement(ELEM_SLEIGH); encoder.closeElement(ElementId.ELEM_SLEIGH);
} }
private void initParallelHelper() { private void initParallelHelper() {

View file

@ -27,6 +27,7 @@ import org.xml.sax.*;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.pcode.DecoderException;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
@ -137,18 +138,17 @@ public class SleighLanguageProvider implements LanguageProvider {
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e); "Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
throw e; throw e;
} }
catch (DecoderException e) {
Msg.showError(this, null, "Error",
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
throw new SleighException("Format violation in the .sla file", e);
}
catch (FileNotFoundException e) { catch (FileNotFoundException e) {
Msg.showError(this, null, "Error", Msg.showError(this, null, "Error",
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e); "Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
throw new SleighException( throw new SleighException(
"File not found - language probably did not compile properly", e); "File not found - language probably did not compile properly", e);
} }
catch (UnknownInstructionException e) {
Msg.showError(this, null, "Error",
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
throw new SleighException(
"Unknown instruction - language probably did not compile properly", e);
}
catch (SAXException e) { catch (SAXException e) {
Msg.showError(this, null, "Error", Msg.showError(this, null, "Error",
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e); "Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);

View file

@ -20,12 +20,10 @@
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* Base class for binary operators that combine PatternExpressions * Base class for binary operators that combine PatternExpressions
*/ */
public abstract class BinaryExpression extends PatternExpression { public abstract class BinaryExpression extends PatternExpression {
@ -69,10 +67,10 @@ public abstract class BinaryExpression extends PatternExpression {
} }
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start(); int el = decoder.openElement();
left = PatternExpression.restoreExpression(parser, lang); left = PatternExpression.decodeExpression(decoder, lang);
right = PatternExpression.restoreExpression(parser, lang); right = PatternExpression.decodeExpression(decoder, lang);
parser.end(el); decoder.closeElement(el);
} }
} }

View file

@ -19,19 +19,17 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* A constant value associated with an alwaysTrue pattern * A constant value associated with an alwaysTrue pattern
*/ */
public class ConstantValue extends PatternValue { public class ConstantValue extends PatternValue {
private long val; // The constant value private long val; // The constant value
@ -61,25 +59,16 @@ public class ConstantValue extends PatternValue {
val = b; val = b;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
*/
@Override @Override
public long minValue() { public long minValue() {
return val; return val;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
*/
@Override @Override
public long maxValue() { public long maxValue() {
return val; return val;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public long getValue(ParserWalker walker) throws MemoryAccessException { public long getValue(ParserWalker walker) throws MemoryAccessException {
return val; return val;
@ -89,14 +78,11 @@ public class ConstantValue extends PatternValue {
return val; return val;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start("intb"); int el = decoder.openElement(ELEM_INTB);
val = SpecXmlUtils.decodeLong(el.getAttribute("val")); val = decoder.readSignedInteger(ATTRIB_VAL);
parser.end(el); decoder.closeElement(el);
} }
@Override @Override

View file

@ -19,16 +19,15 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* Contiguous bits in the non-instruction part of the context interpreted * Contiguous bits in the non-instruction part of the context interpreted
* as an integer value * as an integer value
*/ */
@ -81,17 +80,11 @@ public class ContextField extends PatternValue {
return signbit; return signbit;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
*/
@Override @Override
public long minValue() { public long minValue() {
return 0; return 0;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
*/
@Override @Override
public long maxValue() { public long maxValue() {
long res = -1; long res = -1;
@ -100,39 +93,35 @@ public class ContextField extends PatternValue {
return ~res; return ~res;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.InstructionContext)
*/
@Override @Override
public long getValue(ParserWalker walker) throws MemoryAccessException { public long getValue(ParserWalker walker) throws MemoryAccessException {
long res = getContextBytes(walker); long res = getContextBytes(walker);
res >>= shift; res >>= shift;
if (signbit) if (signbit) {
res = TokenField.signExtend(res, endbit - startbit); res = TokenField.signExtend(res, endbit - startbit);
else }
else {
res = TokenField.zeroExtend(res, endbit - startbit); res = TokenField.zeroExtend(res, endbit - startbit);
}
return res; return res;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start("contextfield"); int el = decoder.openElement(ELEM_CONTEXTFIELD);
signbit = SpecXmlUtils.decodeBoolean(el.getAttribute("signbit")); signbit = decoder.readBool(ATTRIB_SIGNBIT);
startbit = SpecXmlUtils.decodeInt(el.getAttribute("startbit")); startbit = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
endbit = SpecXmlUtils.decodeInt(el.getAttribute("endbit")); endbit = (int) decoder.readSignedInteger(ATTRIB_ENDBIT);
startbyte = SpecXmlUtils.decodeInt(el.getAttribute("startbyte")); startbyte = (int) decoder.readSignedInteger(ATTRIB_STARTBYTE);
endbyte = SpecXmlUtils.decodeInt(el.getAttribute("endbyte")); endbyte = (int) decoder.readSignedInteger(ATTRIB_ENDBYTE);
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift")); shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
parser.end(el); decoder.closeElement(el);
} }
/** /**
* Build a long from the context bytes in pos * Build a long from the context bytes at the current point in the instruction parse
* @param pos * @param walker is the parsing state
* @return * @return the recover value
*/ */
private long getContextBytes(ParserWalker walker) { private long getContextBytes(ParserWalker walker) {
long res = 0; long res = 0;

View file

@ -19,15 +19,16 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* The integer offset of the address following the current instruction * The integer offset of the address following the current instruction
*/ */
public class EndInstructionValue extends PatternValue { public class EndInstructionValue extends PatternValue {
@ -43,37 +44,26 @@ public class EndInstructionValue extends PatternValue {
return obj instanceof EndInstructionValue; return obj instanceof EndInstructionValue;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
*/
@Override @Override
public long minValue() { public long minValue() {
return 0; return 0;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
*/
@Override @Override
public long maxValue() { public long maxValue() {
return 0; return 0;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public long getValue(ParserWalker walker) throws MemoryAccessException { public long getValue(ParserWalker walker) throws MemoryAccessException {
Address addr = walker.getNaddr(); Address addr = walker.getNaddr();
return addr.getAddressableWordOffset(); return addr.getAddressableWordOffset();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
parser.discardSubTree("end_exp"); int el = decoder.openElement(ELEM_END_EXP);
decoder.closeElement(el);
// Nothing to do // Nothing to do
} }

View file

@ -15,15 +15,16 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* The integer offset of the address following the current instruction * The integer offset of the address following the current instruction
*/ */
public class Next2InstructionValue extends PatternValue { public class Next2InstructionValue extends PatternValue {
@ -56,8 +57,9 @@ public class Next2InstructionValue extends PatternValue {
} }
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
parser.discardSubTree("next2_exp"); int el = decoder.openElement(ELEM_NEXT2_EXP);
decoder.closeElement(el);
// Nothing to do // Nothing to do
} }

View file

@ -19,16 +19,15 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.*; import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.symbol.*; import ghidra.app.plugin.processors.sleigh.symbol.*;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* An Expression representing the value of a Constructor operand * An Expression representing the value of a Constructor operand
*/ */
public class OperandValue extends PatternValue { public class OperandValue extends PatternValue {
@ -75,25 +74,16 @@ public class OperandValue extends PatternValue {
return ct; return ct;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
*/
@Override @Override
public long minValue() { public long minValue() {
throw new SleighException("Operand used in pattern expression"); throw new SleighException("Operand used in pattern expression");
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
*/
@Override @Override
public long maxValue() { public long maxValue() {
throw new SleighException("Operand used in pattern expression"); throw new SleighException("Operand used in pattern expression");
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public long getValue(ParserWalker walker) throws MemoryAccessException { public long getValue(ParserWalker walker) throws MemoryAccessException {
OperandSymbol sym = ct.getOperand(index); OperandSymbol sym = ct.getOperand(index);
@ -114,18 +104,15 @@ public class OperandValue extends PatternValue {
return res; return res;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start("operand_exp"); int el = decoder.openElement(ELEM_OPERAND_EXP);
index = SpecXmlUtils.decodeInt(el.getAttribute("index")); index = (int) decoder.readSignedInteger(ATTRIB_INDEX);
int tabid = SpecXmlUtils.decodeInt(el.getAttribute("table")); int tabid = (int) decoder.readUnsignedInteger(ATTRIB_TABLE);
int ctid = SpecXmlUtils.decodeInt(el.getAttribute("ct")); int ctid = (int) decoder.readUnsignedInteger(ATTRIB_CT);
SubtableSymbol sym = (SubtableSymbol) lang.getSymbolTable().findSymbol(tabid); SubtableSymbol sym = (SubtableSymbol) lang.getSymbolTable().findSymbol(tabid);
ct = sym.getConstructor(ctid); ct = sym.getConstructor(ctid);
parser.end(el); decoder.closeElement(el);
} }
@Override @Override

View file

@ -19,66 +19,85 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* An expression which results in a pattern for a specific InstructionContext * An expression which results in a pattern for a specific InstructionContext
*/ */
public abstract class PatternExpression { public abstract class PatternExpression {
public abstract long getValue(ParserWalker walker) throws MemoryAccessException; public abstract long getValue(ParserWalker walker) throws MemoryAccessException;
public abstract void restoreXml(XmlPullParser parser, SleighLanguage lang); public abstract void decode(Decoder decoder, SleighLanguage lang) throws DecoderException;
public static PatternExpression restoreExpression(XmlPullParser parser, SleighLanguage lang) { public static PatternExpression decodeExpression(Decoder decoder, SleighLanguage lang)
XmlElement el = parser.peek(); throws DecoderException {
int el = decoder.peekElement();
PatternExpression res; PatternExpression res;
String nm = el.getName(); if (el == ELEM_TOKENFIELD.id()) {
if (nm.equals("tokenfield"))
res = new TokenField(); res = new TokenField();
else if (nm.equals("contextfield")) }
else if (el == ELEM_CONTEXTFIELD.id()) {
res = new ContextField(); res = new ContextField();
else if (nm.equals("intb")) }
else if (el == ELEM_INTB.id()) {
res = new ConstantValue(); res = new ConstantValue();
else if (nm.equals("operand_exp")) }
else if (el == ELEM_OPERAND_EXP.id()) {
res = new OperandValue(); res = new OperandValue();
else if (nm.equals("start_exp")) }
else if (el == ELEM_START_EXP.id()) {
res = new StartInstructionValue(); res = new StartInstructionValue();
else if (nm.equals("end_exp")) }
else if (el == ELEM_END_EXP.id()) {
res = new EndInstructionValue(); res = new EndInstructionValue();
else if (nm.equals("next2_exp")) }
else if (el == ELEM_NEXT2_EXP.id()) {
res = new Next2InstructionValue(); res = new Next2InstructionValue();
else if (nm.equals("plus_exp")) }
else if (el == ELEM_PLUS_EXP.id()) {
res = new PlusExpression(); res = new PlusExpression();
else if (nm.equals("sub_exp")) }
else if (el == ELEM_SUB_EXP.id()) {
res = new SubExpression(); res = new SubExpression();
else if (nm.equals("mult_exp")) }
else if (el == ELEM_MULT_EXP.id()) {
res = new MultExpression(); res = new MultExpression();
else if (nm.equals("lshift_exp")) }
else if (el == ELEM_LSHIFT_EXP.id()) {
res = new LeftShiftExpression(); res = new LeftShiftExpression();
else if (nm.equals("rshift_exp")) }
else if (el == ELEM_RSHIFT_EXP.id()) {
res = new RightShiftExpression(); res = new RightShiftExpression();
else if (nm.equals("and_exp")) }
else if (el == ELEM_AND_EXP.id()) {
res = new AndExpression(); res = new AndExpression();
else if (nm.equals("or_exp")) }
else if (el == ELEM_OR_EXP.id()) {
res = new OrExpression(); res = new OrExpression();
else if (nm.equals("xor_exp")) }
else if (el == ELEM_XOR_EXP.id()) {
res = new XorExpression(); res = new XorExpression();
else if (nm.equals("div_exp")) }
else if (el == ELEM_DIV_EXP.id()) {
res = new DivExpression(); res = new DivExpression();
else if (nm.equals("minus_exp")) }
else if (el == ELEM_MINUS_EXP.id()) {
res = new MinusExpression(); res = new MinusExpression();
else if (nm.equals("not_exp")) }
else if (el == ELEM_NOT_EXP.id()) {
res = new NotExpression(); res = new NotExpression();
else }
else {
return null; return null;
}
res.restoreXml(parser, lang); res.decode(decoder, lang);
return res; return res;
} }

View file

@ -19,15 +19,16 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* The offset value of the current instructions address * The offset value of the current instructions address
*/ */
public class StartInstructionValue extends PatternValue { public class StartInstructionValue extends PatternValue {
@ -43,37 +44,26 @@ public class StartInstructionValue extends PatternValue {
return obj instanceof StartInstructionValue; return obj instanceof StartInstructionValue;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
*/
@Override @Override
public long minValue() { public long minValue() {
return 0; return 0;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
*/
@Override @Override
public long maxValue() { public long maxValue() {
return 0; return 0;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public long getValue(ParserWalker walker) throws MemoryAccessException { public long getValue(ParserWalker walker) throws MemoryAccessException {
Address addr = walker.getAddr(); Address addr = walker.getAddr();
return addr.getAddressableWordOffset(); return addr.getAddressableWordOffset();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
parser.discardSubTree("start_exp"); int el = decoder.openElement(ELEM_START_EXP);
decoder.closeElement(el);
// Nothing to do // Nothing to do
} }

View file

@ -19,16 +19,15 @@
*/ */
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* A contiguous set of bits within instruction stream, interpreted * A contiguous set of bits within instruction stream, interpreted
* as an integer value * as an integer value
*/ */
@ -75,17 +74,11 @@ public class TokenField extends PatternValue {
return true; return true;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
*/
@Override @Override
public long minValue() { public long minValue() {
return 0; return 0;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
*/
@Override @Override
public long maxValue() { public long maxValue() {
long res = -1; long res = -1;
@ -94,18 +87,17 @@ public class TokenField extends PatternValue {
return ~res; return ~res;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.InstructionContext)
*/
@Override @Override
public long getValue(ParserWalker walker) throws MemoryAccessException { public long getValue(ParserWalker walker) throws MemoryAccessException {
long res = getInstructionBytes(walker); long res = getInstructionBytes(walker);
res >>= shift; res >>= shift;
if (signbit) if (signbit) {
res = signExtend(res, bitend - bitstart); res = signExtend(res, bitend - bitstart);
else }
else {
res = zeroExtend(res, bitend - bitstart); res = zeroExtend(res, bitend - bitstart);
}
return res; return res;
} }
@ -125,20 +117,17 @@ public class TokenField extends PatternValue {
return byteend; return byteend;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start("tokenfield"); int el = decoder.openElement(ELEM_TOKENFIELD);
bigendian = SpecXmlUtils.decodeBoolean(el.getAttribute("bigendian")); bigendian = decoder.readBool(ATTRIB_BIGENDIAN);
signbit = SpecXmlUtils.decodeBoolean(el.getAttribute("signbit")); signbit = decoder.readBool(ATTRIB_SIGNBIT);
bitstart = SpecXmlUtils.decodeInt(el.getAttribute("bitstart")); bitstart = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
bitend = SpecXmlUtils.decodeInt(el.getAttribute("bitend")); bitend = (int) decoder.readSignedInteger(ATTRIB_ENDBIT);
bytestart = SpecXmlUtils.decodeInt(el.getAttribute("bytestart")); bytestart = (int) decoder.readSignedInteger(ATTRIB_STARTBYTE);
byteend = SpecXmlUtils.decodeInt(el.getAttribute("byteend")); byteend = (int) decoder.readSignedInteger(ATTRIB_ENDBYTE);
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift")); shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
parser.end(el); decoder.closeElement(el);
} }
public boolean hasSignbit() { public boolean hasSignbit() {
@ -146,10 +135,10 @@ public class TokenField extends PatternValue {
} }
/** /**
* Build a long from the instruction bytes in pos * Build a long from the instruction bytes at the current point in the parse
* @param pos Current instruction * @param walker is the instruction parse state
* @return * @return the recovered value
* @throws MemoryAccessException * @throws MemoryAccessException for problems reading the bytes
*/ */
private long getInstructionBytes(ParserWalker walker) throws MemoryAccessException { private long getInstructionBytes(ParserWalker walker) throws MemoryAccessException {
long res = 0; long res = 0;
@ -171,8 +160,9 @@ public class TokenField extends PatternValue {
res = res << (8 * tmpsize); res = res << (8 * tmpsize);
res |= (tmp & 0xffffffffl); res |= (tmp & 0xffffffffl);
} }
if (!bigendian) if (!bigendian) {
res = byteSwap(res, size); res = byteSwap(res, size);
}
return res; return res;
} }
@ -180,15 +170,17 @@ public class TokenField extends PatternValue {
* Sign extend -val- above -bit- * Sign extend -val- above -bit-
* @param val value to extend * @param val value to extend
* @param bit bit specifying sign * @param bit bit specifying sign
* @return * @return the extended value
*/ */
public static long signExtend(long val, int bit) { public static long signExtend(long val, int bit) {
long mask = 0; long mask = 0;
mask = (~mask) << bit; mask = (~mask) << bit;
if (((val >> bit) & 1) != 0) if (((val >> bit) & 1) != 0) {
val |= mask; val |= mask;
else }
else {
val &= (~mask); val &= (~mask);
}
return val; return val;
} }
@ -196,7 +188,7 @@ public class TokenField extends PatternValue {
* Clear all bits in -val- above -bit- * Clear all bits in -val- above -bit-
* @param val value to zero extend * @param val value to zero extend
* @param bit bit above which to zero extend * @param bit bit above which to zero extend
* @return * @return the extended value
*/ */
public static long zeroExtend(long val, int bit) { public static long zeroExtend(long val, int bit) {
long mask = 0; long mask = 0;
@ -210,7 +202,7 @@ public class TokenField extends PatternValue {
* Swap the least sig -size- bytes in -val- * Swap the least sig -size- bytes in -val-
* @param val value to be byte swapped * @param val value to be byte swapped
* @param size number of bytes involved in swap * @param size number of bytes involved in swap
* @return * @return the byte swapped value
*/ */
public static long byteSwap(long val, int size) { public static long byteSwap(long val, int size) {
long res = 0; long res = 0;

View file

@ -21,12 +21,10 @@
package ghidra.app.plugin.processors.sleigh.expression; package ghidra.app.plugin.processors.sleigh.expression;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* Base class for unary operators on PatternExpressions * Base class for unary operators on PatternExpressions
*/ */
@ -59,10 +57,10 @@ public abstract class UnaryExpression extends PatternExpression {
} }
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start(); int el = decoder.openElement();
unary = PatternExpression.restoreExpression(parser, lang); unary = PatternExpression.decodeExpression(decoder, lang);
parser.end(el); decoder.closeElement(el);
} }
} }

View file

@ -19,15 +19,15 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A pattern that has both an instruction part and non-instruction part * A pattern that has both an instruction part and non-instruction part
*/ */
public class CombinePattern extends DisjointPattern { public class CombinePattern extends DisjointPattern {
@ -35,9 +35,6 @@ public class CombinePattern extends DisjointPattern {
private ContextPattern context; // Context piece private ContextPattern context; // Context piece
private InstructionPattern instr; // Instruction piece private InstructionPattern instr; // Instruction piece
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
*/
@Override @Override
public PatternBlock getBlock(boolean cont) { public PatternBlock getBlock(boolean cont) {
return cont ? context.getBlock() : instr.getBlock(); return cont ? context.getBlock() : instr.getBlock();
@ -53,55 +50,50 @@ public class CombinePattern extends DisjointPattern {
instr = in; instr = in;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
*/
@Override @Override
public Pattern simplifyClone() { public Pattern simplifyClone() {
if (context.alwaysTrue()) if (context.alwaysTrue()) {
return instr.simplifyClone(); return instr.simplifyClone();
if (instr.alwaysTrue()) }
if (instr.alwaysTrue()) {
return context.simplifyClone(); return context.simplifyClone();
if (context.alwaysFalse() || instr.alwaysFalse()) }
if (context.alwaysFalse() || instr.alwaysFalse()) {
return new InstructionPattern(false); return new InstructionPattern(false);
}
return new CombinePattern((ContextPattern) context.simplifyClone(), return new CombinePattern((ContextPattern) context.simplifyClone(),
(InstructionPattern) instr.simplifyClone()); (InstructionPattern) instr.simplifyClone());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
*/
@Override @Override
public void shiftInstruction(int sa) { public void shiftInstruction(int sa) {
instr.shiftInstruction(sa); instr.shiftInstruction(sa);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doOr(Pattern b, int sa) { public Pattern doOr(Pattern b, int sa) {
if (b.numDisjoint() != 0) if (b.numDisjoint() != 0) {
return b.doOr(this, -sa); return b.doOr(this, -sa);
}
DisjointPattern res1 = (DisjointPattern) simplifyClone(); DisjointPattern res1 = (DisjointPattern) simplifyClone();
DisjointPattern res2 = (DisjointPattern) b.simplifyClone(); DisjointPattern res2 = (DisjointPattern) b.simplifyClone();
if (sa < 0) if (sa < 0) {
res1.shiftInstruction(-sa); res1.shiftInstruction(-sa);
else }
else {
res2.shiftInstruction(sa); res2.shiftInstruction(sa);
}
OrPattern tmp = new OrPattern(res1, res2); OrPattern tmp = new OrPattern(res1, res2);
return tmp; return tmp;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doAnd(Pattern b, int sa) { public Pattern doAnd(Pattern b, int sa) {
if (b.numDisjoint() != 0) if (b.numDisjoint() != 0) {
return b.doAnd(this, -sa); return b.doAnd(this, -sa);
}
CombinePattern tmp; CombinePattern tmp;
if (b instanceof CombinePattern) { if (b instanceof CombinePattern) {
@ -117,17 +109,15 @@ public class CombinePattern extends DisjointPattern {
else { // Must be a ContextPattern else { // Must be a ContextPattern
ContextPattern c = (ContextPattern) context.doAnd(b, 0); ContextPattern c = (ContextPattern) context.doAnd(b, 0);
InstructionPattern newpat = (InstructionPattern) instr.simplifyClone(); InstructionPattern newpat = (InstructionPattern) instr.simplifyClone();
if (sa < 0) if (sa < 0) {
newpat.shiftInstruction(-sa); newpat.shiftInstruction(-sa);
}
tmp = new CombinePattern(c, newpat); tmp = new CombinePattern(c, newpat);
} }
} }
return tmp; return tmp;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
*/
@Override @Override
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug) public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException { throws MemoryAccessException {
@ -167,41 +157,29 @@ public class CombinePattern extends DisjointPattern {
debug.indent(); debug.indent();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
*/
@Override @Override
public boolean alwaysTrue() { public boolean alwaysTrue() {
return (context.alwaysTrue() && instr.alwaysTrue()); return (context.alwaysTrue() && instr.alwaysTrue());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
*/
@Override @Override
public boolean alwaysFalse() { public boolean alwaysFalse() {
return (context.alwaysFalse() || instr.alwaysFalse()); return (context.alwaysFalse() || instr.alwaysFalse());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
*/
@Override @Override
public boolean alwaysInstructionTrue() { public boolean alwaysInstructionTrue() {
return instr.alwaysInstructionTrue(); return instr.alwaysInstructionTrue();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser) { public void decode(Decoder decoder) throws DecoderException {
XmlElement el = parser.start("combine_pat"); int el = decoder.openElement(ELEM_COMBINE_PAT);
context = new ContextPattern(); context = new ContextPattern();
context.restoreXml(parser); context.decode(decoder);
instr = new InstructionPattern(); instr = new InstructionPattern();
instr.restoreXml(parser); instr.decode(decoder);
parser.end(el); decoder.closeElement(el);
} }
@Override @Override

View file

@ -19,16 +19,16 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
import ghidra.util.StringUtilities; import ghidra.util.StringUtilities;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* Pattern which depends only on the non-instruction stream bits * Pattern which depends only on the non-instruction stream bits
* of the context * of the context
*/ */
@ -36,9 +36,6 @@ public class ContextPattern extends DisjointPattern {
private PatternBlock maskvalue; private PatternBlock maskvalue;
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
*/
@Override @Override
public PatternBlock getBlock(boolean context) { public PatternBlock getBlock(boolean context) {
return context ? maskvalue : null; return context ? maskvalue : null;
@ -56,49 +53,36 @@ public class ContextPattern extends DisjointPattern {
return maskvalue; return maskvalue;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
*/
@Override @Override
public Pattern simplifyClone() { public Pattern simplifyClone() {
return new ContextPattern((PatternBlock) maskvalue.clone()); return new ContextPattern((PatternBlock) maskvalue.clone());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
*/
@Override @Override
public void shiftInstruction(int sa) { public void shiftInstruction(int sa) {
// do nothing // do nothing
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doOr(Pattern b, int sa) { public Pattern doOr(Pattern b, int sa) {
if (!(b instanceof ContextPattern)) if (!(b instanceof ContextPattern)) {
return b.doOr(this, -sa); return b.doOr(this, -sa);
}
return new OrPattern((DisjointPattern) simplifyClone(), return new OrPattern((DisjointPattern) simplifyClone(),
(DisjointPattern) b.simplifyClone()); (DisjointPattern) b.simplifyClone());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doAnd(Pattern b, int sa) { public Pattern doAnd(Pattern b, int sa) {
if (!(b instanceof ContextPattern)) if (!(b instanceof ContextPattern)) {
return b.doAnd(this, -sa); return b.doAnd(this, -sa);
}
PatternBlock resblock = maskvalue.andBlock(((ContextPattern) b).maskvalue); PatternBlock resblock = maskvalue.andBlock(((ContextPattern) b).maskvalue);
return new ContextPattern(resblock); return new ContextPattern(resblock);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
*/
@Override @Override
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug) public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException { throws MemoryAccessException {
@ -149,39 +133,27 @@ public class ContextPattern extends DisjointPattern {
} }
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
*/
@Override @Override
public boolean alwaysTrue() { public boolean alwaysTrue() {
return maskvalue.alwaysTrue(); return maskvalue.alwaysTrue();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
*/
@Override @Override
public boolean alwaysFalse() { public boolean alwaysFalse() {
return maskvalue.alwaysFalse(); return maskvalue.alwaysFalse();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
*/
@Override @Override
public boolean alwaysInstructionTrue() { public boolean alwaysInstructionTrue() {
return true; return true;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser) { public void decode(Decoder decoder) throws DecoderException {
XmlElement el = parser.start("context_pat"); int el = decoder.openElement(ELEM_CONTEXT_PAT);
maskvalue = new PatternBlock(true); maskvalue = new PatternBlock(true);
maskvalue.restoreXml(parser); maskvalue.decode(decoder);
parser.end(el); decoder.closeElement(el);
} }
@Override @Override

View file

@ -19,12 +19,12 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import ghidra.xml.XmlElement; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.xml.XmlPullParser;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A pattern with no ORs in it * A pattern with no ORs in it
*/ */
public abstract class DisjointPattern extends Pattern { public abstract class DisjointPattern extends Pattern {
@ -55,22 +55,25 @@ public abstract class DisjointPattern extends Pattern {
public int getMask(int startbit, int size, boolean context) { public int getMask(int startbit, int size, boolean context) {
PatternBlock block = getBlock(context); PatternBlock block = getBlock(context);
if (block != null) if (block != null) {
return block.getMask(startbit, size); return block.getMask(startbit, size);
}
return 0; return 0;
} }
public int getValue(int startbit, int size, boolean context) { public int getValue(int startbit, int size, boolean context) {
PatternBlock block = getBlock(context); PatternBlock block = getBlock(context);
if (block != null) if (block != null) {
return block.getValue(startbit, size); return block.getValue(startbit, size);
}
return 0; return 0;
} }
public int getLength(boolean context) { public int getLength(boolean context) {
PatternBlock block = getBlock(context); PatternBlock block = getBlock(context);
if (block != null) if (block != null) {
return block.getLength(); return block.getLength();
}
return 0; return 0;
} }
@ -80,18 +83,22 @@ public abstract class DisjointPattern extends Pattern {
a = getBlock(false); a = getBlock(false);
b = op2.getBlock(false); b = op2.getBlock(false);
if (b != null) { // a must match existing block if (b != null) { // a must match existing block
if (a == null) if (a == null) {
return false; return false;
if (!a.specializes(b)) }
if (!a.specializes(b)) {
return false; return false;
}
} }
a = getBlock(true); a = getBlock(true);
b = op2.getBlock(true); b = op2.getBlock(true);
if (b != null) { // a must match existing block if (b != null) { // a must match existing block
if (a == null) if (a == null) {
return false; return false;
if (!a.specializes(b)) }
if (!a.specializes(b)) {
return false; return false;
}
} }
return true; return true;
} }
@ -102,32 +109,39 @@ public abstract class DisjointPattern extends Pattern {
a = getBlock(false); a = getBlock(false);
b = op2.getBlock(false); b = op2.getBlock(false);
if (b != null) { // a must match existing block if (b != null) { // a must match existing block
if (a == null) if (a == null) {
return false; return false;
if (!a.identical(b)) }
if (!a.identical(b)) {
return false; return false;
}
} }
a = getBlock(true); a = getBlock(true);
b = op2.getBlock(true); b = op2.getBlock(true);
if (b != null) { // a must match existing block if (b != null) { // a must match existing block
if (a == null) if (a == null) {
return false; return false;
if (!a.identical(b)) }
if (!a.identical(b)) {
return false; return false;
}
} }
return true; return true;
} }
static public DisjointPattern restoreDisjoint(XmlPullParser parser) { static public DisjointPattern decodeDisjoint(Decoder decoder) throws DecoderException {
XmlElement el = parser.peek(); int el = decoder.peekElement();
DisjointPattern res; DisjointPattern res;
if (el.getName().equals("instruct_pat")) if (el == ELEM_INSTRUCT_PAT.id()) {
res = new InstructionPattern(); res = new InstructionPattern();
else if (el.getName().equals("context_pat")) }
else if (el == ELEM_CONTEXT_PAT.id()) {
res = new ContextPattern(); res = new ContextPattern();
else }
else {
res = new CombinePattern(); res = new CombinePattern();
res.restoreXml(parser); }
res.decode(decoder);
return res; return res;
} }
} }

View file

@ -19,26 +19,23 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
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.Decoder;
import ghidra.program.model.pcode.DecoderException;
import ghidra.util.StringUtilities; import ghidra.util.StringUtilities;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* Matches against the actual instruction bit stream * Matches against the actual instruction bit stream
*/ */
public class InstructionPattern extends DisjointPattern { public class InstructionPattern extends DisjointPattern {
private PatternBlock maskvalue; private PatternBlock maskvalue;
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
*/
@Override @Override
public PatternBlock getBlock(boolean context) { public PatternBlock getBlock(boolean context) {
return context ? null : maskvalue; return context ? null : maskvalue;
@ -60,56 +57,51 @@ public class InstructionPattern extends DisjointPattern {
return maskvalue; return maskvalue;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
*/
@Override @Override
public Pattern simplifyClone() { public Pattern simplifyClone() {
return new InstructionPattern((PatternBlock) maskvalue.clone()); return new InstructionPattern((PatternBlock) maskvalue.clone());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction()
*/
@Override @Override
public void shiftInstruction(int sa) { public void shiftInstruction(int sa) {
maskvalue.shift(sa); maskvalue.shift(sa);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doOr(Pattern b, int sa) { public Pattern doOr(Pattern b, int sa) {
if (b.numDisjoint() > 0) if (b.numDisjoint() > 0) {
return b.doOr(this, -sa); return b.doOr(this, -sa);
}
if (b instanceof CombinePattern) if (b instanceof CombinePattern) {
return b.doOr(this, -sa); return b.doOr(this, -sa);
}
DisjointPattern res1, res2; DisjointPattern res1, res2;
res1 = (DisjointPattern) simplifyClone(); res1 = (DisjointPattern) simplifyClone();
res2 = (DisjointPattern) b.simplifyClone(); res2 = (DisjointPattern) b.simplifyClone();
if (sa < 0) if (sa < 0) {
res1.shiftInstruction(-sa); res1.shiftInstruction(-sa);
else }
else {
res2.shiftInstruction(sa); res2.shiftInstruction(sa);
}
return new OrPattern(res1, res2); return new OrPattern(res1, res2);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doAnd(Pattern b, int sa) { public Pattern doAnd(Pattern b, int sa) {
if (b.numDisjoint() > 0) if (b.numDisjoint() > 0) {
return b.doAnd(this, -sa); return b.doAnd(this, -sa);
if (b instanceof CombinePattern) }
if (b instanceof CombinePattern) {
return b.doAnd(this, -sa); return b.doAnd(this, -sa);
}
if (b instanceof ContextPattern) { if (b instanceof ContextPattern) {
InstructionPattern newpat = (InstructionPattern) simplifyClone(); InstructionPattern newpat = (InstructionPattern) simplifyClone();
if (sa < 0) if (sa < 0) {
newpat.shiftInstruction(-sa); newpat.shiftInstruction(-sa);
}
return new CombinePattern((ContextPattern) b.simplifyClone(), newpat); return new CombinePattern((ContextPattern) b.simplifyClone(), newpat);
} }
// b must be an InstructionPattern if it reaches here // b must be an InstructionPattern if it reaches here
@ -127,9 +119,6 @@ public class InstructionPattern extends DisjointPattern {
return new InstructionPattern(respattern); return new InstructionPattern(respattern);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
*/
@Override @Override
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug) public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException { throws MemoryAccessException {
@ -176,39 +165,27 @@ public class InstructionPattern extends DisjointPattern {
} }
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
*/
@Override @Override
public boolean alwaysTrue() { public boolean alwaysTrue() {
return maskvalue.alwaysTrue(); return maskvalue.alwaysTrue();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
*/
@Override @Override
public boolean alwaysFalse() { public boolean alwaysFalse() {
return maskvalue.alwaysFalse(); return maskvalue.alwaysFalse();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
*/
@Override @Override
public boolean alwaysInstructionTrue() { public boolean alwaysInstructionTrue() {
return maskvalue.alwaysTrue(); return maskvalue.alwaysTrue();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser) { public void decode(Decoder decoder) throws DecoderException {
XmlElement el = parser.start("instruct_pat"); int el = decoder.openElement(ELEM_INSTRUCT_PAT);
maskvalue = new PatternBlock(true); maskvalue = new PatternBlock(true);
maskvalue.restoreXml(parser); maskvalue.decode(decoder);
parser.end(el); decoder.closeElement(el);
} }
@Override @Override

View file

@ -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,127 +19,127 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import ghidra.app.plugin.processors.sleigh.*; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.program.model.mem.*;
import ghidra.xml.*;
import java.util.*; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A pattern that can be matched by matching any of a list of subpatterns * A pattern that can be matched by matching any of a list of subpatterns
*/ */
public class OrPattern extends Pattern { public class OrPattern extends Pattern {
private DisjointPattern[] orlist; private DisjointPattern[] orlist;
public OrPattern() { orlist = null; } // For use with restoreXml public OrPattern() {
orlist = null;
public OrPattern(DisjointPattern a,DisjointPattern b) { }
public OrPattern(DisjointPattern a, DisjointPattern b) {
orlist = new DisjointPattern[2]; orlist = new DisjointPattern[2];
orlist[0] = a; orlist[0] = a;
orlist[1] = b; orlist[1] = b;
} }
public OrPattern(ArrayList<?> list) { public OrPattern(ArrayList<?> list) {
orlist = new DisjointPattern[list.size()]; orlist = new DisjointPattern[list.size()];
for(int i=0;i<list.size();++i) for (int i = 0; i < list.size(); ++i) {
orlist[i] = (DisjointPattern)list.get(i); orlist[i] = (DisjointPattern) list.get(i);
}
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
*/
@Override @Override
public Pattern simplifyClone() { public Pattern simplifyClone() {
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
if (orlist[i].alwaysTrue()) if (orlist[i].alwaysTrue()) {
return new InstructionPattern(true); return new InstructionPattern(true);
}
} }
ArrayList<Object> newlist = new ArrayList<Object>(); ArrayList<Object> newlist = new ArrayList<Object>();
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
if (!orlist[i].alwaysFalse()) if (!orlist[i].alwaysFalse()) {
newlist.add(orlist[i].simplifyClone()); newlist.add(orlist[i].simplifyClone());
}
} }
if (newlist.size()==0) if (newlist.size() == 0) {
return new InstructionPattern(false); return new InstructionPattern(false);
else if (newlist.size()==1) }
return (Pattern)newlist.get(0); else if (newlist.size() == 1) {
return (Pattern) newlist.get(0);
}
return new OrPattern(newlist); return new OrPattern(newlist);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
*/
@Override @Override
public void shiftInstruction(int sa) { public void shiftInstruction(int sa) {
for(int i=0;i<orlist.length;++i) for (int i = 0; i < orlist.length; ++i) {
orlist[i].shiftInstruction(sa); orlist[i].shiftInstruction(sa);
}
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doOr(Pattern b, int sa) { public Pattern doOr(Pattern b, int sa) {
ArrayList<Object> newlist = new ArrayList<Object>(); ArrayList<Object> newlist = new ArrayList<Object>();
for(int i=0;i<orlist.length;++i) for (int i = 0; i < orlist.length; ++i) {
newlist.add(orlist[i].simplifyClone()); newlist.add(orlist[i].simplifyClone());
if (sa < 0) {
for(int i=0;i<orlist.length;++i)
orlist[i].shiftInstruction(-sa);
} }
if (sa < 0) {
for (int i = 0; i < orlist.length; ++i) {
orlist[i].shiftInstruction(-sa);
}
}
if (b instanceof OrPattern) { if (b instanceof OrPattern) {
OrPattern b2 = (OrPattern)b; OrPattern b2 = (OrPattern) b;
for(int i=0;i<b2.orlist.length;++i) for (int i = 0; i < b2.orlist.length; ++i) {
newlist.add(b2.orlist[i].simplifyClone()); newlist.add(b2.orlist[i].simplifyClone());
}
} }
else { else {
newlist.add(b.simplifyClone()); newlist.add(b.simplifyClone());
} }
if (sa > 0) { if (sa > 0) {
for(int i=0;i<newlist.size();++i) for (int i = 0; i < newlist.size(); ++i) {
((Pattern)newlist.get(i)).shiftInstruction(sa); ((Pattern) newlist.get(i)).shiftInstruction(sa);
}
} }
return new OrPattern(newlist); return new OrPattern(newlist);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
*/
@Override @Override
public Pattern doAnd(Pattern b, int sa) { public Pattern doAnd(Pattern b, int sa) {
DisjointPattern tmp; DisjointPattern tmp;
ArrayList<Object> newlist = new ArrayList<Object>(); ArrayList<Object> newlist = new ArrayList<Object>();
if (b instanceof OrPattern) { if (b instanceof OrPattern) {
OrPattern b2 = (OrPattern)b; OrPattern b2 = (OrPattern) b;
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
for(int j=0;j<b2.orlist.length;++j) { for (int j = 0; j < b2.orlist.length; ++j) {
tmp = (DisjointPattern)orlist[i].doAnd(b2.orlist[j],sa); tmp = (DisjointPattern) orlist[i].doAnd(b2.orlist[j], sa);
newlist.add(tmp); newlist.add(tmp);
} }
} }
} }
else { else {
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
tmp = (DisjointPattern)orlist[i].doAnd(b,sa); tmp = (DisjointPattern) orlist[i].doAnd(b, sa);
newlist.add(tmp); newlist.add(tmp);
} }
} }
return new OrPattern(newlist); return new OrPattern(newlist);
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
*/
@Override @Override
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException { public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException {
boolean match = false; boolean match = false;
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
debugNextMatch(debug, i); debugNextMatch(debug, i);
if (orlist[i].isMatch(walker, debug)) { if (orlist[i].isMatch(walker, debug)) {
match = true; match = true;
@ -148,9 +147,9 @@ public class OrPattern extends Pattern {
} }
} }
debugDone(debug, match); debugDone(debug, match);
return match; return match;
} }
private void debugDone(SleighDebugLogger debug, boolean match) { private void debugDone(SleighDebugLogger debug, boolean match) {
if (debug != null) { if (debug != null) {
debug.endPatternGroup(match); debug.endPatternGroup(match);
@ -175,72 +174,60 @@ public class OrPattern extends Pattern {
debug.indent(); debug.indent();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#numDisjoint()
*/
@Override @Override
public int numDisjoint() { public int numDisjoint() {
return orlist.length; return orlist.length;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#getDisjoint(int)
*/
@Override @Override
public DisjointPattern getDisjoint(int i) { public DisjointPattern getDisjoint(int i) {
return orlist[i]; return orlist[i];
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
*/
@Override @Override
public boolean alwaysTrue() { public boolean alwaysTrue() {
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
if (orlist[i].alwaysTrue()) return true; if (orlist[i].alwaysTrue()) {
return true;
}
} }
return false; return false;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
*/
@Override @Override
public boolean alwaysFalse() { public boolean alwaysFalse() {
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
if (!orlist[i].alwaysFalse()) return false; if (!orlist[i].alwaysFalse()) {
return false;
}
} }
return true; return true;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
*/
@Override @Override
public boolean alwaysInstructionTrue() { public boolean alwaysInstructionTrue() {
for(int i=0;i<orlist.length;++i) { for (int i = 0; i < orlist.length; ++i) {
if (!orlist[i].alwaysInstructionTrue()) return false; if (!orlist[i].alwaysInstructionTrue()) {
return false;
}
} }
return true; return true;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
*/
@Override @Override
public void restoreXml(XmlPullParser parser) { public void decode(Decoder decoder) throws DecoderException {
XmlElement el = parser.start("or_pat"); int el = decoder.openElement(ELEM_OR_PAT);
ArrayList<DisjointPattern> ors = new ArrayList<DisjointPattern>(); ArrayList<DisjointPattern> ors = new ArrayList<DisjointPattern>();
XmlElement peek = parser.peek(); int peek = decoder.peekElement();
while (!peek.isEnd()) { while (peek != 0) {
ors.add(DisjointPattern.restoreDisjoint(parser)); ors.add(DisjointPattern.decodeDisjoint(decoder));
} }
orlist = new DisjointPattern[ors.size()]; orlist = new DisjointPattern[ors.size()];
int i = 0; int i = 0;
for (DisjointPattern pat : ors) { for (DisjointPattern pat : ors) {
orlist[i++] = pat; orlist[i++] = pat;
} }
parser.end(el); decoder.closeElement(el);
} }
} }

View file

@ -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,13 +19,13 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import ghidra.app.plugin.processors.sleigh.*; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.program.model.mem.*; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
import ghidra.xml.*; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A pattern which either matches or doesnt match a particular * A pattern which either matches or doesnt match a particular
* InstructionContext. In particular, the bits comprising the * InstructionContext. In particular, the bits comprising the
* current instruction in the executable, and possible other * current instruction in the executable, and possible other
@ -34,14 +33,25 @@ import ghidra.xml.*;
*/ */
public abstract class Pattern { public abstract class Pattern {
public abstract Pattern simplifyClone(); public abstract Pattern simplifyClone();
public abstract void shiftInstruction(int sa); public abstract void shiftInstruction(int sa);
public abstract Pattern doOr(Pattern b,int sa);
public abstract Pattern doAnd(Pattern b,int sa); public abstract Pattern doOr(Pattern b, int sa);
public abstract boolean isMatch(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException;
public abstract Pattern doAnd(Pattern b, int sa);
public abstract boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException;
public abstract int numDisjoint(); public abstract int numDisjoint();
public abstract DisjointPattern getDisjoint(int i); public abstract DisjointPattern getDisjoint(int i);
public abstract boolean alwaysTrue(); public abstract boolean alwaysTrue();
public abstract boolean alwaysFalse(); public abstract boolean alwaysFalse();
public abstract boolean alwaysInstructionTrue(); public abstract boolean alwaysInstructionTrue();
public abstract void restoreXml(XmlPullParser parser);
public abstract void decode(Decoder decoder) throws DecoderException;
} }

View file

@ -19,18 +19,17 @@
*/ */
package ghidra.app.plugin.processors.sleigh.pattern; package ghidra.app.plugin.processors.sleigh.pattern;
import static ghidra.pcode.utils.SlaFormat.*;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.ParserWalker; import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
import ghidra.util.NumericUtilities; import ghidra.util.NumericUtilities;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* A mask/value pair viewed as two bitstreams * A mask/value pair viewed as two bitstreams
*/ */
public class PatternBlock { public class PatternBlock {
@ -43,10 +42,12 @@ public class PatternBlock {
int delsize = end - start; int delsize = end - start;
int newsize = array.length - delsize; int newsize = array.length - delsize;
int[] res = new int[newsize]; int[] res = new int[newsize];
for (int i = 0; i < start; ++i) for (int i = 0; i < start; ++i) {
res[i] = array[i]; res[i] = array[i];
for (int i = end; i < array.length; ++i) }
for (int i = end; i < array.length; ++i) {
res[i - delsize] = array[i]; res[i - delsize] = array[i];
}
return res; return res;
} }
@ -104,8 +105,9 @@ public class PatternBlock {
while (iter1 != 0) { while (iter1 != 0) {
--iter1; --iter1;
--iter2; --iter2;
if (maskvec[iter1] != 0) if (maskvec[iter1] != 0) {
break; // Find last non-zero break; // Find last non-zero
}
} }
if (iter1 != maskvec.length) { if (iter1 != maskvec.length) {
iter1++; // Find first zero,in last zero chain iter1++; // Find first zero,in last zero chain
@ -142,10 +144,12 @@ public class PatternBlock {
public PatternBlock(boolean tf) { public PatternBlock(boolean tf) {
offset = 0; offset = 0;
if (tf) if (tf) {
nonzerosize = 0; nonzerosize = 0;
else }
else {
nonzerosize = -1; nonzerosize = -1;
}
maskvec = null; maskvec = null;
valvec = null; valvec = null;
} }
@ -193,8 +197,9 @@ public class PatternBlock {
int maxlength = (getLength() > b.getLength()) ? getLength() : b.getLength(); int maxlength = (getLength() > b.getLength()) ? getLength() : b.getLength();
int asize = maxlength / 4; int asize = maxlength / 4;
if (maxlength % 4 != 0) if (maxlength % 4 != 0) {
asize += 1; asize += 1;
}
res.maskvec = new int[asize]; res.maskvec = new int[asize];
res.valvec = new int[asize]; res.valvec = new int[asize];
res.offset = 0; res.offset = 0;
@ -206,17 +211,20 @@ public class PatternBlock {
val1 = getValue(offset1 * 8, 32); val1 = getValue(offset1 * 8, 32);
mask2 = b.getMask(offset1 * 8, 32); mask2 = b.getMask(offset1 * 8, 32);
val2 = b.getValue(offset1 * 8, 32); val2 = b.getValue(offset1 * 8, 32);
if (((mask2 & mask1) & val2) != ((mask2 & mask1) & val1)) if (((mask2 & mask1) & val2) != ((mask2 & mask1) & val1)) {
break; // Impossible pattern break; // Impossible pattern
}
res.maskvec[i] = mask1 | mask2; res.maskvec[i] = mask1 | mask2;
res.valvec[i] = val1 | val2; res.valvec[i] = val1 | val2;
offset1 += 4; offset1 += 4;
i += 1; i += 1;
} }
if (offset1 < maxlength) // If pattern is impossible if (offset1 < maxlength) { // If pattern is impossible
res.nonzerosize = -1; res.nonzerosize = -1;
else }
else { // If pattern is impossible
res.nonzerosize = maxlength; res.nonzerosize = maxlength;
}
res.normalize(); res.normalize();
return res; return res;
} }
@ -228,16 +236,19 @@ public class PatternBlock {
int sbit = 0; int sbit = 0;
while (sbit < length) { while (sbit < length) {
tmplength = length - sbit; tmplength = length - sbit;
if (tmplength > 32) if (tmplength > 32) {
tmplength = 32; tmplength = 32;
}
mask1 = getMask(sbit, tmplength); mask1 = getMask(sbit, tmplength);
value1 = getValue(sbit, tmplength); value1 = getValue(sbit, tmplength);
mask2 = op2.getMask(sbit, tmplength); mask2 = op2.getMask(sbit, tmplength);
value2 = op2.getValue(sbit, tmplength); value2 = op2.getValue(sbit, tmplength);
if ((mask1 & mask2) != mask2) if ((mask1 & mask2) != mask2) {
return false; return false;
if ((value1 & mask2) != (value2 & mask2)) }
if ((value1 & mask2) != (value2 & mask2)) {
return false; return false;
}
sbit += tmplength; sbit += tmplength;
} }
return true; return true;
@ -250,16 +261,19 @@ public class PatternBlock {
int sbit = 0; int sbit = 0;
while (sbit < length) { while (sbit < length) {
tmplength = length - sbit; tmplength = length - sbit;
if (tmplength > 32) if (tmplength > 32) {
tmplength = 32; tmplength = 32;
}
mask1 = getMask(sbit, tmplength); mask1 = getMask(sbit, tmplength);
value1 = getValue(sbit, tmplength); value1 = getValue(sbit, tmplength);
mask2 = op2.getMask(sbit, tmplength); mask2 = op2.getMask(sbit, tmplength);
value2 = op2.getValue(sbit, tmplength); value2 = op2.getValue(sbit, tmplength);
if (mask1 != mask2) if (mask1 != mask2) {
return false; return false;
if ((mask1 & value1) != (mask2 & value2)) }
if ((mask1 & value1) != (mask2 & value2)) {
return false; return false;
}
sbit += tmplength; sbit += tmplength;
} }
return true; return true;
@ -281,17 +295,21 @@ public class PatternBlock {
int wordnum2 = (startbit + size - 1) / 32; int wordnum2 = (startbit + size - 1) / 32;
int res; int res;
if ((wordnum1 < 0) || (wordnum1 >= maskvec.length)) if ((wordnum1 < 0) || (wordnum1 >= maskvec.length)) {
res = 0; res = 0;
else }
else {
res = maskvec[wordnum1]; res = maskvec[wordnum1];
}
res <<= shift; res <<= shift;
if (wordnum1 != wordnum2) { if (wordnum1 != wordnum2) {
int tmp; int tmp;
if ((wordnum2 < 0) || (wordnum2 >= maskvec.length)) if ((wordnum2 < 0) || (wordnum2 >= maskvec.length)) {
tmp = 0; tmp = 0;
else }
else {
tmp = maskvec[wordnum2]; tmp = maskvec[wordnum2];
}
res |= (tmp >>> (32 - shift)); res |= (tmp >>> (32 - shift));
} }
res >>>= 32 - size; res >>>= 32 - size;
@ -305,17 +323,21 @@ public class PatternBlock {
int wordnum2 = (startbit + size - 1) / 32; int wordnum2 = (startbit + size - 1) / 32;
int res; int res;
if ((wordnum1 < 0) || (wordnum1 >= valvec.length)) if ((wordnum1 < 0) || (wordnum1 >= valvec.length)) {
res = 0; res = 0;
else }
else {
res = valvec[wordnum1]; res = valvec[wordnum1];
}
res <<= shift; res <<= shift;
if (wordnum1 != wordnum2) { if (wordnum1 != wordnum2) {
int tmp; int tmp;
if ((wordnum2 < 0) || (wordnum2 >= valvec.length)) if ((wordnum2 < 0) || (wordnum2 >= valvec.length)) {
tmp = 0; tmp = 0;
else }
else {
tmp = valvec[wordnum2]; tmp = valvec[wordnum2];
}
res |= (tmp >>> (32 - shift)); res |= (tmp >>> (32 - shift));
} }
res >>>= 32 - size; res >>>= 32 - size;
@ -331,14 +353,16 @@ public class PatternBlock {
} }
public boolean isInstructionMatch(ParserWalker walker) { public boolean isInstructionMatch(ParserWalker walker) {
if (nonzerosize <= 0) if (nonzerosize <= 0) {
return (nonzerosize == 0); return (nonzerosize == 0);
}
int off = offset; int off = offset;
try { try {
for (int i = 0; i < maskvec.length; ++i) { for (int i = 0; i < maskvec.length; ++i) {
int data = walker.getInstructionBytes(off, 4); int data = walker.getInstructionBytes(off, 4);
if ((maskvec[i] & data) != valvec[i]) if ((maskvec[i] & data) != valvec[i]) {
return false; return false;
}
off += 4; off += 4;
} }
return true; return true;
@ -349,37 +373,39 @@ public class PatternBlock {
} }
public boolean isContextMatch(ParserWalker walker) { public boolean isContextMatch(ParserWalker walker) {
if (nonzerosize <= 0) if (nonzerosize <= 0) {
return (nonzerosize == 0); return (nonzerosize == 0);
}
int off = offset; int off = offset;
for (int i = 0; i < maskvec.length; ++i) { for (int i = 0; i < maskvec.length; ++i) {
int data = walker.getContextBytes(off, 4); int data = walker.getContextBytes(off, 4);
if ((maskvec[i] & data) != valvec[i]) if ((maskvec[i] & data) != valvec[i]) {
return false; return false;
}
off += 4; off += 4;
} }
return true; return true;
} }
public void restoreXml(XmlPullParser parser) { public void decode(Decoder decoder) throws DecoderException {
XmlElement el = parser.start("pat_block"); int el = decoder.openElement(ELEM_PAT_BLOCK);
offset = SpecXmlUtils.decodeInt(el.getAttribute("offset")); offset = (int) decoder.readSignedInteger(ATTRIB_OFF);
nonzerosize = SpecXmlUtils.decodeInt(el.getAttribute("nonzero")); nonzerosize = (int) decoder.readSignedInteger(ATTRIB_NONZERO);
ArrayList<String> masks = new ArrayList<>(); ArrayList<Integer> masks = new ArrayList<>();
ArrayList<String> vals = new ArrayList<>(); ArrayList<Integer> vals = new ArrayList<>();
XmlElement subel; while (decoder.peekElement() == ELEM_MASK_WORD.id()) {
while ((subel = parser.softStart("mask_word")) != null) { decoder.openElement();
masks.add(subel.getAttribute("mask")); masks.add((int) decoder.readUnsignedInteger(ATTRIB_MASK));
vals.add(subel.getAttribute("val")); vals.add((int) decoder.readUnsignedInteger(ATTRIB_VAL));
parser.end(subel); decoder.closeElement(ELEM_MASK_WORD.id());
} }
maskvec = new int[masks.size()]; maskvec = new int[masks.size()];
valvec = new int[vals.size()]; valvec = new int[vals.size()];
for (int i = 0; i < maskvec.length; ++i) { for (int i = 0; i < maskvec.length; ++i) {
maskvec[i] = SpecXmlUtils.decodeInt(masks.get(i)); maskvec[i] = masks.get(i);
valvec[i] = SpecXmlUtils.decodeInt(vals.get(i)); valvec[i] = vals.get(i);
} }
parser.end(el); decoder.closeElement(el);
} }
@Override @Override

View file

@ -19,15 +19,14 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.plugin.processors.sleigh.expression.*; import ghidra.app.plugin.processors.sleigh.expression.*;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* A ValueSymbol that gets its semantic value from contiguous bits * A ValueSymbol that gets its semantic value from contiguous bits
* in a VarnodeSymbol. This serves as an embedding of a ContextOp * in a VarnodeSymbol. This serves as an embedding of a ContextOp
* into an actual Varnode and is probably only relevant at compile time * into an actual Varnode and is probably only relevant at compile time
@ -35,11 +34,13 @@ import ghidra.xml.XmlPullParser;
public class ContextSymbol extends ValueSymbol { public class ContextSymbol extends ValueSymbol {
private VarnodeSymbol vn; private VarnodeSymbol vn;
private int low,high; // Bit range of context value private int low, high; // Bit range of context value
private boolean flow = true; // indicates that context should follow flow private boolean flow = true; // indicates that context should follow flow
public VarnodeSymbol getVarnode() { return vn; } public VarnodeSymbol getVarnode() {
return vn;
}
/** /**
* Get starting bit of context value within its context register. * Get starting bit of context value within its context register.
* @return the starting bit * @return the starting bit
@ -74,20 +75,39 @@ public class ContextSymbol extends ValueSymbol {
public int getInternalHigh() { public int getInternalHigh() {
return ((ContextField) patval).getEndBit(); return ((ContextField) patval).getEndBit();
} }
public boolean followsFlow() { return flow; }
public boolean followsFlow() {
return flow;
}
@Override @Override
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) { public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
XmlElement el = parser.start("context_sym"); // int el = decoder.openElement(ELEM_CONTEXT_SYM);
int id = SpecXmlUtils.decodeInt(el.getAttribute("varnode")); flow = false;
int id = (int) decoder.readUnsignedInteger(ATTRIB_VARNODE);
SymbolTable symtab = sleigh.getSymbolTable(); SymbolTable symtab = sleigh.getSymbolTable();
vn = (VarnodeSymbol)symtab.findSymbol(id); vn = (VarnodeSymbol) symtab.findSymbol(id);
low = SpecXmlUtils.decodeInt(el.getAttribute("low")); int attrib = decoder.getNextAttributeId();
if (el.hasAttribute("flow")) { boolean lowMissing = true;
flow = SpecXmlUtils.decodeBoolean(el.getAttribute("flow")); boolean highMissing = true;
while (attrib != 0) {
if (attrib == ATTRIB_LOW.id()) {
low = (int) decoder.readSignedInteger();
lowMissing = false;
}
else if (attrib == ATTRIB_HIGH.id()) {
high = (int) decoder.readSignedInteger();
highMissing = false;
}
else if (attrib == ATTRIB_FLOW.id()) {
flow = decoder.readBool();
}
attrib = decoder.getNextAttributeId();
} }
high = SpecXmlUtils.decodeInt(el.getAttribute("high")); if (lowMissing || highMissing) {
patval = (PatternValue)PatternExpression.restoreExpression(parser,sleigh); throw new DecoderException("Missing high/low attributes");
parser.end(el); }
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
decoder.closeElement(ELEM_CONTEXT_SYM.id());
} }
} }

View file

@ -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,63 +19,54 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import ghidra.app.plugin.processors.sleigh.*; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.expression.*;
import ghidra.program.model.mem.*;
import ghidra.xml.*;
import java.util.*; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.expression.EndInstructionValue;
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* Symbol with semantic value equal to offset of address immediately * Symbol with semantic value equal to offset of address immediately
* after current instruction * after current instruction
*/ */
public class EndSymbol extends SpecificSymbol { public class EndSymbol extends SpecificSymbol {
private PatternExpression patexp; private PatternExpression patexp;
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
*/
@Override @Override
public PatternExpression getPatternExpression() { public PatternExpression getPatternExpression() {
return patexp; return patexp;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public void getFixedHandle(FixedHandle hand, ParserWalker walker) { public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
hand.space = walker.getCurSpace(); hand.space = walker.getCurSpace();
hand.offset_space = null; hand.offset_space = null;
hand.offset_offset = walker.getNaddr().getOffset(); hand.offset_offset = walker.getNaddr().getOffset();
hand.size = hand.space.getPointerSize(); hand.size = hand.space.getPointerSize();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public String print(ParserWalker walker) throws MemoryAccessException { public String print(ParserWalker walker) throws MemoryAccessException {
long val = walker.getNaddr().getOffset(); long val = walker.getNaddr().getOffset();
return "0x"+Long.toHexString(val); return "0x" + Long.toHexString(val);
} }
@Override @Override
public void printList(ParserWalker walker, ArrayList<Object> list) { public void printList(ParserWalker walker, ArrayList<Object> list) {
list.add(walker.getParentHandle()); list.add(walker.getParentHandle());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) { public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
XmlElement element = parser.start("end_sym"); // int el = decoder.openElement(ELEM_END_SYM);
patexp = new EndInstructionValue(); patexp = new EndInstructionValue();
parser.end(element); decoder.closeElement(ELEM_END_SYM.id());
} }
} }

View file

@ -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,50 +19,43 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import ghidra.app.plugin.processors.sleigh.*; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.xml.*;
import java.util.*; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.*;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A pattern with no semantic or printing content, that will match * A pattern with no semantic or printing content, that will match
* any pattern. * any pattern.
*/ */
public class EpsilonSymbol extends PatternlessSymbol { public class EpsilonSymbol extends PatternlessSymbol {
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public void getFixedHandle(FixedHandle hand, ParserWalker walker) { public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
hand.space = walker.getConstSpace(); hand.space = walker.getConstSpace();
hand.offset_space = null; // Not a dynamic value hand.offset_space = null; // Not a dynamic value
hand.offset_offset = 0; hand.offset_offset = 0;
hand.size = 0; // Cannot provide size hand.size = 0; // Cannot provide size
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public String print(ParserWalker walker) { public String print(ParserWalker walker) {
return "0"; return "0";
} }
@Override @Override
public void printList(ParserWalker walker, ArrayList<Object> list) { public void printList(ParserWalker walker, ArrayList<Object> list) {
list.add(walker.getParentHandle()); list.add(walker.getParentHandle());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.Symbol#restoreXml(org.jdom.Element, ghidra.program.model.address.AddressFactory)
*/
@Override @Override
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) { public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
XmlElement element = parser.start("epsilon_sym"); // int element = decoder.openElement(ELEM_EPSILON_SYM);
decoder.closeElement(ELEM_EPSILON_SYM.id());
// Nothing to do // Nothing to do
parser.end(element);
} }
} }

View file

@ -19,6 +19,8 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import static ghidra.pcode.utils.SlaFormat.*;
import java.util.*; import java.util.*;
import ghidra.app.plugin.processors.sleigh.*; import ghidra.app.plugin.processors.sleigh.*;
@ -26,12 +28,10 @@ import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.app.plugin.processors.sleigh.expression.PatternValue; import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A ValueSymbol whose printing aspect is determined by looking * A ValueSymbol whose printing aspect is determined by looking
* up the context value of the symbol in a table of strings * up the context value of the symbol in a table of strings
*/ */
@ -55,9 +55,6 @@ public class NameSymbol extends ValueSymbol {
} }
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#resolve(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
*/
@Override @Override
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug) public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException, UnknownInstructionException { throws MemoryAccessException, UnknownInstructionException {
@ -75,42 +72,43 @@ public class NameSymbol extends ValueSymbol {
return null; return null;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public String print(ParserWalker walker) throws MemoryAccessException { public String print(ParserWalker walker) throws MemoryAccessException {
int ind = (int) getPatternValue().getValue(walker); int ind = (int) getPatternValue().getValue(walker);
return nametable[ind]; return nametable[ind];
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#printList(ghidra.app.plugin.processors.sleigh.ParserWalker, java.util.ArrayList)
*/
@Override @Override
public void printList(ParserWalker walker, ArrayList<Object> list) public void printList(ParserWalker walker, ArrayList<Object> list)
throws MemoryAccessException { throws MemoryAccessException {
int ind = (int) getPatternValue().getValue(walker); int ind = (int) getPatternValue().getValue(walker);
String token = nametable[ind]; String token = nametable[ind];
for (int i = 0; i < token.length(); ++i) for (int i = 0; i < token.length(); ++i) {
list.add(Character.valueOf(token.charAt(i))); list.add(Character.valueOf(token.charAt(i)));
}
} }
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) { public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
XmlElement el = parser.start("name_sym"); // int el = decoder.openElement(ELEM_NAME_SYM);
patval = (PatternValue) PatternExpression.restoreExpression(parser, sleigh); patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
ArrayList<String> names = new ArrayList<>(); ArrayList<String> names = new ArrayList<>();
XmlElement nametab; while (decoder.peekElement() == ELEM_NAMETAB.id()) {
while ((nametab = parser.softStart("nametab")) != null) { decoder.openElement();
names.add(nametab.getAttribute("name")); int attrib = decoder.getNextAttributeId();
parser.end(nametab); if (attrib == ATTRIB_NAME.id()) {
names.add(decoder.readString());
}
else {
names.add(null);
}
decoder.closeElement(ELEM_NAMETAB.id());
} }
nametable = new String[names.size()]; nametable = new String[names.size()];
for (int i = 0; i < nametable.length; ++i) { for (int i = 0; i < nametable.length; ++i) {
nametable[i] = names.get(i); nametable[i] = names.get(i);
} }
checkTableFill(); checkTableFill();
parser.end(el); decoder.closeElement(ELEM_NAME_SYM.id());
} }
} }

View file

@ -15,32 +15,32 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import static ghidra.pcode.utils.SlaFormat.*;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.*; import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.expression.Next2InstructionValue; import ghidra.app.plugin.processors.sleigh.expression.Next2InstructionValue;
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression; import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlPullParser; import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* Symbol with semantic value equal to offset of address immediately * Symbol with semantic value equal to offset of address immediately
* after the next instruction (inst_next2) * after the next instruction (inst_next2)
*/ */
public class Next2Symbol extends SpecificSymbol { public class Next2Symbol extends SpecificSymbol {
private PatternExpression patexp; private PatternExpression patexp;
@Override @Override
public PatternExpression getPatternExpression() { public PatternExpression getPatternExpression() {
return patexp; return patexp;
} }
@Override @Override
public void getFixedHandle(FixedHandle hand, ParserWalker walker) { public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
hand.space = walker.getCurSpace(); hand.space = walker.getCurSpace();
hand.offset_space = null; hand.offset_space = null;
hand.offset_offset = walker.getN2addr().getOffset(); hand.offset_offset = walker.getN2addr().getOffset();
@ -48,21 +48,21 @@ public class Next2Symbol extends SpecificSymbol {
} }
@Override @Override
public String print(ParserWalker walker) throws MemoryAccessException { public String print(ParserWalker walker) throws MemoryAccessException {
long val = walker.getN2addr().getOffset(); long val = walker.getN2addr().getOffset();
return "0x"+Long.toHexString(val); return "0x" + Long.toHexString(val);
} }
@Override @Override
public void printList(ParserWalker walker, ArrayList<Object> list) { public void printList(ParserWalker walker, ArrayList<Object> list) {
list.add(walker.getParentHandle()); list.add(walker.getParentHandle());
} }
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) { public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
XmlElement element = parser.start("next2_sym"); // int element = decoder.openElement(ELEM_NEXT2_SYM);
patexp = new Next2InstructionValue(); patexp = new Next2InstructionValue();
parser.end(element); decoder.closeElement(ELEM_NEXT2_SYM.id());
} }
} }

View file

@ -19,21 +19,18 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import static ghidra.pcode.utils.SlaFormat.*;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.FixedHandle; import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.plugin.processors.sleigh.expression.OperandValue; import ghidra.app.plugin.processors.sleigh.expression.OperandValue;
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression; import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.program.model.pcode.Decoder;
import ghidra.xml.XmlElement; import ghidra.program.model.pcode.DecoderException;
import ghidra.xml.XmlPullParser;
/** /**
*
*
* Variable representing an operand to a specific Constructor * Variable representing an operand to a specific Constructor
*/ */
public class OperandSymbol extends SpecificSymbol { public class OperandSymbol extends SpecificSymbol {
@ -77,17 +74,11 @@ public class OperandSymbol extends SpecificSymbol {
return codeaddress; return codeaddress;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
*/
@Override @Override
public PatternExpression getPatternExpression() { public PatternExpression getPatternExpression() {
return localexp; return localexp;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public void getFixedHandle(FixedHandle hnd, ParserWalker walker) { public void getFixedHandle(FixedHandle hnd, ParserWalker walker) {
FixedHandle h = walker.getFixedHandle(hand); FixedHandle h = walker.getFixedHandle(hand);
@ -100,25 +91,26 @@ public class OperandSymbol extends SpecificSymbol {
hnd.temp_offset = h.temp_offset; hnd.temp_offset = h.temp_offset;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public String print(ParserWalker walker) throws MemoryAccessException { public String print(ParserWalker walker) throws MemoryAccessException {
String res; String res;
walker.pushOperand(hand); walker.pushOperand(hand);
if (triple != null) { if (triple != null) {
if (triple instanceof SubtableSymbol) if (triple instanceof SubtableSymbol) {
res = walker.getConstructor().print(walker); res = walker.getConstructor().print(walker);
else }
else {
res = triple.print(walker); res = triple.print(walker);
}
} }
else { // Must be expression resulting in a constant else { // Must be expression resulting in a constant
long val = defexp.getValue(walker); long val = defexp.getValue(walker);
if (val >= 0) if (val >= 0) {
res = "0x" + Long.toHexString(val); res = "0x" + Long.toHexString(val);
else }
else {
res = "-0x" + Long.toHexString(-val); res = "-0x" + Long.toHexString(-val);
}
} }
walker.popOperand(); walker.popOperand();
return res; return res;
@ -129,10 +121,12 @@ public class OperandSymbol extends SpecificSymbol {
throws MemoryAccessException { throws MemoryAccessException {
walker.pushOperand(hand); walker.pushOperand(hand);
if (triple != null) { if (triple != null) {
if (triple instanceof SubtableSymbol) if (triple instanceof SubtableSymbol) {
walker.getConstructor().printList(walker, list); walker.getConstructor().printList(walker, list);
else }
else {
triple.printList(walker, list); triple.printList(walker, list);
}
} }
else { else {
FixedHandle handle = walker.getParentHandle(); FixedHandle handle = walker.getParentHandle();
@ -144,32 +138,41 @@ public class OperandSymbol extends SpecificSymbol {
walker.popOperand(); walker.popOperand();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage lang) { public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
XmlElement el = parser.start("operand_sym"); // int el = decoder.openElement(ELEM_OPERAND_SYM);
defexp = null; defexp = null;
triple = null; triple = null;
codeaddress = false; codeaddress = false;
int attrib = decoder.getNextAttributeId();
hand = SpecXmlUtils.decodeInt(el.getAttribute("index")); while (attrib != 0) {
if (attrib == ATTRIB_INDEX.id()) {
reloffset = SpecXmlUtils.decodeInt(el.getAttribute("off")); hand = (int) decoder.readSignedInteger();
offsetbase = SpecXmlUtils.decodeInt(el.getAttribute("base")); }
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("minlen")); else if (attrib == ATTRIB_OFF.id()) {
String attrstr = el.getAttribute("subsym"); reloffset = (int) decoder.readSignedInteger();
if (attrstr != null) { }
int id = SpecXmlUtils.decodeInt(attrstr); else if (attrib == ATTRIB_BASE.id()) {
triple = (TripleSymbol) lang.getSymbolTable().findSymbol(id); offsetbase = (int) decoder.readSignedInteger();
}
else if (attrib == ATTRIB_MINLEN.id()) {
minimumlength = (int) decoder.readSignedInteger();
}
else if (attrib == ATTRIB_SUBSYM.id()) {
int id = (int) decoder.readUnsignedInteger();
triple = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
}
else if (attrib == ATTRIB_CODE.id()) {
codeaddress = decoder.readBool();
}
attrib = decoder.getNextAttributeId();
} }
codeaddress = SpecXmlUtils.decodeBoolean(el.getAttribute("code"));
localexp = (OperandValue) PatternExpression.restoreExpression(parser, lang); localexp = (OperandValue) PatternExpression.decodeExpression(decoder, lang);
if (!parser.peek().isEnd()) if (decoder.peekElement() != 0) {
defexp = PatternExpression.restoreExpression(parser, lang); defexp = PatternExpression.decodeExpression(decoder, lang);
parser.end(el); }
decoder.closeElement(ELEM_OPERAND_SYM.id());
} }
@Override @Override

View file

@ -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,63 +19,54 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import ghidra.app.plugin.processors.sleigh.*; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.expression.*;
import ghidra.program.model.mem.*;
import ghidra.xml.*;
import java.util.*; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.app.plugin.processors.sleigh.expression.StartInstructionValue;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* TripleSymbol with semantic value equal to offset of instruction's * TripleSymbol with semantic value equal to offset of instruction's
* current address * current address
*/ */
public class StartSymbol extends SpecificSymbol { public class StartSymbol extends SpecificSymbol {
private PatternExpression patexp; private PatternExpression patexp;
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
*/
@Override @Override
public PatternExpression getPatternExpression() { public PatternExpression getPatternExpression() {
return patexp; return patexp;
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public void getFixedHandle(FixedHandle hand, ParserWalker walker) { public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
hand.space = walker.getCurSpace(); hand.space = walker.getCurSpace();
hand.offset_space = null; hand.offset_space = null;
hand.offset_offset = walker.getAddr().getOffset(); hand.offset_offset = walker.getAddr().getOffset();
hand.size = hand.space.getPointerSize(); hand.size = hand.space.getPointerSize();
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public String print(ParserWalker walker) throws MemoryAccessException { public String print(ParserWalker walker) throws MemoryAccessException {
long val = walker.getAddr().getOffset(); long val = walker.getAddr().getOffset();
return "0x" + Long.toHexString(val); return "0x" + Long.toHexString(val);
} }
@Override @Override
public void printList(ParserWalker walker, ArrayList<Object> list) { public void printList(ParserWalker walker, ArrayList<Object> list) {
list.add(walker.getParentHandle()); list.add(walker.getParentHandle());
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) { public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
XmlElement element = parser.start("start_sym"); // int element = decoder.openElement(ELEM_START_SYM);
patexp = new StartInstructionValue(); patexp = new StartInstructionValue();
parser.end(element); decoder.closeElement(ELEM_START_SYM.id());
} }
} }

View file

@ -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,18 +19,18 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import ghidra.app.plugin.processors.sleigh.*; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.app.plugin.processors.sleigh.expression.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.mem.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
import java.util.*; import java.util.ArrayList;
import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* A collection of Constructors or a Symbol representing * A collection of Constructors or a Symbol representing
* one out of a family of Constructors, choosen based on InstructionContext * one out of a family of Constructors, choosen based on InstructionContext
*/ */
@ -40,67 +39,61 @@ public class SubtableSymbol extends TripleSymbol {
private Constructor[] construct; // All the constructors in this table private Constructor[] construct; // All the constructors in this table
private DecisionNode decisiontree; // The decision tree for this table private DecisionNode decisiontree; // The decision tree for this table
public DecisionNode getDecisionNode() { return decisiontree; } public DecisionNode getDecisionNode() {
return decisiontree;
/* (non-Javadoc) }
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#resolve(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
*/
@Override @Override
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException, UnknownInstructionException { public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
throws MemoryAccessException, UnknownInstructionException {
return decisiontree.resolve(walker, debug); return decisiontree.resolve(walker, debug);
} }
public int getNumConstructors() { return construct.length; } public int getNumConstructors() {
public Constructor getConstructor(int i) { return construct[i]; } return construct.length;
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
*/
@Override
public PatternExpression getPatternExpression() {
throw new SleighException("Cannot use subtable in expression");
} }
/* (non-Javadoc) public Constructor getConstructor(int i) {
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker) return construct[i];
*/
@Override
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
throw new SleighException("Cannot use subtable in expression");
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
*/
@Override @Override
public String print(ParserWalker walker) throws MemoryAccessException { public PatternExpression getPatternExpression() {
throw new SleighException("Cannot use subtable in expression"); throw new SleighException("Cannot use subtable in expression");
} }
@Override @Override
public void printList(ParserWalker walker, ArrayList<Object> list) { public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
throw new SleighException("Cannot use subtable in expression"); throw new SleighException("Cannot use subtable in expression");
} }
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
*/
@Override @Override
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) throws UnknownInstructionException { public String print(ParserWalker walker) throws MemoryAccessException {
XmlElement el = parser.start("subtable_sym"); throw new SleighException("Cannot use subtable in expression");
int numct = SpecXmlUtils.decodeInt(el.getAttribute("numct")); }
@Override
public void printList(ParserWalker walker, ArrayList<Object> list) {
throw new SleighException("Cannot use subtable in expression");
}
@Override
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
// int el = decoder.openElement(ELEM_SUBTABLE_SYM);
int numct = (int) decoder.readSignedInteger(ATTRIB_NUMCT);
construct = new Constructor[numct]; // Array must be built construct = new Constructor[numct]; // Array must be built
// before restoring constructors // before restoring constructors
for(int i=0;i<numct;++i) { for (int i = 0; i < numct; ++i) {
Constructor ct = new Constructor(); Constructor ct = new Constructor();
ct.setId(i); ct.setId(i);
construct[i] = ct; construct[i] = ct;
ct.restoreXml(parser,sleigh); ct.decode(decoder, sleigh);
} }
if (!parser.peek().isEnd()) { if (decoder.peekElement() != 0) {
decisiontree = new DecisionNode(); decisiontree = new DecisionNode();
decisiontree.restoreXml(parser,null,this); decisiontree.decode(decoder, null, this);
} }
parser.end(el); decoder.closeElement(ELEM_SUBTABLE_SYM.id());
} }
} }

View file

@ -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,32 +19,39 @@
*/ */
package ghidra.app.plugin.processors.sleigh.symbol; package ghidra.app.plugin.processors.sleigh.symbol;
import ghidra.app.plugin.processors.sleigh.*; import static ghidra.pcode.utils.SlaFormat.*;
import ghidra.program.model.lang.*;
import ghidra.util.xml.*; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.xml.*; import ghidra.program.model.pcode.Decoder;
import ghidra.program.model.pcode.DecoderException;
/** /**
*
*
* Base class for symbols in sleigh * Base class for symbols in sleigh
*/ */
public abstract class Symbol { public abstract class Symbol {
private String name; private String name;
private int id; // Unique id across all symbols private int id; // Unique id across all symbols
private int scopeid; // id of scope this symbol is in private int scopeid; // id of scope this symbol is in
public String getName() { return name; } public String getName() {
public int getId() { return id; } return name;
public int getScopeId() { return scopeid; }
public void restoreHeaderXml(XmlPullParser parser) {
XmlElement el = parser.start();
name = el.getAttribute("name");
id = SpecXmlUtils.decodeInt(el.getAttribute("id"));
scopeid = SpecXmlUtils.decodeInt(el.getAttribute("scope"));
parser.end(el);
} }
public abstract void restoreXml(XmlPullParser parser,SleighLanguage sleigh) throws UnknownInstructionException; // Always overridden by subclass public int getId() {
return id;
}
public int getScopeId() {
return scopeid;
}
public void decodeHeader(Decoder decoder) throws DecoderException {
int el = decoder.openElement();
name = decoder.readString(ATTRIB_NAME);
id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
scopeid = (int) decoder.readUnsignedInteger(ATTRIB_SCOPE);
decoder.closeElement(el);
}
public abstract void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException;
} }

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