mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-08 21:47:59 -05:00
GP-4285 Compressed SLEIGH
This commit is contained in:
@@ -0,0 +1 @@
|
||||
MODULE FILE LICENSE: src/decompile/zlib zlib License
|
||||
|
||||
@@ -26,7 +26,6 @@ if (findProject(':Generic') == null) {
|
||||
* Define the "native build model" for building the decompiler executables.
|
||||
*/
|
||||
model {
|
||||
|
||||
// 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 same directory with other files that are not used by the decompiler.
|
||||
@@ -174,6 +173,8 @@ model {
|
||||
include "slghpattern.cc"
|
||||
include "semantics.cc"
|
||||
include "context.cc"
|
||||
include "slaformat.cc"
|
||||
include "compression.cc"
|
||||
include "filemanage.cc"
|
||||
include "slgh_compile.cc"
|
||||
|
||||
@@ -188,7 +189,27 @@ model {
|
||||
srcDir "src/decompile/cpp"
|
||||
}
|
||||
} // end cpp
|
||||
|
||||
if (isCurrentWindows()) {
|
||||
c {
|
||||
source {
|
||||
srcDir "src/decompile/zlib"
|
||||
include "*.c"
|
||||
}
|
||||
}
|
||||
}
|
||||
} // 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 components
|
||||
@@ -223,7 +244,15 @@ model {
|
||||
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) {
|
||||
b.cppCompiler.args "-std=c++11"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
##MODULE IP: Modified Nuvola Icons - LGPL 2.1
|
||||
##MODULE IP: Oxygen Icons - LGPL 3.0
|
||||
##MODULE IP: Tango Icons - Public Domain
|
||||
##MODULE IP: zlib License
|
||||
Module.manifest||GHIDRA||||END|
|
||||
data/decompiler.theme.properties||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/varcross.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/cspec.xml||GHIDRA||||END|
|
||||
src/main/doc/cspec_html.xsl||GHIDRA||||END|
|
||||
|
||||
@@ -50,9 +50,9 @@ YACC=bison
|
||||
# libraries
|
||||
#INCLUDES=-I$(BFDHOME)/include
|
||||
INCLUDES=
|
||||
BFDLIB=-lbfd -lz
|
||||
BFDLIB=-lbfd
|
||||
|
||||
LNK=
|
||||
LNK=-lz
|
||||
|
||||
# Source files
|
||||
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)
|
||||
# Files used for any project that use the sleigh decoder
|
||||
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
|
||||
GHIDRA= ghidra_arch inject_ghidra ghidra_translate loadimage_ghidra \
|
||||
typegrp_ghidra database_ghidra ghidra_context cpool_ghidra \
|
||||
@@ -260,10 +260,10 @@ test: ghidra_test_dbg
|
||||
./ghidra_test_dbg
|
||||
|
||||
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)
|
||||
$(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)
|
||||
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o sleigh_dbg $(SLEIGH_DBG_OBJS) $(LNK)
|
||||
|
||||
@@ -98,10 +98,10 @@ public:
|
||||
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
|
||||
|
||||
/// Restore an address from parsed XML
|
||||
/// Decode an address from a stream
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -221,7 +221,7 @@ class RangeProperties {
|
||||
bool seenLast; ///< End of the range is actively specified
|
||||
public:
|
||||
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
|
||||
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function
|
||||
void setPrintLanguage(const string &nm); ///< Establish a particular output language
|
||||
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
|
||||
|
||||
/// \brief Get a string describing \b this architecture
|
||||
|
||||
@@ -132,7 +132,7 @@ private:
|
||||
// the result of the condition being false
|
||||
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 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 halfDeleteOutEdge(int4 slot); ///< Delete the \e out half of an edge, correcting indices
|
||||
void removeInEdge(int4 slot); ///< Remove an incoming edge
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
int4 getUniq(void) const { return uniq; } ///< Get the sub-sorting index
|
||||
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 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 string decodeCommentType(uint4 val); ///< Convert comment property to string
|
||||
};
|
||||
@@ -146,7 +146,7 @@ public:
|
||||
/// \param encoder is the stream encoder
|
||||
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
|
||||
virtual void decode(Decoder &decoder)=0;
|
||||
|
||||
165
Ghidra/Features/Decompiler/src/decompile/cpp/compression.cc
Normal file
165
Ghidra/Features/Decompiler/src/decompile/cpp/compression.cc
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
100
Ghidra/Features/Decompiler/src/decompile/cpp/compression.hh
Normal file
100
Ghidra/Features/Decompiler/src/decompile/cpp/compression.hh
Normal 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
|
||||
@@ -628,66 +628,4 @@ uintb FloatFormat::opRound(uintb a) const
|
||||
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
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef __FLOAT_HH__
|
||||
#define __FLOAT_HH__
|
||||
|
||||
#include "xml.hh"
|
||||
#include "error.hh"
|
||||
|
||||
namespace ghidra {
|
||||
|
||||
@@ -61,7 +61,6 @@ private:
|
||||
uintb getNaNEncoding(bool sgn) const; ///< Get an encoded NaN value
|
||||
void calcPrecision(void); ///< Calculate the decimal precision of this format
|
||||
public:
|
||||
FloatFormat(void) {} ///< Construct for use with restoreXml()
|
||||
FloatFormat(int4 sz); ///< Construct default IEEE 754 standard settings
|
||||
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
|
||||
@@ -93,9 +92,6 @@ public:
|
||||
uintb opRound(uintb a) const; ///< Round
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -1959,7 +1959,7 @@ const string FspecSpace::NAME = "fspec";
|
||||
/// \param t is the associated processor translator
|
||||
/// \param ind is the index associated with the space
|
||||
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);
|
||||
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)
|
||||
|
||||
{
|
||||
|
||||
@@ -345,7 +345,6 @@ public:
|
||||
virtual void encodeAttributes(Encoder &encoder,uintb offset) const;
|
||||
virtual void encodeAttributes(Encoder &encoder,uintb offset,int4 size) const;
|
||||
virtual void printRaw(ostream &s,uintb offset) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
static const string NAME; ///< Reserved name for the fspec space
|
||||
};
|
||||
|
||||
@@ -197,7 +197,7 @@ public:
|
||||
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 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 decodeJumpTable(Decoder &decoder); ///< Decode jump-tables from a stream
|
||||
void encodeTree(Encoder &encoder) const; ///< Encode a description of the p-code tree to stream
|
||||
|
||||
@@ -321,7 +321,7 @@ void IfcOption::execute(istream &s)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
catch(ParseError &err) {
|
||||
|
||||
@@ -91,7 +91,8 @@ void InjectPayloadSleigh::decode(Decoder &decoder)
|
||||
void InjectPayloadSleigh::printTemplate(ostream &s) const
|
||||
|
||||
{
|
||||
tpl->saveXml(s,-1);
|
||||
XmlEncode encoder(s);
|
||||
tpl->encode(encoder,-1);
|
||||
}
|
||||
|
||||
void InjectPayloadSleigh::checkParameterRestrictions(InjectContextSleigh &con,
|
||||
@@ -247,7 +248,8 @@ void ExecutablePcodeSleigh::decode(Decoder &decoder)
|
||||
void ExecutablePcodeSleigh::printTemplate(ostream &s) const
|
||||
|
||||
{
|
||||
tpl->saveXml(s,-1);
|
||||
XmlEncode encoder(s);
|
||||
tpl->encode(encoder,-1);
|
||||
}
|
||||
|
||||
InjectPayloadDynamic::~InjectPayloadDynamic(void)
|
||||
|
||||
@@ -24,6 +24,9 @@ unordered_map<string,uint4> AttributeId::lookupAttributeId;
|
||||
|
||||
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
|
||||
/// The list itself is created once on the first call to this method.
|
||||
/// \return a reference to the vector
|
||||
@@ -38,11 +41,13 @@ vector<AttributeId *> &AttributeId::getList(void)
|
||||
/// in the global hashtable.
|
||||
/// \param nm is the name of 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)
|
||||
{
|
||||
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
|
||||
@@ -78,11 +83,13 @@ vector<ElementId *> &ElementId::getList(void)
|
||||
/// in the global hashtable.
|
||||
/// \param nm is the name of 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)
|
||||
{
|
||||
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
|
||||
@@ -132,7 +139,7 @@ uint4 XmlDecode::peekElement(void)
|
||||
return 0;
|
||||
el = *iter;
|
||||
}
|
||||
return ElementId::find(el->getName());
|
||||
return ElementId::find(el->getName(),scope);
|
||||
}
|
||||
|
||||
uint4 XmlDecode::openElement(void)
|
||||
@@ -156,7 +163,7 @@ uint4 XmlDecode::openElement(void)
|
||||
elStack.push_back(el);
|
||||
iterStack.push_back(el->getChildren().begin());
|
||||
attributeIndex = -1;
|
||||
return ElementId::find(el->getName());
|
||||
return ElementId::find(el->getName(),scope);
|
||||
}
|
||||
|
||||
uint4 XmlDecode::openElement(const ElementId &elemId)
|
||||
@@ -194,7 +201,7 @@ void XmlDecode::closeElement(uint4 id)
|
||||
const Element *el = elStack.back();
|
||||
if (iterStack.back() != el->getChildren().end())
|
||||
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");
|
||||
#endif
|
||||
elStack.pop_back();
|
||||
@@ -207,7 +214,7 @@ void XmlDecode::closeElementSkipping(uint4 id)
|
||||
{
|
||||
#ifdef CPUI_DEBUG
|
||||
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");
|
||||
#endif
|
||||
elStack.pop_back();
|
||||
@@ -228,7 +235,7 @@ uint4 XmlDecode::getNextAttributeId(void)
|
||||
int4 nextIndex = attributeIndex + 1;
|
||||
if (nextIndex < el->getNumAttributes()) {
|
||||
attributeIndex = nextIndex;
|
||||
return AttributeId::find(el->getAttributeName(attributeIndex));
|
||||
return AttributeId::find(el->getAttributeName(attributeIndex),scope);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -419,40 +426,89 @@ AddrSpace *XmlDecode::readSpace(const AttributeId &attribId)
|
||||
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)
|
||||
|
||||
{
|
||||
if (elementTagIsOpen)
|
||||
if (tagStatus == tag_start)
|
||||
outStream << '>';
|
||||
else
|
||||
elementTagIsOpen = true;
|
||||
tagStatus = tag_start;
|
||||
newLine();
|
||||
outStream << '<' << elemId.getName();
|
||||
depth += 1;
|
||||
}
|
||||
|
||||
void XmlEncode::closeElement(const ElementId &elemId)
|
||||
|
||||
{
|
||||
if (elementTagIsOpen) {
|
||||
depth -= 1;
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << "/>";
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
else {
|
||||
outStream << "</" << elemId.getName() << '>';
|
||||
tagStatus = tag_stop;
|
||||
return;
|
||||
}
|
||||
if (tagStatus != tag_content)
|
||||
newLine();
|
||||
else
|
||||
tagStatus = tag_stop;
|
||||
|
||||
outStream << "</" << elemId.getName() << '>';
|
||||
}
|
||||
|
||||
void XmlEncode::writeBool(const AttributeId &attribId,bool val)
|
||||
|
||||
{
|
||||
if (attribId == ATTRIB_CONTENT) { // Special id indicating, text value
|
||||
if (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
if (val)
|
||||
outStream << "true";
|
||||
else
|
||||
outStream << "false";
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
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 (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
outStream << dec << val;
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
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 (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
outStream << hex << "0x" << val;
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
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 (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
xml_escape(outStream, val.c_str());
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
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 (elementTagIsOpen) {
|
||||
if (tagStatus == tag_start) {
|
||||
outStream << '>';
|
||||
elementTagIsOpen = false;
|
||||
}
|
||||
xml_escape(outStream, spc->getName().c_str());
|
||||
tagStatus = tag_content;
|
||||
return;
|
||||
}
|
||||
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 decode from the \e current position, and the position is advanced.
|
||||
/// \param len is the number of bytes to extract
|
||||
@@ -598,6 +671,27 @@ void PackedDecode::skipAttributeRemaining(uint1 typeByte)
|
||||
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)
|
||||
|
||||
{
|
||||
@@ -612,25 +706,11 @@ void PackedDecode::ingestStream(istream &s)
|
||||
{
|
||||
int4 gcount = 0;
|
||||
while(s.peek() > 0) {
|
||||
uint1 *buf = new uint1[BUFFER_SIZE + 1];
|
||||
inStream.emplace_back(buf,buf+BUFFER_SIZE);
|
||||
uint1 *buf = allocateNextInputBuffer(1);
|
||||
s.get((char *)buf,BUFFER_SIZE+1,'\0');
|
||||
gcount = s.gcount();
|
||||
}
|
||||
endPos.seqIter = inStream.begin();
|
||||
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;
|
||||
}
|
||||
endIngest(gcount);
|
||||
}
|
||||
|
||||
uint4 PackedDecode::peekElement(void)
|
||||
@@ -959,6 +1039,24 @@ AddrSpace *PackedDecode::readSpace(const AttributeId &attribId)
|
||||
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.
|
||||
/// 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.
|
||||
@@ -973,7 +1071,7 @@ void PackedEncode::writeInteger(uint1 typeByte,uint8 val)
|
||||
lenCode = 0;
|
||||
sa = -1;
|
||||
}
|
||||
if (val < 0x800000000) {
|
||||
else if (val < 0x800000000) {
|
||||
if (val < 0x200000) {
|
||||
if (val < 0x80) {
|
||||
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
|
||||
AttributeId ATTRIB_CONTENT = AttributeId("XMLcontent",1);
|
||||
AttributeId ATTRIB_ALIGN = AttributeId("align",2);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define __MARSHAL_HH__
|
||||
|
||||
#include "xml.hh"
|
||||
#include "opcodes.hh"
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -43,11 +44,11 @@ class AttributeId {
|
||||
string name; ///< The name of the attribute
|
||||
uint4 id; ///< The (internal) id of the attribute
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
@@ -67,11 +68,11 @@ class ElementId {
|
||||
string name; ///< The name of the element
|
||||
uint4 id; ///< The (internal) id of the attribute
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
@@ -269,6 +270,21 @@ public:
|
||||
/// \return the address space associated with the attribute
|
||||
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
|
||||
///
|
||||
/// 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 spc is the address space to encode
|
||||
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
|
||||
@@ -363,12 +386,13 @@ class XmlDecode : public Decoder {
|
||||
vector<const Element *> elStack; ///< Stack of currently \e open elements
|
||||
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 scope; ///< Scope of element/attribute tags to look up
|
||||
int4 findMatchingAttribute(const Element *el,const string &attribName);
|
||||
public:
|
||||
XmlDecode(const AddrSpaceManager *spc,const Element *root) : Decoder(spc) {
|
||||
document = (Document *)0; rootElement = root; attributeIndex = -1; } ///< Constructor with preparsed root
|
||||
XmlDecode(const AddrSpaceManager *spc) : Decoder(spc) {
|
||||
document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream
|
||||
XmlDecode(const AddrSpaceManager *spc,const Element *root,int4 sc=0) : Decoder(spc) {
|
||||
document = (Document *)0; rootElement = root; attributeIndex = -1; scope = sc; } ///< Constructor with preparsed root
|
||||
XmlDecode(const AddrSpaceManager *spc,int4 sc=0) : Decoder(spc) {
|
||||
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
|
||||
virtual ~XmlDecode(void);
|
||||
virtual void ingestStream(istream &s);
|
||||
@@ -392,6 +416,8 @@ public:
|
||||
virtual string readString(const AttributeId &attribId);
|
||||
virtual AddrSpace *readSpace(void);
|
||||
virtual AddrSpace *readSpace(const AttributeId &attribId);
|
||||
virtual OpCode readOpcode(void);
|
||||
virtual OpCode readOpcode(AttributeId &attribId);
|
||||
};
|
||||
|
||||
/// \brief An XML based encoder
|
||||
@@ -400,10 +426,20 @@ public:
|
||||
/// receive the XML document as calls are made on the encoder.
|
||||
class XmlEncode : public Encoder {
|
||||
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
|
||||
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:
|
||||
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 closeElement(const ElementId &elemId);
|
||||
virtual void writeBool(const AttributeId &attribId,bool val);
|
||||
@@ -412,6 +448,7 @@ public:
|
||||
virtual void writeString(const AttributeId &attribId,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 writeOpcode(const AttributeId &attribId,OpCode opc);
|
||||
};
|
||||
|
||||
/// \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 skipAttribute(void); ///< Skip over the attribute at the current position
|
||||
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:
|
||||
PackedDecode(const AddrSpaceManager *spcManager) : Decoder(spcManager) {} ///< Constructor
|
||||
virtual ~PackedDecode(void);
|
||||
@@ -529,6 +569,8 @@ public:
|
||||
virtual string readString(const AttributeId &attribId);
|
||||
virtual AddrSpace *readSpace(void);
|
||||
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
|
||||
@@ -548,6 +590,7 @@ public:
|
||||
virtual void writeString(const AttributeId &attribId,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 writeOpcode(const AttributeId &attribId,OpCode opc);
|
||||
};
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// 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 id is the id associated with the element or attribute
|
||||
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_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.
|
||||
/// \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
|
||||
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 (iter != lookupAttributeId.end())
|
||||
return (*iter).second;
|
||||
if (scope == 0) { // Current only support reverse look up for scope 0
|
||||
unordered_map<string,uint4>::const_iterator iter = lookupAttributeId.find(nm);
|
||||
if (iter != lookupAttributeId.end())
|
||||
return (*iter).second;
|
||||
}
|
||||
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.
|
||||
/// \param nm is the name of the element
|
||||
/// \param scope is the id of the scope in which to search
|
||||
/// \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 (iter != lookupElementId.end())
|
||||
return (*iter).second;
|
||||
if (scope == 0) {
|
||||
unordered_map<string,uint4>::const_iterator iter = lookupElementId.find(nm);
|
||||
if (iter != lookupElementId.end())
|
||||
return (*iter).second;
|
||||
}
|
||||
return ELEM_UNKNOWN.id;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ const string IopSpace::NAME = "iop";
|
||||
/// \param t is the associated processor translator
|
||||
/// \param ind is the associated index
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void IopSpace::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
throw LowlevelError("Should never encode iop space to stream");
|
||||
}
|
||||
|
||||
void IopSpace::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
|
||||
@@ -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,int4 size) const { encoder.writeString(ATTRIB_SPACE, "iop"); }
|
||||
virtual void printRaw(ostream &s,uintb offset) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
static const string NAME; ///< Reserved name for the iop space
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ bool ArchOption::onOrOff(const string &p)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -290,39 +290,6 @@ void ConstTpl::transfer(const vector<HandleTpl *> ¶ms)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
{
|
||||
@@ -330,120 +297,129 @@ void ConstTpl::changeHandleIndex(const vector<int4> &handmap)
|
||||
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) {
|
||||
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;
|
||||
case handle:
|
||||
s << "handle\" val=\"" << dec << value.handle_index << "\" ";
|
||||
s << "s=\"";
|
||||
printHandleSelector(s,select);
|
||||
s << "\"";
|
||||
encoder.openElement(sla::ELEM_CONST_HANDLE);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_VAL, value.handle_index);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_S, select);
|
||||
if (select == v_offset_plus)
|
||||
s << " plus=\"0x" << hex << value_real << "\"";
|
||||
s << "/>";
|
||||
encoder.writeUnsignedInteger(sla::ATTRIB_PLUS, value_real);
|
||||
encoder.closeElement(sla::ELEM_CONST_HANDLE);
|
||||
break;
|
||||
case j_start:
|
||||
s << "start\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_START);
|
||||
encoder.closeElement(sla::ELEM_CONST_START);
|
||||
break;
|
||||
case j_next:
|
||||
s << "next\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_NEXT);
|
||||
encoder.closeElement(sla::ELEM_CONST_NEXT);
|
||||
break;
|
||||
case j_next2:
|
||||
s << "next2\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_NEXT2);
|
||||
encoder.closeElement(sla::ELEM_CONST_NEXT2);
|
||||
break;
|
||||
case j_curspace:
|
||||
s << "curspace\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_CURSPACE);
|
||||
encoder.closeElement(sla::ELEM_CONST_CURSPACE);
|
||||
break;
|
||||
case j_curspace_size:
|
||||
s << "curspace_size\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_CURSPACE_SIZE);
|
||||
encoder.closeElement(sla::ELEM_CONST_CURSPACE_SIZE);
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
case j_flowref:
|
||||
s << "flowref\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_FLOWREF);
|
||||
encoder.closeElement(sla::ELEM_CONST_FLOWREF);
|
||||
break;
|
||||
case j_flowref_size:
|
||||
s << "flowref_size\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_FLOWREF_SIZE);
|
||||
encoder.closeElement(sla::ELEM_CONST_FLOWREF_SIZE);
|
||||
break;
|
||||
case j_flowdest:
|
||||
s << "flowdest\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_FLOWDEST);
|
||||
encoder.closeElement(sla::ELEM_CONST_FLOWDEST);
|
||||
break;
|
||||
case j_flowdest_size:
|
||||
s << "flowdest_size\"/>";
|
||||
encoder.openElement(sla::ELEM_CONST_FLOWDEST_SIZE);
|
||||
encoder.closeElement(sla::ELEM_CONST_FLOWDEST_SIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ConstTpl::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
||||
void ConstTpl::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
const string &typestring(el->getAttributeValue("type"));
|
||||
if (typestring == "real") {
|
||||
uint4 el = decoder.openElement();
|
||||
if (el == sla::ELEM_CONST_REAL) {
|
||||
type = real;
|
||||
istringstream s(el->getAttributeValue("val"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> value_real;
|
||||
value_real = decoder.readUnsignedInteger(sla::ATTRIB_VAL);
|
||||
}
|
||||
else if (typestring=="handle") {
|
||||
else if (el == sla::ELEM_CONST_HANDLE) {
|
||||
type = handle;
|
||||
istringstream s(el->getAttributeValue("val"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> value.handle_index;
|
||||
select = readHandleSelector(el->getAttributeValue("s"));
|
||||
value.handle_index = decoder.readSignedInteger(sla::ATTRIB_VAL);
|
||||
uint4 selectInt = decoder.readSignedInteger(sla::ATTRIB_S);
|
||||
if (selectInt > v_offset_plus)
|
||||
throw DecoderError("Bad handle selector encoding");
|
||||
select = (v_field)selectInt;
|
||||
if (select == v_offset_plus) {
|
||||
istringstream s2(el->getAttributeValue("plus"));
|
||||
s2.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s2 >> value_real;
|
||||
value_real = decoder.readUnsignedInteger(sla::ATTRIB_PLUS);
|
||||
}
|
||||
}
|
||||
else if (typestring=="start") {
|
||||
else if (el == sla::ELEM_CONST_START) {
|
||||
type = j_start;
|
||||
}
|
||||
else if (typestring=="next") {
|
||||
else if (el == sla::ELEM_CONST_NEXT) {
|
||||
type = j_next;
|
||||
}
|
||||
else if (typestring=="next2") {
|
||||
else if (el == sla::ELEM_CONST_NEXT2) {
|
||||
type = j_next2;
|
||||
}
|
||||
else if (typestring=="curspace") {
|
||||
else if (el == sla::ELEM_CONST_CURSPACE) {
|
||||
type = j_curspace;
|
||||
}
|
||||
else if (typestring=="curspace_size") {
|
||||
else if (el == sla::ELEM_CONST_CURSPACE_SIZE) {
|
||||
type = j_curspace_size;
|
||||
}
|
||||
else if (typestring=="spaceid") {
|
||||
else if (el == sla::ELEM_CONST_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;
|
||||
istringstream s(el->getAttributeValue("val"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> value_real;
|
||||
value_real = decoder.readUnsignedInteger(sla::ATTRIB_VAL);
|
||||
}
|
||||
else if (typestring == "flowref") {
|
||||
else if (el == sla::ELEM_CONST_FLOWREF) {
|
||||
type = j_flowref;
|
||||
}
|
||||
else if (typestring == "flowref_size") {
|
||||
else if (el == sla::ELEM_CONST_FLOWREF_SIZE) {
|
||||
type = j_flowref_size;
|
||||
}
|
||||
else if (typestring == "flowdest") {
|
||||
else if (el == sla::ELEM_CONST_FLOWDEST) {
|
||||
type = j_flowdest;
|
||||
}
|
||||
else if (typestring == "flowdest_size") {
|
||||
else if (el == sla::ELEM_CONST_FLOWDEST_SIZE) {
|
||||
type = j_flowdest_size;
|
||||
}
|
||||
else
|
||||
throw LowlevelError("Bad constant type");
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
VarnodeTpl::VarnodeTpl(int4 hand,bool zerosize) :
|
||||
@@ -544,27 +520,24 @@ bool VarnodeTpl::adjustTruncation(int4 sz,bool isbigendian)
|
||||
return true;
|
||||
}
|
||||
|
||||
void VarnodeTpl::saveXml(ostream &s) const
|
||||
void VarnodeTpl::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<varnode_tpl>";
|
||||
space.saveXml(s);
|
||||
offset.saveXml(s);
|
||||
size.saveXml(s);
|
||||
s << "</varnode_tpl>\n";
|
||||
encoder.openElement(sla::ELEM_VARNODE_TPL);
|
||||
space.encode(encoder);
|
||||
offset.encode(encoder);
|
||||
size.encode(encoder);
|
||||
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());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
space.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
offset.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
size.restoreXml(*iter,manage);
|
||||
uint4 el = decoder.openElement(sla::ELEM_VARNODE_TPL);
|
||||
space.decode(decoder);
|
||||
offset.decode(decoder);
|
||||
size.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
bool VarnodeTpl::operator<(const VarnodeTpl &op2) const
|
||||
@@ -633,39 +606,32 @@ void HandleTpl::changeHandleIndex(const vector<int4> &handmap)
|
||||
temp_offset.changeHandleIndex(handmap);
|
||||
}
|
||||
|
||||
void HandleTpl::saveXml(ostream &s) const
|
||||
void HandleTpl::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<handle_tpl>";
|
||||
space.saveXml(s);
|
||||
size.saveXml(s);
|
||||
ptrspace.saveXml(s);
|
||||
ptroffset.saveXml(s);
|
||||
ptrsize.saveXml(s);
|
||||
temp_space.saveXml(s);
|
||||
temp_offset.saveXml(s);
|
||||
s << "</handle_tpl>\n";
|
||||
encoder.openElement(sla::ELEM_HANDLE_TPL);
|
||||
space.encode(encoder);
|
||||
size.encode(encoder);
|
||||
ptrspace.encode(encoder);
|
||||
ptroffset.encode(encoder);
|
||||
ptrsize.encode(encoder);
|
||||
temp_space.encode(encoder);
|
||||
temp_offset.encode(encoder);
|
||||
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());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
space.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
size.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
ptrspace.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
ptroffset.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
ptrsize.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
temp_space.restoreXml(*iter,manage);
|
||||
++iter;
|
||||
temp_offset.restoreXml(*iter,manage);
|
||||
uint4 el = decoder.openElement(sla::ELEM_HANDLE_TPL);
|
||||
space.decode(decoder);
|
||||
size.decode(decoder);
|
||||
ptrspace.decode(decoder);
|
||||
ptroffset.decode(decoder);
|
||||
ptrsize.decode(decoder);
|
||||
temp_space.decode(decoder);
|
||||
temp_offset.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
OpTpl::~OpTpl(void)
|
||||
@@ -710,39 +676,43 @@ void OpTpl::changeHandleIndex(const vector<int4> &handmap)
|
||||
(*iter)->changeHandleIndex(handmap);
|
||||
}
|
||||
|
||||
void OpTpl::saveXml(ostream &s) const
|
||||
void OpTpl::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<op_tpl code=\"" << get_opname(opc) << "\">";
|
||||
if (output == (VarnodeTpl *)0)
|
||||
s << "<null/>\n";
|
||||
encoder.openElement(sla::ELEM_OP_TPL);
|
||||
encoder.writeOpcode(sla::ATTRIB_CODE, opc);
|
||||
if (output == (VarnodeTpl *)0) {
|
||||
encoder.openElement(sla::ELEM_NULL);
|
||||
encoder.closeElement(sla::ELEM_NULL);
|
||||
}
|
||||
else
|
||||
output->saveXml(s);
|
||||
output->encode(encoder);
|
||||
for(int4 i=0;i<input.size();++i)
|
||||
input[i]->saveXml(s);
|
||||
s << "</op_tpl>\n";
|
||||
input[i]->encode(encoder);
|
||||
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"));
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
if ((*iter)->getName() == "null")
|
||||
uint4 el = decoder.openElement(sla::ELEM_OP_TPL);
|
||||
opc = decoder.readOpcode(sla::ATTRIB_CODE);
|
||||
uint4 subel = decoder.peekElement();
|
||||
if (subel == sla::ELEM_NULL) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(subel);
|
||||
output = (VarnodeTpl *)0;
|
||||
}
|
||||
else {
|
||||
output = new VarnodeTpl();
|
||||
output->restoreXml(*iter,manage);
|
||||
output->decode(decoder);
|
||||
}
|
||||
++iter;
|
||||
while(iter != list.end()) {
|
||||
while(decoder.peekElement() != 0) {
|
||||
VarnodeTpl *vn = new VarnodeTpl();
|
||||
vn->restoreXml(*iter,manage);
|
||||
vn->decode(decoder);
|
||||
input.push_back(vn);
|
||||
++iter;
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
ConstructTpl::~ConstructTpl(void)
|
||||
@@ -882,63 +852,61 @@ void ConstructTpl::deleteOps(const vector<int4> &indices)
|
||||
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 )
|
||||
s << " section=\"" << dec << sectionid << "\"";
|
||||
encoder.writeSignedInteger(sla::ATTRIB_SECTION, sectionid);
|
||||
if (delayslot != 0)
|
||||
s << " delay=\"" << dec << delayslot << "\"";
|
||||
encoder.writeSignedInteger(sla::ATTRIB_DELAY, delayslot);
|
||||
if (numlabels != 0)
|
||||
s << " labels=\"" << dec << numlabels << "\"";
|
||||
s << ">\n";
|
||||
encoder.writeSignedInteger(sla::ATTRIB_LABELS, numlabels);
|
||||
if (result != (HandleTpl *)0)
|
||||
result->saveXml(s);
|
||||
else
|
||||
s << "<null/>";
|
||||
result->encode(encoder);
|
||||
else {
|
||||
encoder.openElement(sla::ELEM_NULL);
|
||||
encoder.closeElement(sla::ELEM_NULL);
|
||||
}
|
||||
for(int4 i=0;i<vec.size();++i)
|
||||
vec[i]->saveXml(s);
|
||||
s << "</construct_tpl>\n";
|
||||
vec[i]->encode(encoder);
|
||||
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;
|
||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
||||
if (el->getAttributeName(i)=="delay") {
|
||||
istringstream s(el->getAttributeValue(i));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> delayslot;
|
||||
uint4 attrib = decoder.getNextAttributeId();
|
||||
while(attrib != 0) {
|
||||
if (attrib == sla::ATTRIB_DELAY) {
|
||||
delayslot = decoder.readSignedInteger();
|
||||
}
|
||||
else if (el->getAttributeName(i)=="labels") {
|
||||
istringstream s(el->getAttributeValue(i));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> numlabels;
|
||||
else if (attrib == sla::ATTRIB_LABELS) {
|
||||
numlabels = decoder.readSignedInteger();
|
||||
}
|
||||
else if (el->getAttributeName(i)=="section") {
|
||||
istringstream s(el->getAttributeValue(i));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> sectionid;
|
||||
else if (attrib == sla::ATTRIB_SECTION) {
|
||||
sectionid = decoder.readSignedInteger();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
if ((*iter)->getName() == "null")
|
||||
uint4 subel = decoder.peekElement();
|
||||
if (subel == sla::ELEM_NULL) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(subel);
|
||||
result = (HandleTpl *)0;
|
||||
}
|
||||
else {
|
||||
result = new HandleTpl();
|
||||
result->restoreXml(*iter,manage);
|
||||
result->decode(decoder);
|
||||
}
|
||||
++iter;
|
||||
while(iter != list.end()) {
|
||||
while(decoder.peekElement() != 0) {
|
||||
OpTpl *op = new OpTpl();
|
||||
op->restoreXml(*iter,manage);
|
||||
op->decode(decoder);
|
||||
vec.push_back(op);
|
||||
++iter;
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
return sectionid;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define __SEMANTICS_HH__
|
||||
|
||||
#include "context.hh"
|
||||
#include "slaformat.hh"
|
||||
|
||||
namespace ghidra {
|
||||
|
||||
@@ -45,8 +46,6 @@ private:
|
||||
} value;
|
||||
uintb value_real;
|
||||
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:
|
||||
ConstTpl(void) { type = real; value_real = 0; }
|
||||
ConstTpl(const ConstTpl &op2) {
|
||||
@@ -72,8 +71,8 @@ public:
|
||||
void changeHandleIndex(const vector<int4> &handmap);
|
||||
void fillinSpace(FixedHandle &hand,const ParserWalker &walker) const;
|
||||
void fillinOffset(FixedHandle &hand,const ParserWalker &walker) const;
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class VarnodeTpl {
|
||||
@@ -102,8 +101,8 @@ public:
|
||||
bool isRelative(void) const { return (offset.getType() == ConstTpl::j_relative); }
|
||||
void changeHandleIndex(const vector<int4> &handmap);
|
||||
bool adjustTruncation(int4 sz,bool isbigendian);
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class HandleTpl {
|
||||
@@ -132,8 +131,8 @@ public:
|
||||
void setTempOffset(uintb val) { temp_offset = ConstTpl(ConstTpl::real,val); }
|
||||
void fix(FixedHandle &hand,const ParserWalker &walker) const;
|
||||
void changeHandleIndex(const vector<int4> &handmap);
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class OpTpl {
|
||||
@@ -156,8 +155,8 @@ public:
|
||||
void setInput(VarnodeTpl *vt,int4 slot) { input[slot] = vt; }
|
||||
void removeInput(int4 index);
|
||||
void changeHandleIndex(const vector<int4> &handmap);
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class ConstructTpl {
|
||||
@@ -185,8 +184,8 @@ public:
|
||||
void setInput(VarnodeTpl *vn,int4 index,int4 slot);
|
||||
void setOutput(VarnodeTpl *vn,int4 index);
|
||||
void deleteOps(const vector<int4> &indices);
|
||||
void saveXml(ostream &s,int4 sectionid) const;
|
||||
int4 restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||
void encode(Encoder &encoder,int4 sectionid) const;
|
||||
int4 decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class PcodeEmit; // Forward declaration for emitter
|
||||
|
||||
258
Ghidra/Features/Decompiler/src/decompile/cpp/slaformat.cc
Normal file
258
Ghidra/Features/Decompiler/src/decompile/cpp/slaformat.cc
Normal 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
|
||||
205
Ghidra/Features/Decompiler/src/decompile/cpp/slaformat.hh
Normal file
205
Ghidra/Features/Decompiler/src/decompile/cpp/slaformat.hh
Normal 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
|
||||
@@ -559,7 +559,13 @@ void Sleigh::initialize(DocumentStorage &store)
|
||||
const Element *el = store.getTag("sleigh");
|
||||
if (el == (const Element *)0)
|
||||
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
|
||||
reregisterContext();
|
||||
|
||||
@@ -356,8 +356,11 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
|
||||
|
||||
specpaths.findFile(processorfile,language.getProcessorSpec());
|
||||
specpaths.findFile(compilerfile,compilertag.getSpec());
|
||||
if (!language_reuse)
|
||||
if (!language_reuse) {
|
||||
specpaths.findFile(slafile,language.getSlaFile());
|
||||
if (slafile.empty())
|
||||
throw SleighError("Could not find .sla file for " + archid);
|
||||
}
|
||||
|
||||
try {
|
||||
Document *doc = store.openDocument(processorfile);
|
||||
@@ -394,16 +397,11 @@ void SleighArchitecture::buildSpecFile(DocumentStorage &store)
|
||||
}
|
||||
|
||||
if (!language_reuse) {
|
||||
istringstream s("<sleigh>" + slafile + "</sleigh>");
|
||||
try {
|
||||
Document *doc = store.openDocument(slafile);
|
||||
Document *doc = store.parseDocument(s);
|
||||
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) {
|
||||
ostringstream serr;
|
||||
serr << "Error reading SLEIGH file: " << slafile;
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
namespace ghidra {
|
||||
|
||||
const int4 SleighBase::SLA_FORMAT_VERSION = 3;
|
||||
|
||||
const uint4 SleighBase::MAX_UNIQUE_SIZE = 128;
|
||||
|
||||
int4 SourceFileIndexer::index(const string filename){
|
||||
@@ -39,26 +37,32 @@ string SourceFileIndexer::getFilename(int4 index){
|
||||
return indexToFile[index];
|
||||
}
|
||||
|
||||
void SourceFileIndexer::restoreXml(const Element *el){
|
||||
const List &sourceFiles(el->getChildren());
|
||||
List::const_iterator iter = sourceFiles.begin();
|
||||
for (; iter != sourceFiles.end(); ++iter){
|
||||
string filename = (*iter)->getAttributeValue("name");
|
||||
int4 index = stoi((*iter)->getAttributeValue("index"),NULL,10);
|
||||
fileToIndex[filename] = index;
|
||||
indexToFile[index] = filename;
|
||||
}
|
||||
void SourceFileIndexer::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
uint4 el = decoder.openElement(sla::ELEM_SOURCEFILES);
|
||||
while(decoder.peekElement() == sla::ELEM_SOURCEFILE) {
|
||||
int4 subel = decoder.openElement();
|
||||
string filename = decoder.readString(sla::ATTRIB_NAME);
|
||||
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 {
|
||||
s << "<sourcefiles>\n";
|
||||
for (int4 i = 0; i < leastUnusedIndex; ++i){
|
||||
s << ("<sourcefile name=\"");
|
||||
const char *str = indexToFile.at(i).c_str();
|
||||
xml_escape(s,str);
|
||||
s << "\" index=\"" << dec << i << "\"/>\n";
|
||||
}
|
||||
s << "</sourcefiles>\n";
|
||||
void SourceFileIndexer::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
encoder.openElement(sla::ELEM_SOURCEFILES);
|
||||
for (int4 i = 0; i < leastUnusedIndex; ++i){
|
||||
encoder.openElement(sla::ELEM_SOURCEFILE);
|
||||
encoder.writeString(sla::ATTRIB_NAME, indexToFile.at(i));
|
||||
encoder.writeSignedInteger(sla::ATTRIB_INDEX, i);
|
||||
encoder.closeElement(sla::ELEM_SOURCEFILE);
|
||||
}
|
||||
encoder.closeElement(sla::ELEM_SOURCEFILES);
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
/// This does the bulk of the work of creating a .sla file
|
||||
/// \param s is the output stream
|
||||
void SleighBase::saveXml(ostream &s) const
|
||||
/// Write a tag fully describing the details of the space.
|
||||
/// \param encoder is the stream being written
|
||||
/// \param spc is the given address space
|
||||
void SleighBase::encodeSlaSpace(Encoder &encoder,AddrSpace *spc) const
|
||||
|
||||
{
|
||||
s << "<sleigh";
|
||||
a_v_i(s,"version",SLA_FORMAT_VERSION);
|
||||
a_v_b(s,"bigendian",isBigEndian());
|
||||
a_v_i(s,"align",alignment);
|
||||
a_v_u(s,"uniqbase",getUniqueBase());
|
||||
if (spc->getType() == IPTR_INTERNAL)
|
||||
encoder.openElement(sla::ELEM_SPACE_UNIQUE);
|
||||
else if (spc->isOtherSpace())
|
||||
encoder.openElement(sla::ELEM_SPACE_OTHER);
|
||||
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)
|
||||
a_v_u(s,"maxdelay",maxdelayslotbytes);
|
||||
encoder.writeUnsignedInteger(sla::ATTRIB_MAXDELAY, maxdelayslotbytes);
|
||||
if (unique_allocatemask != 0)
|
||||
a_v_u(s,"uniqmask",unique_allocatemask);
|
||||
encoder.writeUnsignedInteger(sla::ATTRIB_UNIQMASK, unique_allocatemask);
|
||||
if (numSections != 0)
|
||||
a_v_u(s,"numsections",numSections);
|
||||
s << ">\n";
|
||||
indexer.saveXml(s);
|
||||
s << "<spaces";
|
||||
a_v(s,"defaultspace",getDefaultCodeSpace()->getName());
|
||||
s << ">\n";
|
||||
encoder.writeUnsignedInteger(sla::ATTRIB_NUMSECTIONS, numSections);
|
||||
indexer.encode(encoder);
|
||||
encoder.openElement(sla::ELEM_SPACES);
|
||||
encoder.writeString(sla::ATTRIB_DEFAULTSPACE, getDefaultCodeSpace()->getName());
|
||||
for(int4 i=0;i<numSpaces();++i) {
|
||||
AddrSpace *spc = getSpace(i);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
@@ -204,76 +236,129 @@ void SleighBase::saveXml(ostream &s) const
|
||||
(spc->getType()==IPTR_IOP)||
|
||||
(spc->getType()==IPTR_JOIN))
|
||||
continue;
|
||||
spc->saveXml(s);
|
||||
encodeSlaSpace(encoder,spc);
|
||||
}
|
||||
s << "</spaces>\n";
|
||||
symtab.saveXml(s);
|
||||
s << "</sleigh>\n";
|
||||
encoder.closeElement(sla::ELEM_SPACES);
|
||||
symtab.encode(encoder);
|
||||
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
|
||||
/// of address spaces and the symbol table, with its associated decoding tables
|
||||
/// \param el is the root XML element
|
||||
void SleighBase::restoreXml(const Element *el)
|
||||
/// \param decoder is the stream to decode
|
||||
void SleighBase::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
maxdelayslotbytes = 0;
|
||||
unique_allocatemask = 0;
|
||||
numSections = 0;
|
||||
int4 version = 0;
|
||||
setBigEndian(xml_readbool(el->getAttributeValue("bigendian")));
|
||||
{
|
||||
istringstream s(el->getAttributeValue("align"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> alignment;
|
||||
uint4 el = decoder.openElement(sla::ELEM_SLEIGH);
|
||||
uint4 attrib = decoder.getNextAttributeId();
|
||||
while(attrib != 0) {
|
||||
if (attrib == sla::ATTRIB_BIGENDIAN)
|
||||
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();
|
||||
}
|
||||
{
|
||||
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)
|
||||
if (version != sla::FORMAT_VERSION)
|
||||
throw LowlevelError(".sla file has wrong format");
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
while((*iter)->getName() == "floatformat") {
|
||||
floatformats.emplace_back();
|
||||
floatformats.back().restoreXml(*iter);
|
||||
++iter;
|
||||
}
|
||||
indexer.restoreXml(*iter);
|
||||
iter++;
|
||||
XmlDecode decoder(this,*iter);
|
||||
decodeSpaces(decoder,this);
|
||||
iter++;
|
||||
symtab.restoreXml(*iter,this);
|
||||
indexer.decode(decoder);
|
||||
decodeSlaSpaces(decoder,this);
|
||||
symtab.decode(decoder,this);
|
||||
decoder.closeElement(el);
|
||||
root = (SubtableSymbol *)symtab.getGlobalScope()->findSymbol("instruction");
|
||||
vector<string> errorPairs;
|
||||
buildXrefs(errorPairs);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define __SLEIGHBASE_HH__
|
||||
|
||||
#include "translate.hh"
|
||||
#include "slaformat.hh"
|
||||
#include "slghsymbol.hh"
|
||||
|
||||
namespace ghidra {
|
||||
@@ -41,8 +42,8 @@ public:
|
||||
int4 index(const string filename);
|
||||
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
|
||||
void restoreXml(const Element *el); ///< read a stored index mapping from an XML file
|
||||
void saveXml(ostream&) const; ///< save the index mapping to an XML file
|
||||
void decode(Decoder &decoder); ///< decode a stored index mapping from a stream
|
||||
void encode(Encoder &encoder) const; ///< Encode the index mapping to stream
|
||||
|
||||
private:
|
||||
int4 leastUnusedIndex; ///< one-up count for assigning indices to files
|
||||
@@ -57,7 +58,6 @@ private:
|
||||
/// - Reading the various SLEIGH specification files
|
||||
/// - Building and writing out SLEIGH specification files
|
||||
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
|
||||
map<VarnodeData,string> varnode_xref; ///< A map from Varnodes in the \e register space to register names
|
||||
protected:
|
||||
@@ -69,7 +69,9 @@ protected:
|
||||
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 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:
|
||||
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
|
||||
@@ -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(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
|
||||
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
|
||||
|
||||
@@ -1789,6 +1789,7 @@ SleighCompile::SleighCompile(void)
|
||||
warnalllocalcollisions = false;
|
||||
warnallnops = false;
|
||||
failinsensitivedups = true;
|
||||
debugoutput = false;
|
||||
root = (SubtableSymbol *)0;
|
||||
curmacro = (MacroSymbol *)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
|
||||
/// 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
|
||||
/// saveXml method.
|
||||
/// encode method.
|
||||
void SleighCompile::process(void)
|
||||
|
||||
{
|
||||
@@ -2546,7 +2547,8 @@ void SleighCompile::newSpace(SpaceQuality *qual)
|
||||
}
|
||||
|
||||
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);
|
||||
if (qual->isdefault) {
|
||||
if (getDefaultCodeSpace() != (AddrSpace *)0)
|
||||
@@ -3594,13 +3596,23 @@ int4 SleighCompile::run_compilation(const string &filein,const string &fileout)
|
||||
if (parseres==0)
|
||||
process(); // Do all the post-processing
|
||||
if ((parseres==0)&&(numErrors()==0)) { // If no errors
|
||||
ofstream s(fileout);
|
||||
ofstream s(fileout,ios::binary);
|
||||
if (!s) {
|
||||
ostringstream errs;
|
||||
errs << "Unable to open output file: " << fileout;
|
||||
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();
|
||||
}
|
||||
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,
|
||||
bool lenientConflict, bool allCollisionWarning,
|
||||
bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord,
|
||||
bool largeTemporaryWarning, bool caseSensitiveRegisterNames)
|
||||
bool largeTemporaryWarning, bool caseSensitiveRegisterNames,bool debugOutput)
|
||||
{
|
||||
map<string,string>::const_iterator iter = defines.begin();
|
||||
for (iter = defines.begin(); iter != defines.end(); iter++) {
|
||||
@@ -3711,6 +3723,7 @@ void SleighCompile::setAllOptions(const map<string,string> &defines, bool unnece
|
||||
setEnforceLocalKeyWord(enforceLocalKeyWord);
|
||||
setLargeTemporaryWarning(largeTemporaryWarning);
|
||||
setInsensitiveDuplicateError(!caseSensitiveRegisterNames);
|
||||
setDebugOutput(debugOutput);
|
||||
}
|
||||
|
||||
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 << " -a scan for all slaspec files recursively where inputfile is a directory" << 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 << " -l report pattern conflicts" << endl;
|
||||
cerr << " -n print warnings for all NOP constructors" << endl;
|
||||
@@ -3759,6 +3773,7 @@ int main(int argc,char **argv)
|
||||
bool enforceLocalKeyWord = false;
|
||||
bool largeTemporaryWarning = false;
|
||||
bool caseSensitiveRegisterNames = false;
|
||||
bool debugOutput = false;
|
||||
|
||||
bool compileAll = false;
|
||||
|
||||
@@ -3794,6 +3809,8 @@ int main(int argc,char **argv)
|
||||
largeTemporaryWarning = true;
|
||||
else if (argv[i][1] == 's')
|
||||
caseSensitiveRegisterNames = true;
|
||||
else if (argv[i][1] == 'y')
|
||||
debugOutput = true;
|
||||
#ifdef YYDEBUG
|
||||
else if (argv[i][1] == 'x')
|
||||
sleighdebug = 1; // Debug option
|
||||
@@ -3825,7 +3842,8 @@ int main(int argc,char **argv)
|
||||
sla.replace(slaspec.length() - slaspecExtLen, slaspecExtLen, SLAEXT);
|
||||
SleighCompile compiler;
|
||||
compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning,
|
||||
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning, caseSensitiveRegisterNames);
|
||||
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning, caseSensitiveRegisterNames,
|
||||
debugOutput);
|
||||
retval = compiler.run_compilation(slaspec,sla);
|
||||
if (retval != 0) {
|
||||
return retval; // stop on first error
|
||||
@@ -3861,7 +3879,8 @@ int main(int argc,char **argv)
|
||||
|
||||
SleighCompile compiler;
|
||||
compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning,
|
||||
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning,caseSensitiveRegisterNames);
|
||||
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning,caseSensitiveRegisterNames,
|
||||
debugOutput);
|
||||
|
||||
if (i < argc - 1) {
|
||||
string fileoutExamine(argv[i+1]);
|
||||
|
||||
@@ -300,6 +300,7 @@ private:
|
||||
bool warnalllocalcollisions; ///< \b true if local export collisions 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 debugoutput; ///< \b true if output .sla is written in XML debug format
|
||||
vector<string> noplist; ///< List of individual NOP warnings
|
||||
mutable Location currentLocCache; ///< Location for (last) request of current location
|
||||
int4 errors; ///< Number of fatal errors encountered
|
||||
@@ -382,6 +383,11 @@ public:
|
||||
/// \param val is \b true is duplicates cause an error.
|
||||
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
|
||||
void calcContextLayout(void); ///< Calculate the internal context field layout
|
||||
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,
|
||||
bool lenientConflict, bool allCollisionWarning,
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -462,50 +462,50 @@ void PatternExpression::release(PatternExpression *p)
|
||||
delete p;
|
||||
}
|
||||
|
||||
PatternExpression *PatternExpression::restoreExpression(const Element *el,Translate *trans)
|
||||
PatternExpression *PatternExpression::decodeExpression(Decoder &decoder,Translate *trans)
|
||||
|
||||
{
|
||||
PatternExpression *res;
|
||||
const string &nm(el->getName());
|
||||
uint4 el = decoder.peekElement();
|
||||
|
||||
if (nm == "tokenfield")
|
||||
if (el == sla::ELEM_TOKENFIELD)
|
||||
res = new TokenField();
|
||||
else if (nm == "contextfield")
|
||||
else if (el == sla::ELEM_CONTEXTFIELD)
|
||||
res = new ContextField();
|
||||
else if (nm == "intb")
|
||||
else if (el == sla::ELEM_INTB)
|
||||
res = new ConstantValue();
|
||||
else if (nm == "operand_exp")
|
||||
else if (el == sla::ELEM_OPERAND_EXP)
|
||||
res = new OperandValue();
|
||||
else if (nm == "start_exp")
|
||||
else if (el == sla::ELEM_START_EXP)
|
||||
res = new StartInstructionValue();
|
||||
else if (nm == "end_exp")
|
||||
else if (el == sla::ELEM_END_EXP)
|
||||
res = new EndInstructionValue();
|
||||
else if (nm == "plus_exp")
|
||||
else if (el == sla::ELEM_PLUS_EXP)
|
||||
res = new PlusExpression();
|
||||
else if (nm == "sub_exp")
|
||||
else if (el == sla::ELEM_SUB_EXP)
|
||||
res = new SubExpression();
|
||||
else if (nm == "mult_exp")
|
||||
else if (el == sla::ELEM_MULT_EXP)
|
||||
res = new MultExpression();
|
||||
else if (nm == "lshift_exp")
|
||||
else if (el == sla::ELEM_LSHIFT_EXP)
|
||||
res = new LeftShiftExpression();
|
||||
else if (nm == "rshift_exp")
|
||||
else if (el == sla::ELEM_RSHIFT_EXP)
|
||||
res = new RightShiftExpression();
|
||||
else if (nm == "and_exp")
|
||||
else if (el == sla::ELEM_AND_EXP)
|
||||
res = new AndExpression();
|
||||
else if (nm == "or_exp")
|
||||
else if (el == sla::ELEM_OR_EXP)
|
||||
res = new OrExpression();
|
||||
else if (nm == "xor_exp")
|
||||
else if (el == sla::ELEM_XOR_EXP)
|
||||
res = new XorExpression();
|
||||
else if (nm == "div_exp")
|
||||
else if (el == sla::ELEM_DIV_EXP)
|
||||
res = new DivExpression();
|
||||
else if (nm == "minus_exp")
|
||||
else if (el == sla::ELEM_MINUS_EXP)
|
||||
res = new MinusExpression();
|
||||
else if (nm == "not_exp")
|
||||
else if (el == sla::ELEM_NOT_EXP)
|
||||
res = new NotExpression();
|
||||
else
|
||||
return (PatternExpression *)0;
|
||||
|
||||
res->restoreXml(el,trans);
|
||||
res->decode(decoder,trans);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -597,58 +597,33 @@ TokenPattern TokenField::genPattern(intb val) const
|
||||
return TokenPattern(tok,val,bitstart,bitend);
|
||||
}
|
||||
|
||||
void TokenField::saveXml(ostream &s) const
|
||||
void TokenField::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<tokenfield";
|
||||
s << " bigendian=\"";
|
||||
if (bigendian)
|
||||
s << "true\"";
|
||||
else
|
||||
s << "false\"";
|
||||
s << " signbit=\"";
|
||||
if (signbit)
|
||||
s << "true\"";
|
||||
else
|
||||
s << "false\"";
|
||||
s << " bitstart=\"" << dec << bitstart << "\"";
|
||||
s << " bitend=\"" << bitend << "\"";
|
||||
s << " bytestart=\"" << bytestart << "\"";
|
||||
s << " byteend=\"" << byteend << "\"";
|
||||
s << " shift=\"" << shift << "\"/>\n";
|
||||
encoder.openElement(sla::ELEM_TOKENFIELD);
|
||||
encoder.writeBool(sla::ATTRIB_BIGENDIAN, bigendian);
|
||||
encoder.writeBool(sla::ATTRIB_SIGNBIT, signbit);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_STARTBIT, bitstart);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_ENDBIT, bitend);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_STARTBYTE, bytestart);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_ENDBYTE, byteend);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_SHIFT, shift);
|
||||
encoder.closeElement(sla::ELEM_TOKENFIELD);
|
||||
}
|
||||
|
||||
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;
|
||||
bigendian = xml_readbool(el->getAttributeValue("bigendian"));
|
||||
signbit = xml_readbool(el->getAttributeValue("signbit"));
|
||||
{
|
||||
istringstream s(el->getAttributeValue("bitstart"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> bitstart;
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
bigendian = decoder.readBool(sla::ATTRIB_BIGENDIAN);
|
||||
signbit = decoder.readBool(sla::ATTRIB_SIGNBIT);
|
||||
bitstart = decoder.readSignedInteger(sla::ATTRIB_STARTBIT);
|
||||
bitend = decoder.readSignedInteger(sla::ATTRIB_ENDBIT);
|
||||
bytestart = decoder.readSignedInteger(sla::ATTRIB_STARTBYTE);
|
||||
byteend = decoder.readSignedInteger(sla::ATTRIB_ENDBYTE);
|
||||
shift = decoder.readSignedInteger(sla::ATTRIB_SHIFT);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
ContextField::ContextField(bool s,int4 sbit,int4 ebit)
|
||||
@@ -680,65 +655,88 @@ TokenPattern ContextField::genPattern(intb val) const
|
||||
return TokenPattern(val,startbit,endbit);
|
||||
}
|
||||
|
||||
void ContextField::saveXml(ostream &s) const
|
||||
void ContextField::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<contextfield";
|
||||
s << " signbit=\"";
|
||||
if (signbit)
|
||||
s << "true\"";
|
||||
else
|
||||
s << "false\"";
|
||||
s << " startbit=\"" << dec << startbit << "\"";
|
||||
s << " endbit=\"" << endbit << "\"";
|
||||
s << " startbyte=\"" << startbyte << "\"";
|
||||
s << " endbyte=\"" << endbyte << "\"";
|
||||
s << " shift=\"" << shift << "\"/>\n";
|
||||
encoder.openElement(sla::ELEM_CONTEXTFIELD);
|
||||
encoder.writeBool(sla::ATTRIB_SIGNBIT, signbit);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_STARTBIT, startbit);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_ENDBIT, endbit);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_STARTBYTE, startbyte);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_ENDBYTE, endbyte);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_SHIFT, shift);
|
||||
encoder.closeElement(sla::ELEM_CONTEXTFIELD);
|
||||
}
|
||||
|
||||
void ContextField::restoreXml(const Element *el,Translate *trans)
|
||||
void ContextField::decode(Decoder &decoder,Translate *trans)
|
||||
|
||||
{
|
||||
signbit = xml_readbool(el->getAttributeValue("signbit"));
|
||||
{
|
||||
istringstream s(el->getAttributeValue("startbit"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> startbit;
|
||||
}
|
||||
{
|
||||
istringstream s(el->getAttributeValue("endbit"));
|
||||
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;
|
||||
}
|
||||
uint4 el = decoder.openElement(sla::ELEM_CONTEXTFIELD);
|
||||
signbit = decoder.readBool(sla::ATTRIB_SIGNBIT);
|
||||
startbit = decoder.readSignedInteger(sla::ATTRIB_STARTBIT);
|
||||
endbit = decoder.readSignedInteger(sla::ATTRIB_ENDBIT);
|
||||
startbyte = decoder.readSignedInteger(sla::ATTRIB_STARTBYTE);
|
||||
endbyte = decoder.readSignedInteger(sla::ATTRIB_ENDBYTE);
|
||||
shift = decoder.readSignedInteger(sla::ATTRIB_SHIFT);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
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"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> val;
|
||||
uint4 el = decoder.openElement(sla::ELEM_INTB);
|
||||
val = decoder.readSignedInteger(sla::ATTRIB_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
|
||||
@@ -809,37 +807,27 @@ const string &OperandValue::getName(void) const
|
||||
return sym->getName();
|
||||
}
|
||||
|
||||
void OperandValue::saveXml(ostream &s) const
|
||||
void OperandValue::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<operand_exp";
|
||||
s << " index=\"" << dec << index << "\"";
|
||||
s << " table=\"0x" << hex << ct->getParent()->getId() << "\"";
|
||||
s << " ct=\"0x" << ct->getId() << "\"/>\n"; // Save id of our constructor
|
||||
encoder.openElement(sla::ELEM_OPERAND_EXP);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_INDEX, index);
|
||||
encoder.writeUnsignedInteger(sla::ATTRIB_TABLE, ct->getParent()->getId());
|
||||
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;
|
||||
{
|
||||
istringstream s(el->getAttributeValue("index"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
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;
|
||||
}
|
||||
uint4 el = decoder.openElement(sla::ELEM_OPERAND_EXP);
|
||||
index = decoder.readSignedInteger(sla::ATTRIB_INDEX);
|
||||
uintm tabid = decoder.readUnsignedInteger(sla::ATTRIB_TABLE);
|
||||
uintm ctid = decoder.readUnsignedInteger(sla::ATTRIB_CT);
|
||||
SleighBase *sleigh = (SleighBase *)trans;
|
||||
SubtableSymbol *tab = dynamic_cast<SubtableSymbol *>(sleigh->findSymbol(tabid));
|
||||
ct = tab->getConstructor(ctid);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
BinaryExpression::BinaryExpression(PatternExpression *l,PatternExpression *r)
|
||||
@@ -858,24 +846,22 @@ BinaryExpression::~BinaryExpression(void)
|
||||
PatternExpression::release(right);
|
||||
}
|
||||
|
||||
void BinaryExpression::saveXml(ostream &s) const
|
||||
void BinaryExpression::encode(Encoder &encoder) const
|
||||
|
||||
{ // Outer tag is generated by derived classes
|
||||
left->saveXml(s);
|
||||
right->saveXml(s);
|
||||
left->encode(encoder);
|
||||
right->encode(encoder);
|
||||
}
|
||||
|
||||
void BinaryExpression::restoreXml(const Element *el,Translate *trans)
|
||||
void BinaryExpression::decode(Decoder &decoder,Translate *trans)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
left = PatternExpression::restoreExpression(*iter,trans);
|
||||
++iter;
|
||||
right = PatternExpression::restoreExpression(*iter,trans);
|
||||
uint4 el = decoder.openElement();
|
||||
left = PatternExpression::decodeExpression(decoder,trans);
|
||||
right = PatternExpression::decodeExpression(decoder,trans);
|
||||
left->layClaim();
|
||||
right->layClaim();
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
UnaryExpression::UnaryExpression(PatternExpression *u)
|
||||
@@ -891,20 +877,19 @@ UnaryExpression::~UnaryExpression(void)
|
||||
PatternExpression::release(unary);
|
||||
}
|
||||
|
||||
void UnaryExpression::saveXml(ostream &s) const
|
||||
void UnaryExpression::encode(Encoder &encoder) const
|
||||
|
||||
{ // 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());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
unary = PatternExpression::restoreExpression(*iter,trans);
|
||||
uint4 el = decoder.openElement();
|
||||
unary = PatternExpression::decodeExpression(decoder,trans);
|
||||
unary->layClaim();
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
intb PlusExpression::getValue(ParserWalker &walker) const
|
||||
@@ -923,12 +908,12 @@ intb PlusExpression::getSubValue(const vector<intb> &replace,int4 &listpos) cons
|
||||
return leftval + rightval;
|
||||
}
|
||||
|
||||
void PlusExpression::saveXml(ostream &s) const
|
||||
void PlusExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<plus_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</plus_exp>\n";
|
||||
encoder.openElement(sla::ELEM_PLUS_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_PLUS_EXP);
|
||||
}
|
||||
|
||||
intb SubExpression::getValue(ParserWalker &walker) const
|
||||
@@ -947,12 +932,12 @@ intb SubExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
|
||||
return leftval - rightval;
|
||||
}
|
||||
|
||||
void SubExpression::saveXml(ostream &s) const
|
||||
void SubExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<sub_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</sub_exp>\n";
|
||||
encoder.openElement(sla::ELEM_SUB_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_SUB_EXP);
|
||||
}
|
||||
|
||||
intb MultExpression::getValue(ParserWalker &walker) const
|
||||
@@ -971,12 +956,12 @@ intb MultExpression::getSubValue(const vector<intb> &replace,int4 &listpos) cons
|
||||
return leftval * rightval;
|
||||
}
|
||||
|
||||
void MultExpression::saveXml(ostream &s) const
|
||||
void MultExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<mult_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</mult_exp>\n";
|
||||
encoder.openElement(sla::ELEM_MULT_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_MULT_EXP);
|
||||
}
|
||||
|
||||
intb LeftShiftExpression::getValue(ParserWalker &walker) const
|
||||
@@ -995,12 +980,12 @@ intb LeftShiftExpression::getSubValue(const vector<intb> &replace,int4 &listpos)
|
||||
return leftval << rightval;
|
||||
}
|
||||
|
||||
void LeftShiftExpression::saveXml(ostream &s) const
|
||||
void LeftShiftExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<lshift_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</lshift_exp>\n";
|
||||
encoder.openElement(sla::ELEM_LSHIFT_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_LSHIFT_EXP);
|
||||
}
|
||||
|
||||
intb RightShiftExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1019,12 +1004,12 @@ intb RightShiftExpression::getSubValue(const vector<intb> &replace,int4 &listpos
|
||||
return leftval >> rightval;
|
||||
}
|
||||
|
||||
void RightShiftExpression::saveXml(ostream &s) const
|
||||
void RightShiftExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<rshift_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</rshift_exp>\n";
|
||||
encoder.openElement(sla::ELEM_RSHIFT_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_RSHIFT_EXP);
|
||||
}
|
||||
|
||||
intb AndExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1043,12 +1028,12 @@ intb AndExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
|
||||
return leftval & rightval;
|
||||
}
|
||||
|
||||
void AndExpression::saveXml(ostream &s) const
|
||||
void AndExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<and_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</and_exp>\n";
|
||||
encoder.openElement(sla::ELEM_AND_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_AND_EXP);
|
||||
}
|
||||
|
||||
intb OrExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1067,12 +1052,12 @@ intb OrExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
|
||||
return leftval | rightval;
|
||||
}
|
||||
|
||||
void OrExpression::saveXml(ostream &s) const
|
||||
void OrExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<or_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</or_exp>\n";
|
||||
encoder.openElement(sla::ELEM_OR_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_OR_EXP);
|
||||
}
|
||||
|
||||
intb XorExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1091,12 +1076,12 @@ intb XorExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
|
||||
return leftval ^ rightval;
|
||||
}
|
||||
|
||||
void XorExpression::saveXml(ostream &s) const
|
||||
void XorExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<xor_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</xor_exp>\n";
|
||||
encoder.openElement(sla::ELEM_XOR_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_XOR_EXP);
|
||||
}
|
||||
|
||||
intb DivExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1115,12 +1100,12 @@ intb DivExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
|
||||
return leftval / rightval;
|
||||
}
|
||||
|
||||
void DivExpression::saveXml(ostream &s) const
|
||||
void DivExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<div_exp>\n";
|
||||
BinaryExpression::saveXml(s);
|
||||
s << "</div_exp>\n";
|
||||
encoder.openElement(sla::ELEM_DIV_EXP);
|
||||
BinaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_DIV_EXP);
|
||||
}
|
||||
|
||||
intb MinusExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1137,12 +1122,12 @@ intb MinusExpression::getSubValue(const vector<intb> &replace,int4 &listpos) con
|
||||
return -val;
|
||||
}
|
||||
|
||||
void MinusExpression::saveXml(ostream &s) const
|
||||
void MinusExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<minus_exp>\n";
|
||||
UnaryExpression::saveXml(s);
|
||||
s << "</minus_exp>\n";
|
||||
encoder.openElement(sla::ELEM_MINUS_EXP);
|
||||
UnaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_MINUS_EXP);
|
||||
}
|
||||
|
||||
intb NotExpression::getValue(ParserWalker &walker) const
|
||||
@@ -1159,12 +1144,12 @@ intb NotExpression::getSubValue(const vector<intb> &replace,int4 &listpos) const
|
||||
return ~val;
|
||||
}
|
||||
|
||||
void NotExpression::saveXml(ostream &s) const
|
||||
void NotExpression::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<not_exp>\n";
|
||||
UnaryExpression::saveXml(s);
|
||||
s << "</not_exp>\n";
|
||||
encoder.openElement(sla::ELEM_NOT_EXP);
|
||||
UnaryExpression::encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_NOT_EXP);
|
||||
}
|
||||
|
||||
static bool advance_combo(vector<intb> &val,const vector<intb> &min,vector<intb> &max)
|
||||
|
||||
@@ -67,14 +67,14 @@ public:
|
||||
virtual void listValues(vector<const PatternValue *> &list) 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 void saveXml(ostream &s) const=0;
|
||||
virtual void restoreXml(const Element *el,Translate *trans)=0;
|
||||
virtual void encode(Encoder &encoder) const=0;
|
||||
virtual void decode(Decoder &decoder,Translate *trans)=0;
|
||||
intb getSubValue(const vector<intb> &replace) {
|
||||
int4 listpos = 0;
|
||||
return getSubValue(replace,listpos); }
|
||||
void layClaim(void) { refcount += 1; }
|
||||
static void release(PatternExpression *p);
|
||||
static PatternExpression *restoreExpression(const Element *el,Translate *trans);
|
||||
static PatternExpression *decodeExpression(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class PatternValue : public PatternExpression {
|
||||
@@ -96,15 +96,15 @@ class TokenField : public PatternValue {
|
||||
int4 bytestart,byteend; // Bytes to read to get value
|
||||
int4 shift; // Amount to shift to align value (bitstart % 8)
|
||||
public:
|
||||
TokenField(void) {} // For use with restoreXml
|
||||
TokenField(void) {} // For use with decode
|
||||
TokenField(Token *tk,bool s,int4 bstart,int4 bend);
|
||||
virtual intb getValue(ParserWalker &walker) const;
|
||||
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(tok); }
|
||||
virtual TokenPattern genPattern(intb val) const;
|
||||
virtual intb minValue(void) const { return 0; }
|
||||
virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,bitend-bitstart); }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,Translate *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class ContextField : public PatternValue {
|
||||
@@ -113,7 +113,7 @@ class ContextField : public PatternValue {
|
||||
int4 shift;
|
||||
bool signbit;
|
||||
public:
|
||||
ContextField(void) {} // For use with restoreXml
|
||||
ContextField(void) {} // For use with decode
|
||||
ContextField(bool s,int4 sbit,int4 ebit);
|
||||
int4 getStartBit(void) const { return startbit; }
|
||||
int4 getEndBit(void) const { return endbit; }
|
||||
@@ -123,22 +123,22 @@ public:
|
||||
virtual TokenPattern genPattern(intb val) const;
|
||||
virtual intb minValue(void) const { return 0; }
|
||||
virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,(endbit-startbit)); }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,Translate *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class ConstantValue : public PatternValue {
|
||||
intb val;
|
||||
public:
|
||||
ConstantValue(void) {} // For use with restoreXml
|
||||
ConstantValue(void) {} // For use with decode
|
||||
ConstantValue(intb v) { val = v; }
|
||||
virtual intb getValue(ParserWalker &walker) const { return val; }
|
||||
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); }
|
||||
virtual TokenPattern genPattern(intb v) const { return TokenPattern(val==v); }
|
||||
virtual intb minValue(void) const { return val; }
|
||||
virtual intb maxValue(void) const { return val; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,Translate *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class StartInstructionValue : public PatternValue {
|
||||
@@ -150,8 +150,8 @@ public:
|
||||
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
|
||||
virtual intb minValue(void) const { return (intb)0; }
|
||||
virtual intb maxValue(void) const { return (intb)0; }
|
||||
virtual void saveXml(ostream &s) const { s << "<start_exp/>"; }
|
||||
virtual void restoreXml(const Element *el,Translate *trans) {}
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class EndInstructionValue : public PatternValue {
|
||||
@@ -163,8 +163,8 @@ public:
|
||||
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
|
||||
virtual intb minValue(void) const { return (intb)0; }
|
||||
virtual intb maxValue(void) const { return (intb)0; }
|
||||
virtual void saveXml(ostream &s) const { s << "<end_exp/>"; }
|
||||
virtual void restoreXml(const Element *el,Translate *trans) {}
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class Next2InstructionValue : public PatternValue {
|
||||
@@ -176,8 +176,8 @@ public:
|
||||
virtual TokenPattern genPattern(intb val) const { return TokenPattern(); }
|
||||
virtual intb minValue(void) const { return (intb)0; }
|
||||
virtual intb maxValue(void) const { return (intb)0; }
|
||||
virtual void saveXml(ostream &s) const { s << "<next2_exp/>"; }
|
||||
virtual void restoreXml(const Element *el,Translate *trans) {}
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class Constructor; // Forward declaration
|
||||
@@ -186,7 +186,7 @@ class OperandValue : public PatternValue {
|
||||
int4 index; // This is the defining field of expression
|
||||
Constructor *ct; // cached pointer to constructor
|
||||
public:
|
||||
OperandValue(void) { } // For use with restoreXml
|
||||
OperandValue(void) { } // For use with decode
|
||||
OperandValue(int4 ind,Constructor *c) { index = ind; ct = c; }
|
||||
void changeIndex(int4 newind) { index = newind; }
|
||||
bool isConstructorRelative(void) const;
|
||||
@@ -197,8 +197,8 @@ public:
|
||||
virtual intb getSubValue(const vector<intb> &replace,int4 &listpos) const;
|
||||
virtual intb minValue(void) const;
|
||||
virtual intb maxValue(void) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,Translate *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class BinaryExpression : public PatternExpression {
|
||||
@@ -206,7 +206,7 @@ class BinaryExpression : public PatternExpression {
|
||||
protected:
|
||||
virtual ~BinaryExpression(void);
|
||||
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);
|
||||
PatternExpression *getLeft(void) const { return left; }
|
||||
PatternExpression *getRight(void) const { return right; }
|
||||
@@ -215,8 +215,8 @@ public:
|
||||
left->listValues(list); right->listValues(list); }
|
||||
virtual void getMinMax(vector<intb> &minlist,vector<intb> &maxlist) const {
|
||||
left->getMinMax(minlist,maxlist); right->getMinMax(minlist,maxlist); }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,Translate *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class UnaryExpression : public PatternExpression {
|
||||
@@ -224,7 +224,7 @@ class UnaryExpression : public PatternExpression {
|
||||
protected:
|
||||
virtual ~UnaryExpression(void);
|
||||
public:
|
||||
UnaryExpression(void) { unary = (PatternExpression *)0; } // For use with restoreXml
|
||||
UnaryExpression(void) { unary = (PatternExpression *)0; } // For use with decode
|
||||
UnaryExpression(PatternExpression *u);
|
||||
PatternExpression *getUnary(void) const { return unary; }
|
||||
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 {
|
||||
unary->getMinMax(minlist,maxlist);
|
||||
}
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,Translate *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,Translate *trans);
|
||||
};
|
||||
|
||||
class PlusExpression : public BinaryExpression {
|
||||
public:
|
||||
PlusExpression(void) {} // For use by restoreXml
|
||||
PlusExpression(void) {} // For use by decode
|
||||
PlusExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
public:
|
||||
SubExpression(void) {} // For use with restoreXml
|
||||
SubExpression(void) {} // For use with decode
|
||||
SubExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
public:
|
||||
MultExpression(void) {} // For use with restoreXml
|
||||
MultExpression(void) {} // For use with decode
|
||||
MultExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
LeftShiftExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -279,7 +279,7 @@ public:
|
||||
RightShiftExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -288,7 +288,7 @@ public:
|
||||
AndExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -297,7 +297,7 @@ public:
|
||||
OrExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -306,7 +306,7 @@ public:
|
||||
XorExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -315,7 +315,7 @@ public:
|
||||
DivExpression(PatternExpression *l,PatternExpression *r) : BinaryExpression(l,r) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -324,7 +324,7 @@ public:
|
||||
MinusExpression(PatternExpression *u) : UnaryExpression(u) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
@@ -333,7 +333,7 @@ public:
|
||||
NotExpression(PatternExpression *u) : UnaryExpression(u) {}
|
||||
virtual intb getValue(ParserWalker &walker) 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 {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "slghpattern.hh"
|
||||
#include "slaformat.hh"
|
||||
|
||||
namespace ghidra {
|
||||
|
||||
@@ -137,17 +138,18 @@ bool DisjointPattern::resolvesIntersect(const DisjointPattern *op1,const Disjoin
|
||||
return resolveIntersectBlock(op1->getBlock(true),op2->getBlock(true),getBlock(true));
|
||||
}
|
||||
|
||||
DisjointPattern *DisjointPattern::restoreDisjoint(const Element *el)
|
||||
DisjointPattern *DisjointPattern::decodeDisjoint(Decoder &decoder)
|
||||
|
||||
{ // DisjointPattern factory
|
||||
DisjointPattern *res;
|
||||
if (el->getName() == "instruct_pat")
|
||||
uint4 el = decoder.peekElement();
|
||||
if (el == sla::ELEM_INSTRUCT_PAT)
|
||||
res = new InstructionPattern();
|
||||
else if (el->getName() == "context_pat")
|
||||
else if (el == sla::ELEM_CONTEXT_PAT)
|
||||
res = new ContextPattern();
|
||||
else
|
||||
res = new CombinePattern();
|
||||
res->restoreXml(el);
|
||||
res->decode(decoder);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -485,54 +487,37 @@ bool PatternBlock::isContextMatch(ParserWalker &walker) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void PatternBlock::saveXml(ostream &s) const
|
||||
void PatternBlock::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<pat_block ";
|
||||
s << "offset=\"" << dec << offset << "\" ";
|
||||
s << "nonzero=\"" << nonzerosize << "\">\n";
|
||||
encoder.openElement(sla::ELEM_PAT_BLOCK);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_OFF, offset);
|
||||
encoder.writeSignedInteger(sla::ATTRIB_NONZERO, nonzerosize);
|
||||
for(int4 i=0;i<maskvec.size();++i) {
|
||||
s << " <mask_word ";
|
||||
s << "mask=\"0x" << hex << maskvec[i] << "\" ";
|
||||
s << "val=\"0x" << valvec[i] << "\"/>\n";
|
||||
encoder.openElement(sla::ELEM_MASK_WORD);
|
||||
encoder.writeUnsignedInteger(sla::ATTRIB_MASK, maskvec[i]);
|
||||
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)
|
||||
|
||||
{
|
||||
{
|
||||
istringstream s(el->getAttributeValue("offset"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> offset;
|
||||
}
|
||||
{
|
||||
istringstream s(el->getAttributeValue("nonzero"));
|
||||
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;
|
||||
}
|
||||
uint4 el = decoder.openElement(sla::ELEM_PAT_BLOCK);
|
||||
offset = decoder.readSignedInteger(sla::ATTRIB_OFF);
|
||||
nonzerosize = decoder.readSignedInteger(sla::ATTRIB_NONZERO);
|
||||
while(decoder.peekElement() != 0) {
|
||||
uint4 subel = decoder.openElement(sla::ELEM_MASK_WORD);
|
||||
uintm mask = decoder.readUnsignedInteger(sla::ATTRIB_MASK);
|
||||
uintm val = decoder.readUnsignedInteger(sla::ATTRIB_VAL);
|
||||
maskvec.push_back(mask);
|
||||
valvec.push_back(val);
|
||||
++iter;
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
normalize();
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void InstructionPattern::saveXml(ostream &s) const
|
||||
void InstructionPattern::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<instruct_pat>\n";
|
||||
maskvalue->saveXml(s);
|
||||
s << "</instruct_pat>\n";
|
||||
encoder.openElement(sla::ELEM_INSTRUCT_PAT);
|
||||
maskvalue->encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_INSTRUCT_PAT);
|
||||
}
|
||||
|
||||
void InstructionPattern::restoreXml(const Element *el)
|
||||
void InstructionPattern::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
uint4 el = decoder.openElement(sla::ELEM_INSTRUCT_PAT);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue->restoreXml(*iter);
|
||||
maskvalue->decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void ContextPattern::saveXml(ostream &s) const
|
||||
void ContextPattern::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<context_pat>\n";
|
||||
maskvalue->saveXml(s);
|
||||
s << "</context_pat>\n";
|
||||
encoder.openElement(sla::ELEM_CONTEXT_PAT);
|
||||
maskvalue->encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_CONTEXT_PAT);
|
||||
}
|
||||
|
||||
void ContextPattern::restoreXml(const Element *el)
|
||||
void ContextPattern::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
uint4 el = decoder.openElement(sla::ELEM_CONTEXT_PAT);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue->restoreXml(*iter);
|
||||
maskvalue->decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
CombinePattern::~CombinePattern(void)
|
||||
@@ -804,26 +787,24 @@ Pattern *CombinePattern::simplifyClone(void) const
|
||||
(InstructionPattern *)instr->simplifyClone());
|
||||
}
|
||||
|
||||
void CombinePattern::saveXml(ostream &s) const
|
||||
void CombinePattern::encode(Encoder &encoder) const
|
||||
|
||||
{
|
||||
s << "<combine_pat>\n";
|
||||
context->saveXml(s);
|
||||
instr->saveXml(s);
|
||||
s << "</combine_pat>\n";
|
||||
encoder.openElement(sla::ELEM_COMBINE_PAT);
|
||||
context->encode(encoder);
|
||||
instr->encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_COMBINE_PAT);
|
||||
}
|
||||
|
||||
void CombinePattern::restoreXml(const Element *el)
|
||||
void CombinePattern::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
uint4 el = decoder.openElement(sla::ELEM_COMBINE_PAT);
|
||||
context = new ContextPattern();
|
||||
context->restoreXml(*iter);
|
||||
++iter;
|
||||
context->decode(decoder);
|
||||
instr = new InstructionPattern();
|
||||
instr->restoreXml(*iter);
|
||||
instr->decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
OrPattern::OrPattern(DisjointPattern *a,DisjointPattern *b)
|
||||
@@ -995,26 +976,24 @@ Pattern *OrPattern::simplifyClone(void) const
|
||||
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)
|
||||
orlist[i]->saveXml(s);
|
||||
s << "</or_pat>\n";
|
||||
orlist[i]->encode(encoder);
|
||||
encoder.closeElement(sla::ELEM_OR_PAT);
|
||||
}
|
||||
|
||||
void OrPattern::restoreXml(const Element *el)
|
||||
void OrPattern::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
while(iter != list.end()) {
|
||||
DisjointPattern *pat = DisjointPattern::restoreDisjoint(*iter);
|
||||
uint4 el = decoder.openElement(sla::ELEM_OR_PAT);
|
||||
while(decoder.peekElement() != 0) {
|
||||
DisjointPattern *pat = DisjointPattern::decodeDisjoint(decoder);
|
||||
orlist.push_back(pat);
|
||||
++iter;
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
} // End namespace ghidra
|
||||
|
||||
@@ -45,8 +45,8 @@ public:
|
||||
bool alwaysFalse(void) const { return (nonzerosize==-1); }
|
||||
bool isInstructionMatch(ParserWalker &walker) const;
|
||||
bool isContextMatch(ParserWalker &walker) const;
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class DisjointPattern;
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
virtual bool alwaysTrue(void) const=0;
|
||||
virtual bool alwaysFalse(void) const=0;
|
||||
virtual bool alwaysInstructionTrue(void) const=0;
|
||||
virtual void saveXml(ostream &s) const=0;
|
||||
virtual void restoreXml(const Element *el)=0;
|
||||
virtual void encode(Encoder &encoder) const=0;
|
||||
virtual void decode(Decoder &decoder)=0;
|
||||
};
|
||||
|
||||
class DisjointPattern : public Pattern { // A pattern with no ORs in it
|
||||
@@ -79,14 +79,14 @@ public:
|
||||
bool specializes(const DisjointPattern *op2) const;
|
||||
bool identical(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
|
||||
PatternBlock *maskvalue;
|
||||
virtual PatternBlock *getBlock(bool context) const { return context ? (PatternBlock *)0 : maskvalue; }
|
||||
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(bool tf) { maskvalue = new PatternBlock(tf); }
|
||||
PatternBlock *getBlock(void) { return maskvalue; }
|
||||
@@ -100,15 +100,15 @@ public:
|
||||
virtual bool alwaysTrue(void) const { return maskvalue->alwaysTrue(); }
|
||||
virtual bool alwaysFalse(void) const { return maskvalue->alwaysFalse(); }
|
||||
virtual bool alwaysInstructionTrue(void) const { return maskvalue->alwaysTrue(); }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class ContextPattern : public DisjointPattern { // Matches the context bitstream
|
||||
PatternBlock *maskvalue;
|
||||
virtual PatternBlock *getBlock(bool context) const { return context ? maskvalue : (PatternBlock *)0; }
|
||||
public:
|
||||
ContextPattern(void) { maskvalue = (PatternBlock *)0; } // For use with restoreXml
|
||||
ContextPattern(void) { maskvalue = (PatternBlock *)0; } // For use with decode
|
||||
ContextPattern(PatternBlock *mv) { maskvalue = mv; }
|
||||
PatternBlock *getBlock(void) { return 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 alwaysFalse(void) const { return maskvalue->alwaysFalse(); }
|
||||
virtual bool alwaysInstructionTrue(void) const { return true; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
// 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 *doAnd(const Pattern *b,int4 sa) const;
|
||||
virtual Pattern *commonSubPattern(const Pattern *b,int4 sa) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
class OrPattern : public Pattern {
|
||||
vector<DisjointPattern *> orlist;
|
||||
public:
|
||||
OrPattern(void) {} // For use with restoreXml
|
||||
OrPattern(void) {} // For use with decode
|
||||
OrPattern(DisjointPattern *a,DisjointPattern *b);
|
||||
OrPattern(const vector<DisjointPattern *> &list);
|
||||
virtual ~OrPattern(void);
|
||||
@@ -166,8 +166,8 @@ public:
|
||||
virtual Pattern *doOr(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 void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
} // End namespace ghidra
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,16 +35,16 @@ private:
|
||||
uintm id; // Unique id across all symbols
|
||||
uintm scopeid; // Unique id of scope this symbol is in
|
||||
public:
|
||||
SleighSymbol(void) {} // For use with restoreXml
|
||||
SleighSymbol(void) {} // For use with decode
|
||||
SleighSymbol(const string &nm) { name = nm; id = 0; }
|
||||
virtual ~SleighSymbol(void) {}
|
||||
const string &getName(void) const { return name; }
|
||||
uintm getId(void) const { return id; }
|
||||
virtual symbol_type getType(void) const { return dummy_symbol; }
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
void restoreXmlHeader(const Element *el);
|
||||
virtual void saveXml(ostream &s) const {}
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans) {}
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
void decodeHeader(Decoder &decoder);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
struct SymbolCompare {
|
||||
@@ -92,9 +92,9 @@ public:
|
||||
SleighSymbol *findGlobalSymbol(const string &nm) const { return findSymbolInternal(table[0],nm); }
|
||||
SleighSymbol *findSymbol(uintm id) const { return symbollist[id]; }
|
||||
void replaceSymbol(SleighSymbol *a,SleighSymbol *b);
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,SleighBase *trans);
|
||||
void restoreSymbolHeader(const Element *el);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder,SleighBase *trans);
|
||||
void decodeSymbolHeader(Decoder &decoder);
|
||||
void purge(void);
|
||||
};
|
||||
|
||||
@@ -127,20 +127,19 @@ public:
|
||||
int4 getDefineCount(void) const { return define_count; }
|
||||
int4 getRefCount(void) const { return ref_count; }
|
||||
virtual symbol_type getType(void) const { return section_symbol; }
|
||||
// Not saved or restored
|
||||
};
|
||||
|
||||
class UserOpSymbol : public SleighSymbol { // A user-defined pcode-op
|
||||
uint4 index;
|
||||
public:
|
||||
UserOpSymbol(void) {} // For use with restoreXml
|
||||
UserOpSymbol(void) {} // For use with decode
|
||||
UserOpSymbol(const string &nm) : SleighSymbol(nm) { index = 0; }
|
||||
void setIndex(uint4 ind) { index = ind; }
|
||||
uint4 getIndex(void) const { return index; }
|
||||
virtual symbol_type getType(void) const { return userop_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class Constructor; // Forward declaration
|
||||
@@ -174,33 +173,31 @@ public:
|
||||
class PatternlessSymbol : public SpecificSymbol { // Behaves like constant 0 pattern
|
||||
ConstantValue *patexp;
|
||||
public:
|
||||
PatternlessSymbol(void); // For use with restoreXml
|
||||
PatternlessSymbol(void); // For use with decode
|
||||
PatternlessSymbol(const string &nm);
|
||||
virtual ~PatternlessSymbol(void);
|
||||
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
|
||||
AddrSpace *const_space;
|
||||
public:
|
||||
EpsilonSymbol(void) {} // For use with restoreXml
|
||||
EpsilonSymbol(void) {} // For use with decode
|
||||
EpsilonSymbol(const string &nm,AddrSpace *spc) : PatternlessSymbol(nm) { const_space=spc; }
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return epsilon_symbol; }
|
||||
virtual VarnodeTpl *getVarnode(void) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class ValueSymbol : public FamilySymbol {
|
||||
protected:
|
||||
PatternValue *patval;
|
||||
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);
|
||||
virtual ~ValueSymbol(void);
|
||||
virtual PatternValue *getPatternValue(void) const { return patval; }
|
||||
@@ -208,9 +205,9 @@ public:
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return value_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class ValueMapSymbol : public ValueSymbol {
|
||||
@@ -218,15 +215,15 @@ class ValueMapSymbol : public ValueSymbol {
|
||||
bool tableisfilled;
|
||||
void checkTableFill(void);
|
||||
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(); }
|
||||
virtual Constructor *resolve(ParserWalker &walker);
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return valuemap_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class NameSymbol : public ValueSymbol {
|
||||
@@ -234,21 +231,21 @@ class NameSymbol : public ValueSymbol {
|
||||
bool tableisfilled;
|
||||
void checkTableFill(void);
|
||||
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(); }
|
||||
virtual Constructor *resolve(ParserWalker &walker);
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return name_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class VarnodeSymbol : public PatternlessSymbol { // A global varnode
|
||||
VarnodeData fix;
|
||||
bool context_bits;
|
||||
public:
|
||||
VarnodeSymbol(void) {} // For use with restoreXml
|
||||
VarnodeSymbol(void) {} // For use with decode
|
||||
VarnodeSymbol(const string &nm,AddrSpace *base,uintb offset,int4 size);
|
||||
void markAsContext(void) { context_bits = true; }
|
||||
const VarnodeData &getFixedVarnode(void) const { return fix; }
|
||||
@@ -259,9 +256,9 @@ public:
|
||||
s << getName(); }
|
||||
virtual void collectLocalValues(vector<uintb> &results) const;
|
||||
virtual symbol_type getType(void) const { return varnode_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
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 numbits; // number of bits in the range
|
||||
public:
|
||||
BitrangeSymbol(void) {} // For use with restoreXml
|
||||
BitrangeSymbol(void) {} // For use with decode
|
||||
BitrangeSymbol(const string &nm,VarnodeSymbol *sym,uint4 bitoff,uint4 num)
|
||||
: SleighSymbol(nm) { varsym=sym; bitoffset=bitoff; numbits=num; }
|
||||
VarnodeSymbol *getParentSymbol(void) const { return varsym; }
|
||||
@@ -283,16 +280,16 @@ class ContextSymbol : public ValueSymbol {
|
||||
uint4 low,high; // into a varnode
|
||||
bool flow;
|
||||
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);
|
||||
VarnodeSymbol *getVarnode(void) const { return vn; }
|
||||
uint4 getLow(void) const { return low; }
|
||||
uint4 getHigh(void) const { return high; }
|
||||
bool getFlow(void) const { return flow; }
|
||||
virtual symbol_type getType(void) const { return context_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class VarnodeListSymbol : public ValueSymbol {
|
||||
@@ -300,16 +297,16 @@ class VarnodeListSymbol : public ValueSymbol {
|
||||
bool tableisfilled;
|
||||
void checkTableFill(void);
|
||||
public:
|
||||
VarnodeListSymbol(void) {} // For use with restoreXml
|
||||
VarnodeListSymbol(void) {} // For use with decode
|
||||
VarnodeListSymbol(const string &nm,PatternValue *pv,const vector<SleighSymbol *> &vt);
|
||||
virtual Constructor *resolve(ParserWalker &walker);
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual int4 getSize(void) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return varnodelist_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class OperandSymbol : public SpecificSymbol {
|
||||
@@ -329,7 +326,7 @@ private:
|
||||
void setVariableLength(void) { flags |= variable_len; }
|
||||
bool isVariableLength(void) const { return ((flags&variable_len)!=0); }
|
||||
public:
|
||||
OperandSymbol(void) {} // For use with restoreXml
|
||||
OperandSymbol(void) {} // For use with decode
|
||||
OperandSymbol(const string &nm,int4 index,Constructor *ct);
|
||||
uint4 getRelativeOffset(void) const { return reloffset; }
|
||||
int4 getOffsetBase(void) const { return offsetbase; }
|
||||
@@ -354,16 +351,16 @@ public:
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual void collectLocalValues(vector<uintb> &results) const;
|
||||
virtual symbol_type getType(void) const { return operand_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class StartSymbol : public SpecificSymbol {
|
||||
AddrSpace *const_space;
|
||||
PatternExpression *patexp;
|
||||
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);
|
||||
virtual ~StartSymbol(void);
|
||||
virtual VarnodeTpl *getVarnode(void) const;
|
||||
@@ -371,16 +368,16 @@ public:
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
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);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class EndSymbol : public SpecificSymbol {
|
||||
AddrSpace *const_space;
|
||||
PatternExpression *patexp;
|
||||
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);
|
||||
virtual ~EndSymbol(void);
|
||||
virtual VarnodeTpl *getVarnode(void) const;
|
||||
@@ -388,16 +385,16 @@ public:
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return end_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class Next2Symbol : public SpecificSymbol {
|
||||
AddrSpace *const_space;
|
||||
PatternExpression *patexp;
|
||||
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);
|
||||
virtual ~Next2Symbol(void);
|
||||
virtual VarnodeTpl *getVarnode(void) const;
|
||||
@@ -405,47 +402,41 @@ public:
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
virtual symbol_type getType(void) const { return next2_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class FlowDestSymbol : public SpecificSymbol {
|
||||
AddrSpace *const_space;
|
||||
public:
|
||||
FlowDestSymbol(void) {} // For use with restoreXml
|
||||
FlowDestSymbol(void) {} // For use with decode
|
||||
FlowDestSymbol(const string &nm,AddrSpace *cspc);
|
||||
virtual VarnodeTpl *getVarnode(void) const;
|
||||
virtual PatternExpression *getPatternExpression(void) const { throw SleighError("Cannot use symbol in pattern"); }
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
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 {
|
||||
AddrSpace *const_space;
|
||||
public:
|
||||
FlowRefSymbol(void) {} // For use with restoreXml
|
||||
FlowRefSymbol(void) {} // For use with decode
|
||||
FlowRefSymbol(const string &nm,AddrSpace *cspc);
|
||||
virtual VarnodeTpl *getVarnode(void) const;
|
||||
virtual PatternExpression *getPatternExpression(void) const { throw SleighError("Cannot use symbol in pattern"); }
|
||||
virtual void getFixedHandle(FixedHandle &hand,ParserWalker &walker) const;
|
||||
virtual void print(ostream &s,ParserWalker &walker) const;
|
||||
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
|
||||
public:
|
||||
virtual ~ContextChange(void) {}
|
||||
virtual void validate(void) const=0;
|
||||
virtual void saveXml(ostream &s) const=0;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans)=0;
|
||||
virtual void encode(Encoder &encoder) const=0;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans)=0;
|
||||
virtual void apply(ParserWalkerChange &walker) 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
|
||||
public:
|
||||
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 void validate(void) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
virtual void apply(ParserWalkerChange &walker) const;
|
||||
virtual ContextChange *clone(void) const;
|
||||
};
|
||||
@@ -472,11 +463,11 @@ class ContextCommit : public ContextChange {
|
||||
uintm mask; // mask of bits in word being committed
|
||||
bool flow; // Whether the context "flows" from the point of change
|
||||
public:
|
||||
ContextCommit(void) {} // For use with restoreXml
|
||||
ContextCommit(void) {} // For use with decode
|
||||
ContextCommit(TripleSymbol *s,int4 sbit,int4 ebit,bool fl);
|
||||
virtual void validate(void) const {}
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
virtual void apply(ParserWalkerChange &walker) 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
|
||||
void orderOperands(void);
|
||||
public:
|
||||
Constructor(void); // For use with restoreXml
|
||||
Constructor(void); // For use with decode
|
||||
Constructor(SubtableSymbol *p);
|
||||
~Constructor(void);
|
||||
TokenPattern *buildPattern(ostream &s);
|
||||
@@ -542,8 +533,8 @@ public:
|
||||
void setError(bool val) const { inerror = val; }
|
||||
bool isError(void) const { return inerror; }
|
||||
bool isRecursive(void) const;
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,SleighBase *trans);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class DecisionProperties {
|
||||
@@ -569,15 +560,15 @@ class DecisionNode {
|
||||
int4 getMaximumLength(bool context);
|
||||
void consistentValues(vector<uint4> &bins,DisjointPattern *pat);
|
||||
public:
|
||||
DecisionNode(void) {} // For use with restoreXml
|
||||
DecisionNode(void) {} // For use with decode
|
||||
DecisionNode(DecisionNode *p);
|
||||
~DecisionNode(void);
|
||||
Constructor *resolve(ParserWalker &walker) const;
|
||||
void addConstructorPair(const DisjointPattern *pat,Constructor *ct);
|
||||
void split(DecisionProperties &props);
|
||||
void orderPatterns(DecisionProperties &props);
|
||||
void saveXml(ostream &s) const;
|
||||
void restoreXml(const Element *el,DecisionNode *par,SubtableSymbol *sub);
|
||||
void encode(Encoder &encoder) const;
|
||||
void decode(Decoder &decoder,DecisionNode *par,SubtableSymbol *sub);
|
||||
};
|
||||
|
||||
class SubtableSymbol : public TripleSymbol {
|
||||
@@ -586,7 +577,7 @@ class SubtableSymbol : public TripleSymbol {
|
||||
vector<Constructor *> construct; // All the Constructors in this table
|
||||
DecisionNode *decisiontree;
|
||||
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);
|
||||
virtual ~SubtableSymbol(void);
|
||||
bool isBeingBuilt(void) const { return beingbuilt; }
|
||||
@@ -606,9 +597,9 @@ public:
|
||||
throw SleighError("Cannot use subtable in expression"); }
|
||||
virtual void collectLocalValues(vector<uintb> &results) const;
|
||||
virtual symbol_type getType(void) const { return subtable_symbol; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void saveXmlHeader(ostream &s) const;
|
||||
virtual void restoreXml(const Element *el,SleighBase *trans);
|
||||
virtual void encode(Encoder &encoder) const;
|
||||
virtual void encodeHeader(Encoder &encoder) const;
|
||||
virtual void decode(Decoder &decoder,SleighBase *trans);
|
||||
};
|
||||
|
||||
class MacroSymbol : public SleighSymbol { // A user-defined pcode-macro
|
||||
|
||||
@@ -45,13 +45,15 @@ void AddrSpace::calcScaleMask(void)
|
||||
/// \param t is the processor translator associated with the new space
|
||||
/// \param tp is the type of the new space (PROCESSOR, CONSTANT, INTERNAL,...)
|
||||
/// \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 ws is the number of bytes in an addressable unit
|
||||
/// \param ind is the integer identifier for the new space
|
||||
/// \param fl can be 0 or AddrSpace::hasphysical
|
||||
/// \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,
|
||||
uint4 size,uint4 ws, int4 ind,uint4 fl,int4 dl)
|
||||
/// \param dead is the number of rounds to delay before dead code removal
|
||||
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
|
||||
manage = m;
|
||||
@@ -62,13 +64,13 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
|
||||
wordsize = ws;
|
||||
index = ind;
|
||||
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
|
||||
shortcut = ' '; // Placeholder meaning shortcut is unassigned
|
||||
|
||||
// These are the flags we allow to be set from constructor
|
||||
flags = (fl & hasphysical);
|
||||
if (t->isBigEndian())
|
||||
if (bigEnd)
|
||||
flags |= big_endian;
|
||||
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
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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
|
||||
@@ -310,17 +294,6 @@ uintb AddrSpace::read(const string &s,int4 &size) const
|
||||
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
|
||||
/// this space. The processor translator, \e trans, and the
|
||||
/// \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 t is the associated processor translator
|
||||
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);
|
||||
if (HOST_ENDIAN==1) // Endianness always matches host
|
||||
@@ -399,14 +372,6 @@ void ConstantSpace::printRaw(ostream &s,uintb offset) const
|
||||
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
|
||||
/// decoded either.
|
||||
void ConstantSpace::decode(Decoder &decoder)
|
||||
@@ -426,7 +391,7 @@ const int4 OtherSpace::INDEX = 1;
|
||||
/// \param t is the associated processor translator
|
||||
/// \param ind is the integer identifier
|
||||
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);
|
||||
setFlags(is_otherspace);
|
||||
@@ -445,14 +410,6 @@ void OtherSpace::printRaw(ostream &s,uintb offset) const
|
||||
s << "0x" << hex << offset;
|
||||
}
|
||||
|
||||
void OtherSpace::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
s << "<space_other";
|
||||
saveBasicAttributes(s);
|
||||
s << "/>\n";
|
||||
}
|
||||
|
||||
const string UniqueSpace::NAME = "unique";
|
||||
|
||||
const uint4 UniqueSpace::SIZE = 4;
|
||||
@@ -465,7 +422,7 @@ const uint4 UniqueSpace::SIZE = 4;
|
||||
/// \param ind is the integer identifier
|
||||
/// \param fl are attribute flags (currently unused)
|
||||
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);
|
||||
}
|
||||
@@ -476,14 +433,6 @@ UniqueSpace::UniqueSpace(AddrSpaceManager *m,const Translate *t)
|
||||
setFlags(hasphysical);
|
||||
}
|
||||
|
||||
void UniqueSpace::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
s << "<space_unique";
|
||||
saveBasicAttributes(s);
|
||||
s << "/>\n";
|
||||
}
|
||||
|
||||
const string JoinSpace::NAME = "join";
|
||||
|
||||
/// 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 ind is the integer identifier
|
||||
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
|
||||
// setFlags(hasphysical);
|
||||
@@ -691,12 +640,6 @@ uintb JoinSpace::read(const string &s,int4 &size) const
|
||||
return rec->getUnified().offset;
|
||||
}
|
||||
|
||||
void JoinSpace::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
throw LowlevelError("Should never save join space to XML");
|
||||
}
|
||||
|
||||
void JoinSpace::decode(Decoder &decoder)
|
||||
|
||||
{
|
||||
@@ -712,16 +655,6 @@ OverlaySpace::OverlaySpace(AddrSpaceManager *m,const Translate *t)
|
||||
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)
|
||||
|
||||
{
|
||||
|
||||
@@ -117,11 +117,11 @@ protected:
|
||||
void calcScaleMask(void); ///< Calculate scale and mask
|
||||
void setFlags(uint4 fl); ///< Set 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 truncateSpace(uint4 newsize);
|
||||
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
|
||||
virtual ~AddrSpace(void) {} ///< The address space destructor
|
||||
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 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 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 XML
|
||||
virtual void decode(Decoder &decoder); ///< Recover the details of this space from a stream
|
||||
|
||||
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
|
||||
@@ -190,7 +189,6 @@ public:
|
||||
ConstantSpace(AddrSpaceManager *m,const Translate *t); ///< Only constructor
|
||||
virtual int4 overlapJoin(uintb offset,int4 size,AddrSpace *pointSpace,uintb pointOff,int4 pointSkip) const;
|
||||
virtual void printRaw(ostream &s,uintb offset) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
static const string NAME; ///< Reserved name for the address 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); ///< For use with decode
|
||||
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 int4 INDEX; ///< Reserved index for the other space
|
||||
};
|
||||
@@ -220,7 +217,6 @@ class UniqueSpace : public AddrSpace {
|
||||
public:
|
||||
UniqueSpace(AddrSpaceManager *m,const Translate *t,int4 ind,uint4 fl); ///< Constructor
|
||||
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 uint4 SIZE; ///< Fixed size (in bytes) for unique space offsets
|
||||
};
|
||||
@@ -243,7 +239,6 @@ public:
|
||||
virtual uintb decodeAttributes(Decoder &decoder,uint4 &size) const;
|
||||
virtual void printRaw(ostream &s,uintb offset) const;
|
||||
virtual uintb read(const string &s,int4 &size) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
static const string NAME; ///< Reserved name for the join space
|
||||
};
|
||||
@@ -261,7 +256,6 @@ class OverlaySpace : public AddrSpace {
|
||||
public:
|
||||
OverlaySpace(AddrSpaceManager *m,const Translate *t); ///< Constructor
|
||||
virtual AddrSpace *getContain(void) const { return baseSpace; }
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ void TruncationTag::decode(Decoder &decoder)
|
||||
/// \param isFormal is the formal stack space indicator
|
||||
SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,int4 sz,
|
||||
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;
|
||||
hasbaseregister = false; // No base register assigned yet
|
||||
@@ -123,15 +123,6 @@ const VarnodeData &SpacebaseSpace::getSpacebaseFull(int4 i) const
|
||||
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)
|
||||
|
||||
{
|
||||
|
||||
@@ -185,7 +185,6 @@ public:
|
||||
virtual const VarnodeData &getSpacebaseFull(int4 i) const;
|
||||
virtual bool stackGrowsNegative(void) const { return isNegativeStack; }
|
||||
virtual AddrSpace *getContain(void) const { return contain; } ///< Return containing space
|
||||
virtual void saveXml(ostream &s) const;
|
||||
virtual void decode(Decoder &decoder);
|
||||
};
|
||||
|
||||
@@ -235,7 +234,7 @@ class AddrSpaceManager {
|
||||
vector<JoinRecord *> splitlist; ///< JoinRecords indexed by join address
|
||||
protected:
|
||||
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 setDefaultDataSpace(int4 index); ///< Set the default address space for data
|
||||
void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this space
|
||||
|
||||
@@ -598,8 +598,8 @@ const TypeField *Datatype::resolveTruncation(int8 offset,PcodeOp *op,int4 slot,i
|
||||
return (const TypeField *)0;
|
||||
}
|
||||
|
||||
/// Restore the basic properties (name,size,id) of a data-type from an XML element
|
||||
/// Properties are read from the attributes of the element
|
||||
/// Restore the basic properties (name,size,id) of a data-type from a stream.
|
||||
/// Properties are read from the attributes of the element.
|
||||
/// \param decoder is the stream decoder
|
||||
void Datatype::decodeBasic(Decoder &decoder)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
|
||||
static FuncProtoTestEnvironment theEnviron;
|
||||
|
||||
static Architecture *glb;
|
||||
static Architecture *glb = (Architecture *)0;
|
||||
|
||||
FuncProtoTestEnvironment::FuncProtoTestEnvironment(void)
|
||||
|
||||
@@ -46,7 +46,11 @@ FuncProtoTestEnvironment::FuncProtoTestEnvironment(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");
|
||||
istringstream s(
|
||||
"<binaryimage arch=\"Toy:LE:32:default:default\"></binaryimage>"
|
||||
|
||||
@@ -49,7 +49,7 @@ static MarshalTestEnvironment theEnviron;
|
||||
TestAddrSpaceManager::TestAddrSpaceManager(Translate *t)
|
||||
: 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)
|
||||
|
||||
10
Ghidra/Features/Decompiler/src/decompile/zlib/README.txt
Normal file
10
Ghidra/Features/Decompiler/src/decompile/zlib/README.txt
Normal 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.
|
||||
168
Ghidra/Features/Decompiler/src/decompile/zlib/adler32.c
Normal file
168
Ghidra/Features/Decompiler/src/decompile/zlib/adler32.c
Normal 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);
|
||||
}
|
||||
2143
Ghidra/Features/Decompiler/src/decompile/zlib/deflate.c
Normal file
2143
Ghidra/Features/Decompiler/src/decompile/zlib/deflate.c
Normal file
File diff suppressed because it is too large
Load Diff
381
Ghidra/Features/Decompiler/src/decompile/zlib/deflate.h
Normal file
381
Ghidra/Features/Decompiler/src/decompile/zlib/deflate.h
Normal 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 */
|
||||
218
Ghidra/Features/Decompiler/src/decompile/zlib/gzguts.h
Normal file
218
Ghidra/Features/Decompiler/src/decompile/zlib/gzguts.h
Normal 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())
|
||||
324
Ghidra/Features/Decompiler/src/decompile/zlib/inffast.c
Normal file
324
Ghidra/Features/Decompiler/src/decompile/zlib/inffast.c
Normal 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 */
|
||||
15
Ghidra/Features/Decompiler/src/decompile/zlib/inffast.h
Normal file
15
Ghidra/Features/Decompiler/src/decompile/zlib/inffast.h
Normal 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);
|
||||
98
Ghidra/Features/Decompiler/src/decompile/zlib/inffixed.h
Normal file
98
Ghidra/Features/Decompiler/src/decompile/zlib/inffixed.h
Normal 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}
|
||||
};
|
||||
1530
Ghidra/Features/Decompiler/src/decompile/zlib/inflate.c
Normal file
1530
Ghidra/Features/Decompiler/src/decompile/zlib/inflate.c
Normal file
File diff suppressed because it is too large
Load Diff
130
Ghidra/Features/Decompiler/src/decompile/zlib/inflate.h
Normal file
130
Ghidra/Features/Decompiler/src/decompile/zlib/inflate.h
Normal 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 */
|
||||
};
|
||||
303
Ghidra/Features/Decompiler/src/decompile/zlib/inftrees.c
Normal file
303
Ghidra/Features/Decompiler/src/decompile/zlib/inftrees.c
Normal 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;
|
||||
}
|
||||
66
Ghidra/Features/Decompiler/src/decompile/zlib/inftrees.h
Normal file
66
Ghidra/Features/Decompiler/src/decompile/zlib/inftrees.h
Normal 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);
|
||||
1121
Ghidra/Features/Decompiler/src/decompile/zlib/trees.c
Normal file
1121
Ghidra/Features/Decompiler/src/decompile/zlib/trees.c
Normal file
File diff suppressed because it is too large
Load Diff
132
Ghidra/Features/Decompiler/src/decompile/zlib/trees.h
Normal file
132
Ghidra/Features/Decompiler/src/decompile/zlib/trees.h
Normal 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
|
||||
};
|
||||
|
||||
547
Ghidra/Features/Decompiler/src/decompile/zlib/zconf.h
Normal file
547
Ghidra/Features/Decompiler/src/decompile/zlib/zconf.h
Normal 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 */
|
||||
1942
Ghidra/Features/Decompiler/src/decompile/zlib/zlib.h
Normal file
1942
Ghidra/Features/Decompiler/src/decompile/zlib/zlib.h
Normal file
File diff suppressed because it is too large
Load Diff
303
Ghidra/Features/Decompiler/src/decompile/zlib/zutil.c
Normal file
303
Ghidra/Features/Decompiler/src/decompile/zlib/zutil.c
Normal 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 */
|
||||
258
Ghidra/Features/Decompiler/src/decompile/zlib/zutil.h
Normal file
258
Ghidra/Features/Decompiler/src/decompile/zlib/zutil.h
Normal 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 */
|
||||
@@ -84,10 +84,10 @@ public class DecompInterface {
|
||||
|
||||
public static class EncodeDecodeSet {
|
||||
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 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
|
||||
@@ -95,10 +95,10 @@ public class DecompInterface {
|
||||
*/
|
||||
public EncodeDecodeSet(Program program) {
|
||||
overlay = null;
|
||||
mainQuery = new PackedEncode();
|
||||
mainQuery = new PatchPackedEncode();
|
||||
mainResponse = 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();
|
||||
}
|
||||
long uniqueBase = UniqueLayout.SLEIGH_BASE.getOffset(pcodelanguage);
|
||||
XmlEncode xmlEncode = new XmlEncode();
|
||||
XmlEncode xmlEncode = new XmlEncode(false);
|
||||
pcodelanguage.encodeTranslator(xmlEncode, program.getAddressFactory(), uniqueBase);
|
||||
String tspec = xmlEncode.toString();
|
||||
xmlEncode.clear();
|
||||
|
||||
@@ -208,7 +208,7 @@ public class DecompileCallback {
|
||||
* @param addr is the given address
|
||||
* @param resultEncoder will contain the generated p-code ops
|
||||
*/
|
||||
public void getPcode(Address addr, PackedEncode resultEncoder) {
|
||||
public void getPcode(Address addr, PatchEncoder resultEncoder) {
|
||||
try {
|
||||
Instruction instr = getInstruction(addr);
|
||||
if (instr == null) {
|
||||
|
||||
@@ -77,7 +77,7 @@ public class DecompileProcess {
|
||||
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 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
|
||||
|
||||
public enum DisposeState {
|
||||
@@ -202,7 +202,7 @@ public class DecompileProcess {
|
||||
private int readToBuffer(ByteIngest buf) throws IOException {
|
||||
int cur;
|
||||
for (;;) {
|
||||
buf.ingestStream(nativeIn);
|
||||
buf.ingestStreamToNextTerminator(nativeIn);
|
||||
do {
|
||||
cur = nativeIn.read();
|
||||
}
|
||||
@@ -239,7 +239,7 @@ public class DecompileProcess {
|
||||
write(string_end);
|
||||
}
|
||||
|
||||
private void writeString(Encoder byteResult) throws IOException {
|
||||
private void writeString(CachedEncoder byteResult) throws IOException {
|
||||
if (nativeOut == null) {
|
||||
return;
|
||||
}
|
||||
@@ -426,7 +426,7 @@ public class DecompileProcess {
|
||||
// Decompiler process may callback during the registerProgram operation
|
||||
// so provide query/reponse decoding/encoding
|
||||
paramDecoder = new PackedDecode(program.getAddressFactory());
|
||||
resultEncoder = new PackedEncode();
|
||||
resultEncoder = new PatchPackedEncode();
|
||||
|
||||
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 DecompileException for problems executing the command
|
||||
*/
|
||||
public synchronized void sendCommand1Param(String command, Encoder param1, ByteIngest response)
|
||||
throws IOException, DecompileException {
|
||||
public synchronized void sendCommand1Param(String command, CachedEncoder param1,
|
||||
ByteIngest response) throws IOException, DecompileException {
|
||||
if (!statusGood) {
|
||||
throw new IOException(command + " called on bad process");
|
||||
}
|
||||
|
||||
@@ -15,20 +15,19 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.jdom.JDOMException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.Msg;
|
||||
import resources.ResourceManager;
|
||||
|
||||
@@ -42,7 +41,7 @@ public class SleighLanguageHelper {
|
||||
}
|
||||
|
||||
public static SleighLanguage getMockBE64Language()
|
||||
throws UnknownInstructionException, SAXException, IOException {
|
||||
throws DecoderException, UnknownInstructionException, SAXException, IOException {
|
||||
|
||||
ResourceFile cSpecFile = getResourceFile("mock.cpsec");
|
||||
CompilerSpecDescription cSpecDesc =
|
||||
@@ -59,7 +58,7 @@ public class SleighLanguageHelper {
|
||||
assertEquals("Failed to compile mock.slaspec", 0,
|
||||
SleighCompileLauncher.runMain(new String[] { slaSpecFile.getAbsolutePath() }));
|
||||
}
|
||||
catch (JDOMException | IOException | RecognitionException e) {
|
||||
catch (IOException | RecognitionException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
slaFile = getResourceFile("mock.sla");
|
||||
@@ -67,19 +66,15 @@ public class SleighLanguageHelper {
|
||||
}
|
||||
|
||||
SleighLanguageDescription langDesc = new SleighLanguageDescription(
|
||||
new LanguageID("Mock:BE:64:default"),
|
||||
"Mock language (64-bit BE)",
|
||||
Processor.findOrPossiblyCreateProcessor("Mock"),
|
||||
Endian.BIG, // endian
|
||||
new LanguageID("Mock:BE:64:default"), "Mock language (64-bit BE)",
|
||||
Processor.findOrPossiblyCreateProcessor("Mock"), Endian.BIG, // endian
|
||||
Endian.BIG, // instructionEndian
|
||||
64,
|
||||
"default", // variant
|
||||
64, "default", // variant
|
||||
0, // major version
|
||||
0, // minor version
|
||||
false, // deprecated
|
||||
new HashMap<>(), // truncatedSpaceMap
|
||||
new ArrayList<>(List.of(cSpecDesc)),
|
||||
new HashMap<>() // externalNames
|
||||
new ArrayList<>(List.of(cSpecDesc)), new HashMap<>() // externalNames
|
||||
);
|
||||
langDesc.setDefsFile(lDefsFile);
|
||||
langDesc.setSpecFile(pSpecFile);
|
||||
|
||||
@@ -19,21 +19,18 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.*;
|
||||
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
|
||||
import ghidra.app.plugin.processors.sleigh.template.HandleTpl;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The primary sleigh concept representing a semantic action
|
||||
* taking operands (semantic values) as input
|
||||
* producing a semantic value as output
|
||||
@@ -313,65 +310,59 @@ public class Constructor implements Comparable<Constructor> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh)
|
||||
throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("constructor");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONSTRUCTOR);
|
||||
SymbolTable symtab = sleigh.getSymbolTable();
|
||||
|
||||
int myId = SpecXmlUtils.decodeInt(el.getAttribute("parent"));
|
||||
int myId = (int) decoder.readUnsignedInteger(ATTRIB_PARENT);
|
||||
parent = (SubtableSymbol) symtab.findSymbol(myId);
|
||||
firstwhitespace = SpecXmlUtils.decodeInt(el.getAttribute("first"));
|
||||
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("length"));
|
||||
String sourceAndLine = el.getAttribute("line");
|
||||
String[] parts = sourceAndLine.split(":");
|
||||
if (parts.length != 2) {
|
||||
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()));
|
||||
}
|
||||
firstwhitespace = (int) decoder.readSignedInteger(ATTRIB_FIRST);
|
||||
minimumlength = (int) decoder.readSignedInteger(ATTRIB_LENGTH);
|
||||
int srcLine = (int) decoder.readSignedInteger(ATTRIB_SOURCE);
|
||||
lineno = (int) decoder.readSignedInteger(ATTRIB_LINE);
|
||||
sourceFile = sleigh.getSourceFileIndexer().getFileName(srcLine);
|
||||
|
||||
ArrayList<Object> oplist = new ArrayList<>();
|
||||
ArrayList<Object> piecelist = new ArrayList<>();
|
||||
ArrayList<Object> coplist = new ArrayList<>();
|
||||
XmlElement subel = parser.peek();
|
||||
while (!subel.getName().equals("constructor")) {
|
||||
if (subel.getName().equals("oper")) {
|
||||
myId = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
int subel = decoder.peekElement();
|
||||
while (subel != 0) {
|
||||
if (subel == ELEM_OPER.id()) {
|
||||
decoder.openElement();
|
||||
myId = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
oplist.add(symtab.findSymbol(myId));
|
||||
parser.discardSubTree();
|
||||
decoder.closeElementSkipping(subel);
|
||||
}
|
||||
else if (subel.getName().equals("print")) {
|
||||
piecelist.add(subel.getAttribute("piece"));
|
||||
parser.discardSubTree();
|
||||
else if (subel == ELEM_PRINT.id()) {
|
||||
decoder.openElement();
|
||||
piecelist.add(decoder.readString(ATTRIB_PIECE));
|
||||
decoder.closeElementSkipping(subel);
|
||||
}
|
||||
else if (subel.getName().equals("opprint")) {
|
||||
myId = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
else if (subel == ELEM_OPPRINT.id()) {
|
||||
decoder.openElement();
|
||||
myId = (int) decoder.readSignedInteger(ATTRIB_ID);
|
||||
String operstring = "\n";
|
||||
char ind = (char) ('A' + myId);
|
||||
operstring += ind;
|
||||
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();
|
||||
c_op.restoreXml(parser, sleigh);
|
||||
c_op.decode(decoder, sleigh);
|
||||
coplist.add(c_op);
|
||||
}
|
||||
else if (subel.getName().equals("commit")) {
|
||||
else if (subel == ELEM_COMMIT.id()) {
|
||||
ContextCommit c_op = new ContextCommit();
|
||||
c_op.restoreXml(parser, sleigh);
|
||||
c_op.decode(decoder, sleigh);
|
||||
coplist.add(c_op);
|
||||
}
|
||||
else {
|
||||
ConstructTpl curtempl = new ConstructTpl();
|
||||
int sectionid = curtempl.restoreXml(parser, sleigh.getAddressFactory());
|
||||
int sectionid = curtempl.decode(decoder);
|
||||
if (sectionid < 0) {
|
||||
if (templ != null) {
|
||||
throw new UnknownInstructionException("Duplicate main template section");
|
||||
throw new DecoderException("Duplicate main template section");
|
||||
}
|
||||
templ = curtempl;
|
||||
}
|
||||
@@ -383,12 +374,12 @@ public class Constructor implements Comparable<Constructor> {
|
||||
namedtempl.add(null);
|
||||
}
|
||||
if (namedtempl.get(sectionid) != null) {
|
||||
throw new UnknownInstructionException("Duplicate named template section");
|
||||
throw new DecoderException("Duplicate named template section");
|
||||
}
|
||||
namedtempl.set(sectionid, curtempl);
|
||||
}
|
||||
}
|
||||
subel = parser.peek();
|
||||
subel = decoder.peekElement();
|
||||
}
|
||||
operands = new OperandSymbol[oplist.size()];
|
||||
separators = new String[operands.length + 1];
|
||||
@@ -404,7 +395,7 @@ public class Constructor implements Comparable<Constructor> {
|
||||
else {
|
||||
flowthruindex = -1;
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,10 +423,6 @@ public class Constructor implements Comparable<Constructor> {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* ***************************** *
|
||||
* Get these working as map keys *
|
||||
* ***************************** */
|
||||
|
||||
@Override
|
||||
public int compareTo(Constructor that) {
|
||||
int result;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +16,11 @@
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
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 {
|
||||
void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException;
|
||||
void restoreXml(XmlPullParser parser,SleighLanguage lang);
|
||||
|
||||
void decode(Decoder decoder, SleighLanguage lang) throws DecoderException;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,11 +15,12 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
public class ContextCommit implements ContextChange {
|
||||
|
||||
@@ -32,6 +32,7 @@ public class ContextCommit implements ContextChange {
|
||||
sym = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException {
|
||||
walker.getParserContext().addCommit(walker.getState(), sym, num, mask);
|
||||
if (debug != null) {
|
||||
@@ -40,13 +41,14 @@ public class ContextCommit implements ContextChange {
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("commit");
|
||||
int id = SpecXmlUtils.decodeInt(el.getAttribute("id"));
|
||||
@Override
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_COMMIT);
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
sym = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
|
||||
num = SpecXmlUtils.decodeInt(el.getAttribute("num"));
|
||||
mask = SpecXmlUtils.decodeInt(el.getAttribute("mask"));
|
||||
parser.end(el);
|
||||
num = (int) decoder.readSignedInteger(ATTRIB_NUMBER);
|
||||
mask = (int) decoder.readUnsignedInteger(ATTRIB_MASK);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,16 +19,15 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
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;
|
||||
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
|
||||
*/
|
||||
public class ContextOp implements ContextChange {
|
||||
@@ -51,13 +50,13 @@ public class ContextOp implements ContextChange {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("context_op");
|
||||
num = SpecXmlUtils.decodeInt(el.getAttribute("i"));
|
||||
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift"));
|
||||
mask = SpecXmlUtils.decodeInt(el.getAttribute("mask"));
|
||||
patexp = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONTEXT_OP);
|
||||
num = (int) decoder.readSignedInteger(ATTRIB_I);
|
||||
shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
|
||||
mask = (int) decoder.readUnsignedInteger(ATTRIB_MASK);
|
||||
patexp = PatternExpression.decodeExpression(decoder, lang);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public PatternExpression getPatternExpression() {
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.pattern.DisjointPattern;
|
||||
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.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A node in the decision tree for resolving a Constructor in
|
||||
* a SubtableSymbol based on the InstructionContext
|
||||
*/
|
||||
@@ -224,33 +219,33 @@ public class DecisionNode {
|
||||
// }
|
||||
// }
|
||||
|
||||
public void restoreXml(XmlPullParser parser, DecisionNode par, SubtableSymbol sub) {
|
||||
XmlElement el = parser.start("decision");
|
||||
// parent = par;
|
||||
// num = SpecXmlUtils.decodeInt(el.getAttributeValue("number"));
|
||||
contextdecision = SpecXmlUtils.decodeBoolean(el.getAttribute("context"));
|
||||
startbit = SpecXmlUtils.decodeInt(el.getAttribute("start"));
|
||||
bitsize = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
public void decode(Decoder decoder, DecisionNode par, SubtableSymbol sub)
|
||||
throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_DECISION);
|
||||
|
||||
contextdecision = decoder.readBool(ATTRIB_CONTEXT);
|
||||
startbit = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
|
||||
bitsize = (int) decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
|
||||
ArrayList<Object> patlist = new ArrayList<>();
|
||||
ArrayList<Object> conlist = new ArrayList<>();
|
||||
ArrayList<Object> childlist = new ArrayList<>();
|
||||
// num = 0;
|
||||
XmlElement subel = parser.peek();
|
||||
while (!subel.isEnd()) {
|
||||
if (subel.getName().equals("pair")) {
|
||||
XmlElement start = parser.start();
|
||||
int id = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
int subel = decoder.peekElement();
|
||||
while (subel != 0) {
|
||||
if (subel == ELEM_PAIR.id()) {
|
||||
decoder.openElement();
|
||||
int id = (int) decoder.readSignedInteger(ATTRIB_ID);
|
||||
conlist.add(sub.getConstructor(id));
|
||||
patlist.add(DisjointPattern.restoreDisjoint(parser));
|
||||
parser.end(start);
|
||||
patlist.add(DisjointPattern.decodeDisjoint(decoder));
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
else if (subel.getName().equals("decision")) {
|
||||
else if (subel == ELEM_DECISION.id()) {
|
||||
DecisionNode subnode = new DecisionNode();
|
||||
subnode.restoreXml(parser, this, sub);
|
||||
subnode.decode(decoder, this, sub);
|
||||
childlist.add(subnode);
|
||||
}
|
||||
subel = parser.peek();
|
||||
subel = decoder.peekElement();
|
||||
}
|
||||
patternlist = new DisjointPattern[patlist.size()];
|
||||
patlist.toArray(patternlist);
|
||||
@@ -258,7 +253,7 @@ public class DecisionNode {
|
||||
conlist.toArray(constructlist);
|
||||
children = new DecisionNode[childlist.size()];
|
||||
childlist.toArray(children);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
|
||||
unmodifiablePatternList = Collections.unmodifiableList(Arrays.asList(patternlist));
|
||||
unmodifiableConstructorList = Collections.unmodifiableList(Arrays.asList(constructlist));
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.program.model.pcode.AttributeId.*;
|
||||
import static ghidra.program.model.pcode.ElementId.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
@@ -26,7 +25,6 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.jdom.JDOMException;
|
||||
import org.xml.sax.*;
|
||||
|
||||
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.symbol.*;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcode.utils.SlaFormat;
|
||||
import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.DefaultProgramContext;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.ElementId;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.program.model.util.ProcessorSymbolType;
|
||||
import ghidra.sleigh.grammar.SleighPreprocessor;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
@@ -57,15 +54,6 @@ import utilities.util.FileUtilities;
|
||||
|
||||
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 HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
|
||||
private List<InjectPayloadSleigh> additionalInject = null;
|
||||
@@ -112,7 +100,7 @@ public class SleighLanguage implements Language {
|
||||
SortedMap<String, ManualEntry> manual = null;
|
||||
|
||||
SleighLanguage(SleighLanguageDescription description)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
throws DecoderException, SAXException, IOException {
|
||||
initialize(description);
|
||||
}
|
||||
|
||||
@@ -124,7 +112,7 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
|
||||
private void initialize(SleighLanguageDescription langDescription)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
throws DecoderException, SAXException, IOException {
|
||||
this.defaultSymbols = new ArrayList<>();
|
||||
this.compilerSpecDescriptions = new LinkedHashMap<>();
|
||||
for (CompilerSpecDescription compilerSpecDescription : langDescription
|
||||
@@ -151,7 +139,8 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
|
||||
// Read in the sleigh specification
|
||||
readSpecification(slaFile);
|
||||
PackedDecode decoder = SlaFormat.buildDecoder(slaFile);
|
||||
decode(decoder);
|
||||
|
||||
registerBuilder = new RegisterBuilder();
|
||||
loadRegisters(registerBuilder);
|
||||
@@ -177,42 +166,12 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
|
||||
private boolean isSLAWrongVersion(ResourceFile slaFile) {
|
||||
XmlPullParser parser = null;
|
||||
try {
|
||||
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);
|
||||
try (InputStream stream = slaFile.getInputStream()) {
|
||||
return !SlaFormat.isSlaFormat(stream);
|
||||
}
|
||||
catch (SAXException | IOException e) {
|
||||
catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
if (parser != null) {
|
||||
parser.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSLAStale(ResourceFile slaFile) {
|
||||
@@ -521,9 +480,6 @@ public class SleighLanguage implements Language {
|
||||
" -- please check log messages for details");
|
||||
}
|
||||
}
|
||||
catch (JDOMException e) {
|
||||
throw new IOException("JDOMException error recompiling: " + e.getMessage());
|
||||
}
|
||||
catch (RecognitionException e) {
|
||||
throw new IOException("RecognitionException error recompiling: " + e.getMessage());
|
||||
}
|
||||
@@ -533,10 +489,10 @@ public class SleighLanguage implements Language {
|
||||
try {
|
||||
initialize(description);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
catch (DecoderException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
catch (SAXException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -907,96 +863,104 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
}
|
||||
|
||||
private void readSpecification(final ResourceFile sleighfile)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
ErrorHandler errHandler = new ErrorHandler() {
|
||||
@Override
|
||||
public void error(SAXParseException exception) throws SAXException {
|
||||
Msg.error(SleighLanguage.this, "Error parsing " + sleighfile, exception);
|
||||
private void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_SLEIGH);
|
||||
int version = 0;
|
||||
uniqueBase = 0;
|
||||
alignment = 1;
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException exception) throws SAXException {
|
||||
Msg.error(SleighLanguage.this, "Fatal error parsing " + sleighfile, exception);
|
||||
else if (attrib == ATTRIB_BIGENDIAN.id()) {
|
||||
isBigEndian = decoder.readBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(SAXParseException exception) throws SAXException {
|
||||
Msg.warn(SleighLanguage.this, "Warning parsing " + sleighfile, exception);
|
||||
else if (attrib == ATTRIB_UNIQBASE.id()) {
|
||||
uniqueBase = decoder.readUnsignedInteger();
|
||||
}
|
||||
};
|
||||
XmlPullParser parser = XmlPullParserFactory.create(sleighfile, errHandler, false);
|
||||
try {
|
||||
restoreXml(parser);
|
||||
else if (attrib == ATTRIB_ALIGN.id()) {
|
||||
alignment = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_UNIQMASK.id()) {
|
||||
uniqueAllocateMask = (int) decoder.readUnsignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_NUMSECTIONS.id()) {
|
||||
numSections = (int) decoder.readUnsignedInteger();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
finally {
|
||||
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) {
|
||||
if (version != FORMAT_VERSION) {
|
||||
throw new SleighException(".sla file for " + getLanguageID() + " has the wrong format");
|
||||
}
|
||||
String endianAttr = el.getAttribute("bigendian");
|
||||
Endian slaEndian = SpecXmlUtils.decodeBoolean(endianAttr) ? Endian.BIG : Endian.LITTLE;
|
||||
Endian slaEndian = isBigEndian ? Endian.BIG : Endian.LITTLE;
|
||||
Endian ldefEndian = description.getEndian();
|
||||
Endian instEndian = description.getInstructionEndian();
|
||||
if (slaEndian != ldefEndian && instEndian == ldefEndian) {
|
||||
throw new SleighException(".ldefs says " + getLanguageID() + " is " + ldefEndian +
|
||||
" 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.restoreXml(parser);
|
||||
parseSpaces(parser);
|
||||
indexer.decode(decoder);
|
||||
parseSpaces(decoder);
|
||||
symtab = new SymbolTable();
|
||||
symtab.restoreXml(parser, this);
|
||||
symtab.decode(decoder, this);
|
||||
root =
|
||||
((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();
|
||||
int truncatedSpaceCnt = truncatedSpaceNames.size();
|
||||
XmlElement el = parser.start("spaces");
|
||||
String defname = el.getAttribute("defaultspace");
|
||||
int el = decoder.openElement(ELEM_SPACES);
|
||||
String defname = decoder.readString(ATTRIB_DEFAULTSPACE);
|
||||
spacetable = new LinkedHashMap<>();
|
||||
// Slot zero is always the constant space
|
||||
AddressSpace constspc = new GenericAddressSpace(SpaceNames.CONSTANT_SPACE_NAME, 64,
|
||||
AddressSpace.TYPE_CONSTANT, SpaceNames.CONSTANT_SPACE_INDEX);
|
||||
spacetable.put(SpaceNames.CONSTANT_SPACE_NAME, constspc);
|
||||
default_space = null;
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("space_other")) { // tag must be present
|
||||
parser.discardSubTree(); // We don't process it
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == ELEM_SPACE_OTHER.id()) { // tag must be present
|
||||
decoder.openElement();
|
||||
decoder.closeElementSkipping(subel); // We don't process it
|
||||
// Instead the ProgramAddressFactory maps in the static OTHER_SPACE automatically
|
||||
}
|
||||
else {
|
||||
throw new SleighException(".sla file missing required OTHER space tag");
|
||||
}
|
||||
while ((subel = parser.softStart("space", "space_unique")) != null) {
|
||||
String name = subel.getAttribute("name");
|
||||
int index = SpecXmlUtils.decodeInt(subel.getAttribute("index"));
|
||||
String typename = subel.getName();
|
||||
int delay = SpecXmlUtils.decodeInt(subel.getAttribute("delay"));
|
||||
int size = SpecXmlUtils.decodeInt(subel.getAttribute("size"));
|
||||
|
||||
int type = AddressSpace.TYPE_UNKNOWN;
|
||||
if (typename.equals("space")) {
|
||||
while (decoder.peekElement() != 0) {
|
||||
int wordsize = 1;
|
||||
String name = null;
|
||||
int index = 0;
|
||||
int delay = -1;
|
||||
int size = 0;
|
||||
subel = decoder.openElement();
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
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) {
|
||||
type = AddressSpace.TYPE_RAM;
|
||||
}
|
||||
@@ -1004,19 +968,13 @@ public class SleighLanguage implements Language {
|
||||
type = AddressSpace.TYPE_REGISTER;
|
||||
}
|
||||
}
|
||||
else if (typename.equals("space_unique")) {
|
||||
else if (subel == ELEM_SPACE_UNIQUE.id()) {
|
||||
type = AddressSpace.TYPE_UNIQUE;
|
||||
}
|
||||
if (type == AddressSpace.TYPE_UNKNOWN) {
|
||||
else {
|
||||
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);
|
||||
if (truncateSpace && type != AddressSpace.TYPE_RAM) {
|
||||
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);
|
||||
}
|
||||
spacetable.put(name, spc);
|
||||
parser.end(subel);
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
if (truncatedSpaceCnt > 0) {
|
||||
throw new SleighException(
|
||||
@@ -1058,7 +1016,8 @@ public class SleighLanguage implements Language {
|
||||
defaultDataSpace = default_space;
|
||||
defaultPointerWordSize = defaultDataSpace.getAddressableUnitSize();
|
||||
buildAddressSpaceFactory();
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
decoder.setAddressFactory(addressFactory);
|
||||
}
|
||||
|
||||
void buildAddressSpaceFactory() {
|
||||
@@ -1454,11 +1413,16 @@ public class SleighLanguage implements Language {
|
||||
throws IOException {
|
||||
AddressSpace[] spclist = factory.getAllAddressSpaces();
|
||||
|
||||
encoder.openElement(ELEM_SLEIGH);
|
||||
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeUnsignedInteger(ATTRIB_UNIQBASE, uniqueOffset);
|
||||
encoder.openElement(ELEM_SPACES);
|
||||
encoder.writeString(ATTRIB_DEFAULTSPACE, factory.getDefaultAddressSpace().getName());
|
||||
// WARNING
|
||||
// ELEM_ and ATTRIB_ symbols in this method all come from the AttributeId and ElementId
|
||||
// namespace, some of which conflict with other ELEM_ and ATTRIB_ symbols used in this file
|
||||
|
||||
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;
|
||||
int delay;
|
||||
@@ -1467,31 +1431,31 @@ public class SleighLanguage implements Language {
|
||||
for (AddressSpace element : spclist) {
|
||||
if ((element instanceof OverlayAddressSpace)) {
|
||||
OverlayAddressSpace ospace = (OverlayAddressSpace) element;
|
||||
encoder.openElement(ELEM_SPACE_OVERLAY);
|
||||
encoder.writeString(ATTRIB_NAME, ospace.getName());
|
||||
encoder.writeSignedInteger(ATTRIB_INDEX, ospace.getUnique());
|
||||
encoder.writeSpace(ATTRIB_BASE, ospace.getOverlayedSpace());
|
||||
encoder.closeElement(ELEM_SPACE_OVERLAY);
|
||||
encoder.openElement(ElementId.ELEM_SPACE_OVERLAY);
|
||||
encoder.writeString(AttributeId.ATTRIB_NAME, ospace.getName());
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, ospace.getUnique());
|
||||
encoder.writeSpace(AttributeId.ATTRIB_BASE, ospace.getOverlayedSpace());
|
||||
encoder.closeElement(ElementId.ELEM_SPACE_OVERLAY);
|
||||
continue;
|
||||
}
|
||||
switch (element.getType()) {
|
||||
case AddressSpace.TYPE_RAM:
|
||||
tag = ELEM_SPACE;
|
||||
tag = ElementId.ELEM_SPACE;
|
||||
delay = 1;
|
||||
physical = true;
|
||||
break;
|
||||
case AddressSpace.TYPE_REGISTER:
|
||||
tag = ELEM_SPACE;
|
||||
tag = ElementId.ELEM_SPACE;
|
||||
delay = 0;
|
||||
physical = true;
|
||||
break;
|
||||
case AddressSpace.TYPE_UNIQUE:
|
||||
tag = ELEM_SPACE_UNIQUE;
|
||||
tag = ElementId.ELEM_SPACE_UNIQUE;
|
||||
delay = 0;
|
||||
physical = true;
|
||||
break;
|
||||
case AddressSpace.TYPE_OTHER:
|
||||
tag = ELEM_SPACE_OTHER;
|
||||
tag = ElementId.ELEM_SPACE_OTHER;
|
||||
delay = 0;
|
||||
physical = true;
|
||||
break;
|
||||
@@ -1499,8 +1463,8 @@ public class SleighLanguage implements Language {
|
||||
continue;
|
||||
}
|
||||
encoder.openElement(tag);
|
||||
encoder.writeString(ATTRIB_NAME, element.getName());
|
||||
encoder.writeSignedInteger(ATTRIB_INDEX, element.getUnique());
|
||||
encoder.writeString(AttributeId.ATTRIB_NAME, element.getName());
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, element.getUnique());
|
||||
|
||||
int size = element.getSize(); // Size in bits
|
||||
if (element instanceof SegmentedAddressSpace) {
|
||||
@@ -1511,18 +1475,19 @@ public class SleighLanguage implements Language {
|
||||
size = 64;
|
||||
}
|
||||
int bytesize = (size + 7) / 8; // Convert bits to bytes
|
||||
encoder.writeSignedInteger(ATTRIB_SIZE, bytesize);
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, bytesize);
|
||||
|
||||
if (element.getAddressableUnitSize() > 1) {
|
||||
encoder.writeUnsignedInteger(ATTRIB_WORDSIZE, element.getAddressableUnitSize());
|
||||
encoder.writeUnsignedInteger(AttributeId.ATTRIB_WORDSIZE,
|
||||
element.getAddressableUnitSize());
|
||||
}
|
||||
|
||||
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeSignedInteger(ATTRIB_DELAY, delay);
|
||||
encoder.writeBool(ATTRIB_PHYSICAL, physical);
|
||||
encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, delay);
|
||||
encoder.writeBool(AttributeId.ATTRIB_PHYSICAL, physical);
|
||||
encoder.closeElement(tag);
|
||||
}
|
||||
encoder.closeElement(ELEM_SPACES);
|
||||
encoder.closeElement(ElementId.ELEM_SPACES);
|
||||
|
||||
SleighLanguageDescription sleighDescription =
|
||||
(SleighLanguageDescription) getLanguageDescription();
|
||||
@@ -1530,13 +1495,13 @@ public class SleighLanguage implements Language {
|
||||
if (!truncatedSpaceNames.isEmpty()) {
|
||||
for (String spaceName : truncatedSpaceNames) {
|
||||
int sz = sleighDescription.getTruncatedSpaceSize(spaceName);
|
||||
encoder.openElement(ELEM_TRUNCATE_SPACE);
|
||||
encoder.writeString(ATTRIB_SPACE, spaceName);
|
||||
encoder.writeSignedInteger(ATTRIB_SIZE, sz);
|
||||
encoder.closeElement(ELEM_TRUNCATE_SPACE);
|
||||
encoder.openElement(ElementId.ELEM_TRUNCATE_SPACE);
|
||||
encoder.writeString(AttributeId.ATTRIB_SPACE, spaceName);
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz);
|
||||
encoder.closeElement(ElementId.ELEM_TRUNCATE_SPACE);
|
||||
}
|
||||
}
|
||||
encoder.closeElement(ELEM_SLEIGH);
|
||||
encoder.closeElement(ElementId.ELEM_SLEIGH);
|
||||
}
|
||||
|
||||
private void initParallelHelper() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.xml.sax.*;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
@@ -137,18 +138,17 @@ public class SleighLanguageProvider implements LanguageProvider {
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), 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) {
|
||||
Msg.showError(this, null, "Error",
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
throw new SleighException(
|
||||
"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) {
|
||||
Msg.showError(this, null, "Error",
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Base class for binary operators that combine PatternExpressions
|
||||
*/
|
||||
public abstract class BinaryExpression extends PatternExpression {
|
||||
@@ -69,10 +67,10 @@ public abstract class BinaryExpression extends PatternExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start();
|
||||
left = PatternExpression.restoreExpression(parser, lang);
|
||||
right = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement();
|
||||
left = PatternExpression.decodeExpression(decoder, lang);
|
||||
right = PatternExpression.decodeExpression(decoder, lang);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,19 +19,17 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A constant value associated with an alwaysTrue pattern
|
||||
*/
|
||||
|
||||
public class ConstantValue extends PatternValue {
|
||||
|
||||
private long val; // The constant value
|
||||
@@ -61,25 +59,16 @@ public class ConstantValue extends PatternValue {
|
||||
val = b;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return val;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
return val;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
return val;
|
||||
@@ -89,14 +78,11 @@ public class ConstantValue extends PatternValue {
|
||||
return val;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("intb");
|
||||
val = SpecXmlUtils.decodeLong(el.getAttribute("val"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_INTB);
|
||||
val = decoder.readSignedInteger(ATTRIB_VAL);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,16 +19,15 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Contiguous bits in the non-instruction part of the context interpreted
|
||||
* as an integer value
|
||||
*/
|
||||
@@ -81,17 +80,11 @@ public class ContextField extends PatternValue {
|
||||
return signbit;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
long res = -1;
|
||||
@@ -100,39 +93,35 @@ public class ContextField extends PatternValue {
|
||||
return ~res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.InstructionContext)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
long res = getContextBytes(walker);
|
||||
res >>= shift;
|
||||
if (signbit)
|
||||
if (signbit) {
|
||||
res = TokenField.signExtend(res, endbit - startbit);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = TokenField.zeroExtend(res, endbit - startbit);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("contextfield");
|
||||
signbit = SpecXmlUtils.decodeBoolean(el.getAttribute("signbit"));
|
||||
startbit = SpecXmlUtils.decodeInt(el.getAttribute("startbit"));
|
||||
endbit = SpecXmlUtils.decodeInt(el.getAttribute("endbit"));
|
||||
startbyte = SpecXmlUtils.decodeInt(el.getAttribute("startbyte"));
|
||||
endbyte = SpecXmlUtils.decodeInt(el.getAttribute("endbyte"));
|
||||
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONTEXTFIELD);
|
||||
signbit = decoder.readBool(ATTRIB_SIGNBIT);
|
||||
startbit = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
|
||||
endbit = (int) decoder.readSignedInteger(ATTRIB_ENDBIT);
|
||||
startbyte = (int) decoder.readSignedInteger(ATTRIB_STARTBYTE);
|
||||
endbyte = (int) decoder.readSignedInteger(ATTRIB_ENDBYTE);
|
||||
shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a long from the context bytes in pos
|
||||
* @param pos
|
||||
* @return
|
||||
* Build a long from the context bytes at the current point in the instruction parse
|
||||
* @param walker is the parsing state
|
||||
* @return the recover value
|
||||
*/
|
||||
private long getContextBytes(ParserWalker walker) {
|
||||
long res = 0;
|
||||
|
||||
@@ -19,15 +19,16 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The integer offset of the address following the current instruction
|
||||
*/
|
||||
public class EndInstructionValue extends PatternValue {
|
||||
@@ -43,37 +44,26 @@ public class EndInstructionValue extends PatternValue {
|
||||
return obj instanceof EndInstructionValue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
Address addr = walker.getNaddr();
|
||||
return addr.getAddressableWordOffset();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
parser.discardSubTree("end_exp");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_END_EXP);
|
||||
decoder.closeElement(el);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The integer offset of the address following the current instruction
|
||||
*/
|
||||
public class Next2InstructionValue extends PatternValue {
|
||||
@@ -56,8 +57,9 @@ public class Next2InstructionValue extends PatternValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
parser.discardSubTree("next2_exp");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_NEXT2_EXP);
|
||||
decoder.closeElement(el);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,15 @@
|
||||
*/
|
||||
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.symbol.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* An Expression representing the value of a Constructor operand
|
||||
*/
|
||||
public class OperandValue extends PatternValue {
|
||||
@@ -75,25 +74,16 @@ public class OperandValue extends PatternValue {
|
||||
return ct;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
throw new SleighException("Operand used in pattern expression");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
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
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
OperandSymbol sym = ct.getOperand(index);
|
||||
@@ -114,18 +104,15 @@ public class OperandValue extends PatternValue {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("operand_exp");
|
||||
index = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
int tabid = SpecXmlUtils.decodeInt(el.getAttribute("table"));
|
||||
int ctid = SpecXmlUtils.decodeInt(el.getAttribute("ct"));
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_OPERAND_EXP);
|
||||
index = (int) decoder.readSignedInteger(ATTRIB_INDEX);
|
||||
int tabid = (int) decoder.readUnsignedInteger(ATTRIB_TABLE);
|
||||
int ctid = (int) decoder.readUnsignedInteger(ATTRIB_CT);
|
||||
SubtableSymbol sym = (SubtableSymbol) lang.getSymbolTable().findSymbol(tabid);
|
||||
ct = sym.getConstructor(ctid);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,66 +19,85 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* An expression which results in a pattern for a specific InstructionContext
|
||||
*/
|
||||
public abstract class PatternExpression {
|
||||
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) {
|
||||
XmlElement el = parser.peek();
|
||||
public static PatternExpression decodeExpression(Decoder decoder, SleighLanguage lang)
|
||||
throws DecoderException {
|
||||
int el = decoder.peekElement();
|
||||
PatternExpression res;
|
||||
String nm = el.getName();
|
||||
if (nm.equals("tokenfield"))
|
||||
if (el == ELEM_TOKENFIELD.id()) {
|
||||
res = new TokenField();
|
||||
else if (nm.equals("contextfield"))
|
||||
}
|
||||
else if (el == ELEM_CONTEXTFIELD.id()) {
|
||||
res = new ContextField();
|
||||
else if (nm.equals("intb"))
|
||||
}
|
||||
else if (el == ELEM_INTB.id()) {
|
||||
res = new ConstantValue();
|
||||
else if (nm.equals("operand_exp"))
|
||||
}
|
||||
else if (el == ELEM_OPERAND_EXP.id()) {
|
||||
res = new OperandValue();
|
||||
else if (nm.equals("start_exp"))
|
||||
}
|
||||
else if (el == ELEM_START_EXP.id()) {
|
||||
res = new StartInstructionValue();
|
||||
else if (nm.equals("end_exp"))
|
||||
}
|
||||
else if (el == ELEM_END_EXP.id()) {
|
||||
res = new EndInstructionValue();
|
||||
else if (nm.equals("next2_exp"))
|
||||
}
|
||||
else if (el == ELEM_NEXT2_EXP.id()) {
|
||||
res = new Next2InstructionValue();
|
||||
else if (nm.equals("plus_exp"))
|
||||
}
|
||||
else if (el == ELEM_PLUS_EXP.id()) {
|
||||
res = new PlusExpression();
|
||||
else if (nm.equals("sub_exp"))
|
||||
}
|
||||
else if (el == ELEM_SUB_EXP.id()) {
|
||||
res = new SubExpression();
|
||||
else if (nm.equals("mult_exp"))
|
||||
}
|
||||
else if (el == ELEM_MULT_EXP.id()) {
|
||||
res = new MultExpression();
|
||||
else if (nm.equals("lshift_exp"))
|
||||
}
|
||||
else if (el == ELEM_LSHIFT_EXP.id()) {
|
||||
res = new LeftShiftExpression();
|
||||
else if (nm.equals("rshift_exp"))
|
||||
}
|
||||
else if (el == ELEM_RSHIFT_EXP.id()) {
|
||||
res = new RightShiftExpression();
|
||||
else if (nm.equals("and_exp"))
|
||||
}
|
||||
else if (el == ELEM_AND_EXP.id()) {
|
||||
res = new AndExpression();
|
||||
else if (nm.equals("or_exp"))
|
||||
}
|
||||
else if (el == ELEM_OR_EXP.id()) {
|
||||
res = new OrExpression();
|
||||
else if (nm.equals("xor_exp"))
|
||||
}
|
||||
else if (el == ELEM_XOR_EXP.id()) {
|
||||
res = new XorExpression();
|
||||
else if (nm.equals("div_exp"))
|
||||
}
|
||||
else if (el == ELEM_DIV_EXP.id()) {
|
||||
res = new DivExpression();
|
||||
else if (nm.equals("minus_exp"))
|
||||
}
|
||||
else if (el == ELEM_MINUS_EXP.id()) {
|
||||
res = new MinusExpression();
|
||||
else if (nm.equals("not_exp"))
|
||||
}
|
||||
else if (el == ELEM_NOT_EXP.id()) {
|
||||
res = new NotExpression();
|
||||
else
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
res.restoreXml(parser, lang);
|
||||
res.decode(decoder, lang);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,15 +19,16 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The offset value of the current instructions address
|
||||
*/
|
||||
public class StartInstructionValue extends PatternValue {
|
||||
@@ -43,37 +44,26 @@ public class StartInstructionValue extends PatternValue {
|
||||
return obj instanceof StartInstructionValue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
Address addr = walker.getAddr();
|
||||
return addr.getAddressableWordOffset();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
parser.discardSubTree("start_exp");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_START_EXP);
|
||||
decoder.closeElement(el);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,15 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A contiguous set of bits within instruction stream, interpreted
|
||||
* as an integer value
|
||||
*/
|
||||
@@ -75,17 +74,11 @@ public class TokenField extends PatternValue {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
long res = -1;
|
||||
@@ -94,18 +87,17 @@ public class TokenField extends PatternValue {
|
||||
return ~res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.InstructionContext)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
long res = getInstructionBytes(walker);
|
||||
|
||||
res >>= shift;
|
||||
if (signbit)
|
||||
if (signbit) {
|
||||
res = signExtend(res, bitend - bitstart);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = zeroExtend(res, bitend - bitstart);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -125,20 +117,17 @@ public class TokenField extends PatternValue {
|
||||
return byteend;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("tokenfield");
|
||||
bigendian = SpecXmlUtils.decodeBoolean(el.getAttribute("bigendian"));
|
||||
signbit = SpecXmlUtils.decodeBoolean(el.getAttribute("signbit"));
|
||||
bitstart = SpecXmlUtils.decodeInt(el.getAttribute("bitstart"));
|
||||
bitend = SpecXmlUtils.decodeInt(el.getAttribute("bitend"));
|
||||
bytestart = SpecXmlUtils.decodeInt(el.getAttribute("bytestart"));
|
||||
byteend = SpecXmlUtils.decodeInt(el.getAttribute("byteend"));
|
||||
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_TOKENFIELD);
|
||||
bigendian = decoder.readBool(ATTRIB_BIGENDIAN);
|
||||
signbit = decoder.readBool(ATTRIB_SIGNBIT);
|
||||
bitstart = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
|
||||
bitend = (int) decoder.readSignedInteger(ATTRIB_ENDBIT);
|
||||
bytestart = (int) decoder.readSignedInteger(ATTRIB_STARTBYTE);
|
||||
byteend = (int) decoder.readSignedInteger(ATTRIB_ENDBYTE);
|
||||
shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public boolean hasSignbit() {
|
||||
@@ -146,10 +135,10 @@ public class TokenField extends PatternValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a long from the instruction bytes in pos
|
||||
* @param pos Current instruction
|
||||
* @return
|
||||
* @throws MemoryAccessException
|
||||
* Build a long from the instruction bytes at the current point in the parse
|
||||
* @param walker is the instruction parse state
|
||||
* @return the recovered value
|
||||
* @throws MemoryAccessException for problems reading the bytes
|
||||
*/
|
||||
private long getInstructionBytes(ParserWalker walker) throws MemoryAccessException {
|
||||
long res = 0;
|
||||
@@ -171,8 +160,9 @@ public class TokenField extends PatternValue {
|
||||
res = res << (8 * tmpsize);
|
||||
res |= (tmp & 0xffffffffl);
|
||||
}
|
||||
if (!bigendian)
|
||||
if (!bigendian) {
|
||||
res = byteSwap(res, size);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -180,15 +170,17 @@ public class TokenField extends PatternValue {
|
||||
* Sign extend -val- above -bit-
|
||||
* @param val value to extend
|
||||
* @param bit bit specifying sign
|
||||
* @return
|
||||
* @return the extended value
|
||||
*/
|
||||
public static long signExtend(long val, int bit) {
|
||||
long mask = 0;
|
||||
mask = (~mask) << bit;
|
||||
if (((val >> bit) & 1) != 0)
|
||||
if (((val >> bit) & 1) != 0) {
|
||||
val |= mask;
|
||||
else
|
||||
}
|
||||
else {
|
||||
val &= (~mask);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -196,7 +188,7 @@ public class TokenField extends PatternValue {
|
||||
* Clear all bits in -val- above -bit-
|
||||
* @param val value to zero extend
|
||||
* @param bit bit above which to zero extend
|
||||
* @return
|
||||
* @return the extended value
|
||||
*/
|
||||
public static long zeroExtend(long val, int bit) {
|
||||
long mask = 0;
|
||||
@@ -210,7 +202,7 @@ public class TokenField extends PatternValue {
|
||||
* Swap the least sig -size- bytes in -val-
|
||||
* @param val value to be byte swapped
|
||||
* @param size number of bytes involved in swap
|
||||
* @return
|
||||
* @return the byte swapped value
|
||||
*/
|
||||
public static long byteSwap(long val, int size) {
|
||||
long res = 0;
|
||||
|
||||
@@ -21,12 +21,10 @@
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Base class for unary operators on PatternExpressions
|
||||
*/
|
||||
|
||||
@@ -59,10 +57,10 @@ public abstract class UnaryExpression extends PatternExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start();
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement();
|
||||
|
||||
unary = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
unary = PatternExpression.decodeExpression(decoder, lang);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
*/
|
||||
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.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern that has both an instruction part and non-instruction part
|
||||
*/
|
||||
public class CombinePattern extends DisjointPattern {
|
||||
@@ -35,9 +35,6 @@ public class CombinePattern extends DisjointPattern {
|
||||
private ContextPattern context; // Context piece
|
||||
private InstructionPattern instr; // Instruction piece
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
|
||||
*/
|
||||
@Override
|
||||
public PatternBlock getBlock(boolean cont) {
|
||||
return cont ? context.getBlock() : instr.getBlock();
|
||||
@@ -53,55 +50,50 @@ public class CombinePattern extends DisjointPattern {
|
||||
instr = in;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
if (context.alwaysTrue())
|
||||
if (context.alwaysTrue()) {
|
||||
return instr.simplifyClone();
|
||||
if (instr.alwaysTrue())
|
||||
}
|
||||
if (instr.alwaysTrue()) {
|
||||
return context.simplifyClone();
|
||||
if (context.alwaysFalse() || instr.alwaysFalse())
|
||||
}
|
||||
if (context.alwaysFalse() || instr.alwaysFalse()) {
|
||||
return new InstructionPattern(false);
|
||||
}
|
||||
|
||||
return new CombinePattern((ContextPattern) context.simplifyClone(),
|
||||
(InstructionPattern) instr.simplifyClone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
instr.shiftInstruction(sa);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
if (b.numDisjoint() != 0)
|
||||
if (b.numDisjoint() != 0) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
DisjointPattern res1 = (DisjointPattern) simplifyClone();
|
||||
DisjointPattern res2 = (DisjointPattern) b.simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
res1.shiftInstruction(-sa);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res2.shiftInstruction(sa);
|
||||
}
|
||||
OrPattern tmp = new OrPattern(res1, res2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
if (b.numDisjoint() != 0)
|
||||
if (b.numDisjoint() != 0) {
|
||||
return b.doAnd(this, -sa);
|
||||
}
|
||||
|
||||
CombinePattern tmp;
|
||||
if (b instanceof CombinePattern) {
|
||||
@@ -117,17 +109,15 @@ public class CombinePattern extends DisjointPattern {
|
||||
else { // Must be a ContextPattern
|
||||
ContextPattern c = (ContextPattern) context.doAnd(b, 0);
|
||||
InstructionPattern newpat = (InstructionPattern) instr.simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
newpat.shiftInstruction(-sa);
|
||||
}
|
||||
tmp = new CombinePattern(c, newpat);
|
||||
}
|
||||
}
|
||||
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
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
@@ -167,41 +157,29 @@ public class CombinePattern extends DisjointPattern {
|
||||
debug.indent();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
return (context.alwaysTrue() && instr.alwaysTrue());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
return (context.alwaysFalse() || instr.alwaysFalse());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
return instr.alwaysInstructionTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("combine_pat");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_COMBINE_PAT);
|
||||
context = new ContextPattern();
|
||||
context.restoreXml(parser);
|
||||
context.decode(decoder);
|
||||
instr = new InstructionPattern();
|
||||
instr.restoreXml(parser);
|
||||
parser.end(el);
|
||||
instr.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
*/
|
||||
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.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.StringUtilities;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Pattern which depends only on the non-instruction stream bits
|
||||
* of the context
|
||||
*/
|
||||
@@ -36,9 +36,6 @@ public class ContextPattern extends DisjointPattern {
|
||||
|
||||
private PatternBlock maskvalue;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
|
||||
*/
|
||||
@Override
|
||||
public PatternBlock getBlock(boolean context) {
|
||||
return context ? maskvalue : null;
|
||||
@@ -56,49 +53,36 @@ public class ContextPattern extends DisjointPattern {
|
||||
return maskvalue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
return new ContextPattern((PatternBlock) maskvalue.clone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
if (!(b instanceof ContextPattern))
|
||||
if (!(b instanceof ContextPattern)) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
return new OrPattern((DisjointPattern) simplifyClone(),
|
||||
(DisjointPattern) b.simplifyClone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
if (!(b instanceof ContextPattern))
|
||||
if (!(b instanceof ContextPattern)) {
|
||||
return b.doAnd(this, -sa);
|
||||
}
|
||||
|
||||
PatternBlock resblock = maskvalue.andBlock(((ContextPattern) b).maskvalue);
|
||||
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
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
@@ -149,39 +133,27 @@ public class ContextPattern extends DisjointPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
return maskvalue.alwaysTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
return maskvalue.alwaysFalse();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("context_pat");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONTEXT_PAT);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue.restoreXml(parser);
|
||||
parser.end(el);
|
||||
maskvalue.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern with no ORs in it
|
||||
*/
|
||||
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) {
|
||||
PatternBlock block = getBlock(context);
|
||||
if (block != null)
|
||||
if (block != null) {
|
||||
return block.getMask(startbit, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getValue(int startbit, int size, boolean context) {
|
||||
PatternBlock block = getBlock(context);
|
||||
if (block != null)
|
||||
if (block != null) {
|
||||
return block.getValue(startbit, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getLength(boolean context) {
|
||||
PatternBlock block = getBlock(context);
|
||||
if (block != null)
|
||||
if (block != null) {
|
||||
return block.getLength();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,18 +83,22 @@ public abstract class DisjointPattern extends Pattern {
|
||||
a = getBlock(false);
|
||||
b = op2.getBlock(false);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.specializes(b))
|
||||
}
|
||||
if (!a.specializes(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a = getBlock(true);
|
||||
b = op2.getBlock(true);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.specializes(b))
|
||||
}
|
||||
if (!a.specializes(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -102,32 +109,39 @@ public abstract class DisjointPattern extends Pattern {
|
||||
a = getBlock(false);
|
||||
b = op2.getBlock(false);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.identical(b))
|
||||
}
|
||||
if (!a.identical(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a = getBlock(true);
|
||||
b = op2.getBlock(true);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.identical(b))
|
||||
}
|
||||
if (!a.identical(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public DisjointPattern restoreDisjoint(XmlPullParser parser) {
|
||||
XmlElement el = parser.peek();
|
||||
static public DisjointPattern decodeDisjoint(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.peekElement();
|
||||
DisjointPattern res;
|
||||
if (el.getName().equals("instruct_pat"))
|
||||
if (el == ELEM_INSTRUCT_PAT.id()) {
|
||||
res = new InstructionPattern();
|
||||
else if (el.getName().equals("context_pat"))
|
||||
}
|
||||
else if (el == ELEM_CONTEXT_PAT.id()) {
|
||||
res = new ContextPattern();
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = new CombinePattern();
|
||||
res.restoreXml(parser);
|
||||
}
|
||||
res.decode(decoder);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,26 +19,23 @@
|
||||
*/
|
||||
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.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.StringUtilities;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Matches against the actual instruction bit stream
|
||||
*/
|
||||
public class InstructionPattern extends DisjointPattern {
|
||||
|
||||
private PatternBlock maskvalue;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
|
||||
*/
|
||||
@Override
|
||||
public PatternBlock getBlock(boolean context) {
|
||||
return context ? null : maskvalue;
|
||||
@@ -60,56 +57,51 @@ public class InstructionPattern extends DisjointPattern {
|
||||
return maskvalue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
return new InstructionPattern((PatternBlock) maskvalue.clone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction()
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
maskvalue.shift(sa);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
if (b.numDisjoint() > 0)
|
||||
if (b.numDisjoint() > 0) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
if (b instanceof CombinePattern)
|
||||
if (b instanceof CombinePattern) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
DisjointPattern res1, res2;
|
||||
res1 = (DisjointPattern) simplifyClone();
|
||||
res2 = (DisjointPattern) b.simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
res1.shiftInstruction(-sa);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res2.shiftInstruction(sa);
|
||||
}
|
||||
return new OrPattern(res1, res2);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
if (b.numDisjoint() > 0)
|
||||
if (b.numDisjoint() > 0) {
|
||||
return b.doAnd(this, -sa);
|
||||
if (b instanceof CombinePattern)
|
||||
}
|
||||
if (b instanceof CombinePattern) {
|
||||
return b.doAnd(this, -sa);
|
||||
}
|
||||
if (b instanceof ContextPattern) {
|
||||
InstructionPattern newpat = (InstructionPattern) simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
newpat.shiftInstruction(-sa);
|
||||
}
|
||||
return new CombinePattern((ContextPattern) b.simplifyClone(), newpat);
|
||||
}
|
||||
// b must be an InstructionPattern if it reaches here
|
||||
@@ -127,9 +119,6 @@ public class InstructionPattern extends DisjointPattern {
|
||||
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
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
@@ -176,39 +165,27 @@ public class InstructionPattern extends DisjointPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
return maskvalue.alwaysTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
return maskvalue.alwaysFalse();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
return maskvalue.alwaysTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("instruct_pat");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_INSTRUCT_PAT);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue.restoreXml(parser);
|
||||
parser.end(el);
|
||||
maskvalue.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,127 +19,127 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
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
|
||||
*/
|
||||
public class OrPattern extends Pattern {
|
||||
|
||||
private DisjointPattern[] orlist;
|
||||
|
||||
public OrPattern() { orlist = null; } // For use with restoreXml
|
||||
|
||||
public OrPattern(DisjointPattern a,DisjointPattern b) {
|
||||
|
||||
public OrPattern() {
|
||||
orlist = null;
|
||||
}
|
||||
|
||||
public OrPattern(DisjointPattern a, DisjointPattern b) {
|
||||
orlist = new DisjointPattern[2];
|
||||
orlist[0] = a;
|
||||
orlist[1] = b;
|
||||
}
|
||||
|
||||
|
||||
public OrPattern(ArrayList<?> list) {
|
||||
orlist = new DisjointPattern[list.size()];
|
||||
for(int i=0;i<list.size();++i)
|
||||
orlist[i] = (DisjointPattern)list.get(i);
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
orlist[i] = (DisjointPattern) list.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (orlist[i].alwaysTrue())
|
||||
public Pattern simplifyClone() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (orlist[i].alwaysTrue()) {
|
||||
return new InstructionPattern(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ArrayList<Object> newlist = new ArrayList<Object>();
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (!orlist[i].alwaysFalse())
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (!orlist[i].alwaysFalse()) {
|
||||
newlist.add(orlist[i].simplifyClone());
|
||||
}
|
||||
}
|
||||
if (newlist.size()==0)
|
||||
if (newlist.size() == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
for(int i=0;i<orlist.length;++i)
|
||||
public void shiftInstruction(int sa) {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
orlist[i].shiftInstruction(sa);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
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());
|
||||
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) {
|
||||
OrPattern b2 = (OrPattern)b;
|
||||
for(int i=0;i<b2.orlist.length;++i)
|
||||
OrPattern b2 = (OrPattern) b;
|
||||
for (int i = 0; i < b2.orlist.length; ++i) {
|
||||
newlist.add(b2.orlist[i].simplifyClone());
|
||||
}
|
||||
}
|
||||
else {
|
||||
newlist.add(b.simplifyClone());
|
||||
}
|
||||
if (sa > 0) {
|
||||
for(int i=0;i<newlist.size();++i)
|
||||
((Pattern)newlist.get(i)).shiftInstruction(sa);
|
||||
for (int i = 0; i < newlist.size(); ++i) {
|
||||
((Pattern) newlist.get(i)).shiftInstruction(sa);
|
||||
}
|
||||
}
|
||||
return new OrPattern(newlist);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
DisjointPattern tmp;
|
||||
ArrayList<Object> newlist = new ArrayList<Object>();
|
||||
if (b instanceof OrPattern) {
|
||||
OrPattern b2 = (OrPattern)b;
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
for(int j=0;j<b2.orlist.length;++j) {
|
||||
tmp = (DisjointPattern)orlist[i].doAnd(b2.orlist[j],sa);
|
||||
OrPattern b2 = (OrPattern) b;
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
for (int j = 0; j < b2.orlist.length; ++j) {
|
||||
tmp = (DisjointPattern) orlist[i].doAnd(b2.orlist[j], sa);
|
||||
newlist.add(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
tmp = (DisjointPattern)orlist[i].doAnd(b,sa);
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
tmp = (DisjointPattern) orlist[i].doAnd(b, sa);
|
||||
newlist.add(tmp);
|
||||
}
|
||||
}
|
||||
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
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException {
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
boolean match = false;
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
debugNextMatch(debug, i);
|
||||
if (orlist[i].isMatch(walker, debug)) {
|
||||
match = true;
|
||||
@@ -148,9 +147,9 @@ public class OrPattern extends Pattern {
|
||||
}
|
||||
}
|
||||
debugDone(debug, match);
|
||||
return match;
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
private void debugDone(SleighDebugLogger debug, boolean match) {
|
||||
if (debug != null) {
|
||||
debug.endPatternGroup(match);
|
||||
@@ -175,72 +174,60 @@ public class OrPattern extends Pattern {
|
||||
debug.indent();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#numDisjoint()
|
||||
*/
|
||||
@Override
|
||||
public int numDisjoint() {
|
||||
public int numDisjoint() {
|
||||
return orlist.length;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#getDisjoint(int)
|
||||
*/
|
||||
@Override
|
||||
public DisjointPattern getDisjoint(int i) {
|
||||
public DisjointPattern getDisjoint(int i) {
|
||||
return orlist[i];
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (orlist[i].alwaysTrue()) return true;
|
||||
public boolean alwaysTrue() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (orlist[i].alwaysTrue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (!orlist[i].alwaysFalse()) return false;
|
||||
public boolean alwaysFalse() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (!orlist[i].alwaysFalse()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (!orlist[i].alwaysInstructionTrue()) return false;
|
||||
public boolean alwaysInstructionTrue() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (!orlist[i].alwaysInstructionTrue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("or_pat");
|
||||
ArrayList<DisjointPattern> ors = new ArrayList<DisjointPattern>();
|
||||
XmlElement peek = parser.peek();
|
||||
while (!peek.isEnd()) {
|
||||
ors.add(DisjointPattern.restoreDisjoint(parser));
|
||||
}
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_OR_PAT);
|
||||
ArrayList<DisjointPattern> ors = new ArrayList<DisjointPattern>();
|
||||
int peek = decoder.peekElement();
|
||||
while (peek != 0) {
|
||||
ors.add(DisjointPattern.decodeDisjoint(decoder));
|
||||
}
|
||||
orlist = new DisjointPattern[ors.size()];
|
||||
int i = 0;
|
||||
for (DisjointPattern pat : ors) {
|
||||
orlist[i++] = pat;
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,13 +19,13 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
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 which either matches or doesnt match a particular
|
||||
* InstructionContext. In particular, the bits comprising the
|
||||
* current instruction in the executable, and possible other
|
||||
@@ -34,14 +33,25 @@ import ghidra.xml.*;
|
||||
*/
|
||||
public abstract class Pattern {
|
||||
public abstract Pattern simplifyClone();
|
||||
|
||||
public abstract void shiftInstruction(int sa);
|
||||
public abstract Pattern doOr(Pattern b,int sa);
|
||||
public abstract Pattern doAnd(Pattern b,int sa);
|
||||
public abstract boolean isMatch(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException;
|
||||
|
||||
public abstract Pattern doOr(Pattern b, int sa);
|
||||
|
||||
public abstract Pattern doAnd(Pattern b, int sa);
|
||||
|
||||
public abstract boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException;
|
||||
|
||||
public abstract int numDisjoint();
|
||||
|
||||
public abstract DisjointPattern getDisjoint(int i);
|
||||
|
||||
public abstract boolean alwaysTrue();
|
||||
|
||||
public abstract boolean alwaysFalse();
|
||||
|
||||
public abstract boolean alwaysInstructionTrue();
|
||||
public abstract void restoreXml(XmlPullParser parser);
|
||||
|
||||
public abstract void decode(Decoder decoder) throws DecoderException;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,17 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
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.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A mask/value pair viewed as two bitstreams
|
||||
*/
|
||||
public class PatternBlock {
|
||||
@@ -43,10 +42,12 @@ public class PatternBlock {
|
||||
int delsize = end - start;
|
||||
int newsize = array.length - delsize;
|
||||
int[] res = new int[newsize];
|
||||
for (int i = 0; i < start; ++i)
|
||||
for (int i = 0; i < start; ++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];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -104,8 +105,9 @@ public class PatternBlock {
|
||||
while (iter1 != 0) {
|
||||
--iter1;
|
||||
--iter2;
|
||||
if (maskvec[iter1] != 0)
|
||||
if (maskvec[iter1] != 0) {
|
||||
break; // Find last non-zero
|
||||
}
|
||||
}
|
||||
if (iter1 != maskvec.length) {
|
||||
iter1++; // Find first zero,in last zero chain
|
||||
@@ -142,10 +144,12 @@ public class PatternBlock {
|
||||
|
||||
public PatternBlock(boolean tf) {
|
||||
offset = 0;
|
||||
if (tf)
|
||||
if (tf) {
|
||||
nonzerosize = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
nonzerosize = -1;
|
||||
}
|
||||
maskvec = null;
|
||||
valvec = null;
|
||||
}
|
||||
@@ -193,8 +197,9 @@ public class PatternBlock {
|
||||
int maxlength = (getLength() > b.getLength()) ? getLength() : b.getLength();
|
||||
|
||||
int asize = maxlength / 4;
|
||||
if (maxlength % 4 != 0)
|
||||
if (maxlength % 4 != 0) {
|
||||
asize += 1;
|
||||
}
|
||||
res.maskvec = new int[asize];
|
||||
res.valvec = new int[asize];
|
||||
res.offset = 0;
|
||||
@@ -206,17 +211,20 @@ public class PatternBlock {
|
||||
val1 = getValue(offset1 * 8, 32);
|
||||
mask2 = b.getMask(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
|
||||
}
|
||||
res.maskvec[i] = mask1 | mask2;
|
||||
res.valvec[i] = val1 | val2;
|
||||
offset1 += 4;
|
||||
i += 1;
|
||||
}
|
||||
if (offset1 < maxlength) // If pattern is impossible
|
||||
if (offset1 < maxlength) { // If pattern is impossible
|
||||
res.nonzerosize = -1;
|
||||
else
|
||||
}
|
||||
else { // If pattern is impossible
|
||||
res.nonzerosize = maxlength;
|
||||
}
|
||||
res.normalize();
|
||||
return res;
|
||||
}
|
||||
@@ -228,16 +236,19 @@ public class PatternBlock {
|
||||
int sbit = 0;
|
||||
while (sbit < length) {
|
||||
tmplength = length - sbit;
|
||||
if (tmplength > 32)
|
||||
if (tmplength > 32) {
|
||||
tmplength = 32;
|
||||
}
|
||||
mask1 = getMask(sbit, tmplength);
|
||||
value1 = getValue(sbit, tmplength);
|
||||
mask2 = op2.getMask(sbit, tmplength);
|
||||
value2 = op2.getValue(sbit, tmplength);
|
||||
if ((mask1 & mask2) != mask2)
|
||||
if ((mask1 & mask2) != mask2) {
|
||||
return false;
|
||||
if ((value1 & mask2) != (value2 & mask2))
|
||||
}
|
||||
if ((value1 & mask2) != (value2 & mask2)) {
|
||||
return false;
|
||||
}
|
||||
sbit += tmplength;
|
||||
}
|
||||
return true;
|
||||
@@ -250,16 +261,19 @@ public class PatternBlock {
|
||||
int sbit = 0;
|
||||
while (sbit < length) {
|
||||
tmplength = length - sbit;
|
||||
if (tmplength > 32)
|
||||
if (tmplength > 32) {
|
||||
tmplength = 32;
|
||||
}
|
||||
mask1 = getMask(sbit, tmplength);
|
||||
value1 = getValue(sbit, tmplength);
|
||||
mask2 = op2.getMask(sbit, tmplength);
|
||||
value2 = op2.getValue(sbit, tmplength);
|
||||
if (mask1 != mask2)
|
||||
if (mask1 != mask2) {
|
||||
return false;
|
||||
if ((mask1 & value1) != (mask2 & value2))
|
||||
}
|
||||
if ((mask1 & value1) != (mask2 & value2)) {
|
||||
return false;
|
||||
}
|
||||
sbit += tmplength;
|
||||
}
|
||||
return true;
|
||||
@@ -281,17 +295,21 @@ public class PatternBlock {
|
||||
int wordnum2 = (startbit + size - 1) / 32;
|
||||
int res;
|
||||
|
||||
if ((wordnum1 < 0) || (wordnum1 >= maskvec.length))
|
||||
if ((wordnum1 < 0) || (wordnum1 >= maskvec.length)) {
|
||||
res = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = maskvec[wordnum1];
|
||||
}
|
||||
res <<= shift;
|
||||
if (wordnum1 != wordnum2) {
|
||||
int tmp;
|
||||
if ((wordnum2 < 0) || (wordnum2 >= maskvec.length))
|
||||
if ((wordnum2 < 0) || (wordnum2 >= maskvec.length)) {
|
||||
tmp = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
tmp = maskvec[wordnum2];
|
||||
}
|
||||
res |= (tmp >>> (32 - shift));
|
||||
}
|
||||
res >>>= 32 - size;
|
||||
@@ -305,17 +323,21 @@ public class PatternBlock {
|
||||
int wordnum2 = (startbit + size - 1) / 32;
|
||||
int res;
|
||||
|
||||
if ((wordnum1 < 0) || (wordnum1 >= valvec.length))
|
||||
if ((wordnum1 < 0) || (wordnum1 >= valvec.length)) {
|
||||
res = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = valvec[wordnum1];
|
||||
}
|
||||
res <<= shift;
|
||||
if (wordnum1 != wordnum2) {
|
||||
int tmp;
|
||||
if ((wordnum2 < 0) || (wordnum2 >= valvec.length))
|
||||
if ((wordnum2 < 0) || (wordnum2 >= valvec.length)) {
|
||||
tmp = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
tmp = valvec[wordnum2];
|
||||
}
|
||||
res |= (tmp >>> (32 - shift));
|
||||
}
|
||||
res >>>= 32 - size;
|
||||
@@ -331,14 +353,16 @@ public class PatternBlock {
|
||||
}
|
||||
|
||||
public boolean isInstructionMatch(ParserWalker walker) {
|
||||
if (nonzerosize <= 0)
|
||||
if (nonzerosize <= 0) {
|
||||
return (nonzerosize == 0);
|
||||
}
|
||||
int off = offset;
|
||||
try {
|
||||
for (int i = 0; i < maskvec.length; ++i) {
|
||||
int data = walker.getInstructionBytes(off, 4);
|
||||
if ((maskvec[i] & data) != valvec[i])
|
||||
if ((maskvec[i] & data) != valvec[i]) {
|
||||
return false;
|
||||
}
|
||||
off += 4;
|
||||
}
|
||||
return true;
|
||||
@@ -349,37 +373,39 @@ public class PatternBlock {
|
||||
}
|
||||
|
||||
public boolean isContextMatch(ParserWalker walker) {
|
||||
if (nonzerosize <= 0)
|
||||
if (nonzerosize <= 0) {
|
||||
return (nonzerosize == 0);
|
||||
}
|
||||
int off = offset;
|
||||
for (int i = 0; i < maskvec.length; ++i) {
|
||||
int data = walker.getContextBytes(off, 4);
|
||||
if ((maskvec[i] & data) != valvec[i])
|
||||
if ((maskvec[i] & data) != valvec[i]) {
|
||||
return false;
|
||||
}
|
||||
off += 4;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("pat_block");
|
||||
offset = SpecXmlUtils.decodeInt(el.getAttribute("offset"));
|
||||
nonzerosize = SpecXmlUtils.decodeInt(el.getAttribute("nonzero"));
|
||||
ArrayList<String> masks = new ArrayList<>();
|
||||
ArrayList<String> vals = new ArrayList<>();
|
||||
XmlElement subel;
|
||||
while ((subel = parser.softStart("mask_word")) != null) {
|
||||
masks.add(subel.getAttribute("mask"));
|
||||
vals.add(subel.getAttribute("val"));
|
||||
parser.end(subel);
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_PAT_BLOCK);
|
||||
offset = (int) decoder.readSignedInteger(ATTRIB_OFF);
|
||||
nonzerosize = (int) decoder.readSignedInteger(ATTRIB_NONZERO);
|
||||
ArrayList<Integer> masks = new ArrayList<>();
|
||||
ArrayList<Integer> vals = new ArrayList<>();
|
||||
while (decoder.peekElement() == ELEM_MASK_WORD.id()) {
|
||||
decoder.openElement();
|
||||
masks.add((int) decoder.readUnsignedInteger(ATTRIB_MASK));
|
||||
vals.add((int) decoder.readUnsignedInteger(ATTRIB_VAL));
|
||||
decoder.closeElement(ELEM_MASK_WORD.id());
|
||||
}
|
||||
maskvec = new int[masks.size()];
|
||||
valvec = new int[vals.size()];
|
||||
for (int i = 0; i < maskvec.length; ++i) {
|
||||
maskvec[i] = SpecXmlUtils.decodeInt(masks.get(i));
|
||||
valvec[i] = SpecXmlUtils.decodeInt(vals.get(i));
|
||||
maskvec[i] = masks.get(i);
|
||||
valvec[i] = vals.get(i);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,15 +19,14 @@
|
||||
*/
|
||||
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.expression.*;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A ValueSymbol that gets its semantic value from contiguous bits
|
||||
* in a VarnodeSymbol. This serves as an embedding of a ContextOp
|
||||
* 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 {
|
||||
|
||||
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
|
||||
|
||||
public VarnodeSymbol getVarnode() { return vn; }
|
||||
|
||||
|
||||
public VarnodeSymbol getVarnode() {
|
||||
return vn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get starting bit of context value within its context register.
|
||||
* @return the starting bit
|
||||
@@ -74,20 +75,39 @@ public class ContextSymbol extends ValueSymbol {
|
||||
public int getInternalHigh() {
|
||||
return ((ContextField) patval).getEndBit();
|
||||
}
|
||||
public boolean followsFlow() { return flow; }
|
||||
|
||||
|
||||
public boolean followsFlow() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("context_sym");
|
||||
int id = SpecXmlUtils.decodeInt(el.getAttribute("varnode"));
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_CONTEXT_SYM);
|
||||
flow = false;
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_VARNODE);
|
||||
SymbolTable symtab = sleigh.getSymbolTable();
|
||||
vn = (VarnodeSymbol)symtab.findSymbol(id);
|
||||
low = SpecXmlUtils.decodeInt(el.getAttribute("low"));
|
||||
if (el.hasAttribute("flow")) {
|
||||
flow = SpecXmlUtils.decodeBoolean(el.getAttribute("flow"));
|
||||
vn = (VarnodeSymbol) symtab.findSymbol(id);
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
boolean lowMissing = true;
|
||||
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"));
|
||||
patval = (PatternValue)PatternExpression.restoreExpression(parser,sleigh);
|
||||
parser.end(el);
|
||||
if (lowMissing || highMissing) {
|
||||
throw new DecoderException("Missing high/low attributes");
|
||||
}
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
decoder.closeElement(ELEM_CONTEXT_SYM.id());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,63 +19,54 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
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
|
||||
* after current instruction
|
||||
*/
|
||||
public class EndSymbol extends SpecificSymbol {
|
||||
|
||||
private PatternExpression patexp;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
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
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getCurSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = walker.getNaddr().getOffset();
|
||||
hand.size = hand.space.getPointerSize();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = walker.getNaddr().getOffset();
|
||||
return "0x"+Long.toHexString(val);
|
||||
return "0x" + Long.toHexString(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
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
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("end_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_END_SYM);
|
||||
patexp = new EndInstructionValue();
|
||||
parser.end(element);
|
||||
decoder.closeElement(ELEM_END_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,50 +19,43 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
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
|
||||
* any pattern.
|
||||
*/
|
||||
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
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getConstSpace();
|
||||
hand.offset_space = null; // Not a dynamic value
|
||||
hand.offset_offset = 0;
|
||||
hand.size = 0; // Cannot provide size
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) {
|
||||
public String print(ParserWalker walker) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Symbol#restoreXml(org.jdom.Element, ghidra.program.model.address.AddressFactory)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("epsilon_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int element = decoder.openElement(ELEM_EPSILON_SYM);
|
||||
decoder.closeElement(ELEM_EPSILON_SYM.id());
|
||||
// Nothing to do
|
||||
parser.end(element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
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.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A ValueSymbol whose printing aspect is determined by looking
|
||||
* 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
|
||||
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException, UnknownInstructionException {
|
||||
@@ -75,42 +72,43 @@ public class NameSymbol extends ValueSymbol {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
int ind = (int) getPatternValue().getValue(walker);
|
||||
return nametable[ind];
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#printList(ghidra.app.plugin.processors.sleigh.ParserWalker, java.util.ArrayList)
|
||||
*/
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list)
|
||||
throws MemoryAccessException {
|
||||
int ind = (int) getPatternValue().getValue(walker);
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("name_sym");
|
||||
patval = (PatternValue) PatternExpression.restoreExpression(parser, sleigh);
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_NAME_SYM);
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
XmlElement nametab;
|
||||
while ((nametab = parser.softStart("nametab")) != null) {
|
||||
names.add(nametab.getAttribute("name"));
|
||||
parser.end(nametab);
|
||||
while (decoder.peekElement() == ELEM_NAMETAB.id()) {
|
||||
decoder.openElement();
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
if (attrib == ATTRIB_NAME.id()) {
|
||||
names.add(decoder.readString());
|
||||
}
|
||||
else {
|
||||
names.add(null);
|
||||
}
|
||||
decoder.closeElement(ELEM_NAMETAB.id());
|
||||
}
|
||||
nametable = new String[names.size()];
|
||||
for (int i = 0; i < nametable.length; ++i) {
|
||||
nametable[i] = names.get(i);
|
||||
}
|
||||
checkTableFill();
|
||||
parser.end(el);
|
||||
decoder.closeElement(ELEM_NAME_SYM.id());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,32 +15,32 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.Next2InstructionValue;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Symbol with semantic value equal to offset of address immediately
|
||||
* after the next instruction (inst_next2)
|
||||
*/
|
||||
public class Next2Symbol extends SpecificSymbol {
|
||||
|
||||
private PatternExpression patexp;
|
||||
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
return patexp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getCurSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = walker.getN2addr().getOffset();
|
||||
@@ -48,21 +48,21 @@ public class Next2Symbol extends SpecificSymbol {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = walker.getN2addr().getOffset();
|
||||
return "0x"+Long.toHexString(val);
|
||||
return "0x" + Long.toHexString(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("next2_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int element = decoder.openElement(ELEM_NEXT2_SYM);
|
||||
patexp = new Next2InstructionValue();
|
||||
parser.end(element);
|
||||
decoder.closeElement(ELEM_NEXT2_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,21 +19,18 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.FixedHandle;
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.OperandValue;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Variable representing an operand to a specific Constructor
|
||||
*/
|
||||
public class OperandSymbol extends SpecificSymbol {
|
||||
@@ -77,17 +74,11 @@ public class OperandSymbol extends SpecificSymbol {
|
||||
return codeaddress;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
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
|
||||
public void getFixedHandle(FixedHandle hnd, ParserWalker walker) {
|
||||
FixedHandle h = walker.getFixedHandle(hand);
|
||||
@@ -100,25 +91,26 @@ public class OperandSymbol extends SpecificSymbol {
|
||||
hnd.temp_offset = h.temp_offset;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
String res;
|
||||
walker.pushOperand(hand);
|
||||
if (triple != null) {
|
||||
if (triple instanceof SubtableSymbol)
|
||||
if (triple instanceof SubtableSymbol) {
|
||||
res = walker.getConstructor().print(walker);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = triple.print(walker);
|
||||
}
|
||||
}
|
||||
else { // Must be expression resulting in a constant
|
||||
long val = defexp.getValue(walker);
|
||||
if (val >= 0)
|
||||
if (val >= 0) {
|
||||
res = "0x" + Long.toHexString(val);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = "-0x" + Long.toHexString(-val);
|
||||
}
|
||||
}
|
||||
walker.popOperand();
|
||||
return res;
|
||||
@@ -129,10 +121,12 @@ public class OperandSymbol extends SpecificSymbol {
|
||||
throws MemoryAccessException {
|
||||
walker.pushOperand(hand);
|
||||
if (triple != null) {
|
||||
if (triple instanceof SubtableSymbol)
|
||||
if (triple instanceof SubtableSymbol) {
|
||||
walker.getConstructor().printList(walker, list);
|
||||
else
|
||||
}
|
||||
else {
|
||||
triple.printList(walker, list);
|
||||
}
|
||||
}
|
||||
else {
|
||||
FixedHandle handle = walker.getParentHandle();
|
||||
@@ -144,32 +138,41 @@ public class OperandSymbol extends SpecificSymbol {
|
||||
walker.popOperand();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("operand_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_OPERAND_SYM);
|
||||
defexp = null;
|
||||
triple = null;
|
||||
codeaddress = false;
|
||||
|
||||
hand = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
|
||||
reloffset = SpecXmlUtils.decodeInt(el.getAttribute("off"));
|
||||
offsetbase = SpecXmlUtils.decodeInt(el.getAttribute("base"));
|
||||
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("minlen"));
|
||||
String attrstr = el.getAttribute("subsym");
|
||||
if (attrstr != null) {
|
||||
int id = SpecXmlUtils.decodeInt(attrstr);
|
||||
triple = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
while (attrib != 0) {
|
||||
if (attrib == ATTRIB_INDEX.id()) {
|
||||
hand = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_OFF.id()) {
|
||||
reloffset = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_BASE.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);
|
||||
if (!parser.peek().isEnd())
|
||||
defexp = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
localexp = (OperandValue) PatternExpression.decodeExpression(decoder, lang);
|
||||
if (decoder.peekElement() != 0) {
|
||||
defexp = PatternExpression.decodeExpression(decoder, lang);
|
||||
}
|
||||
decoder.closeElement(ELEM_OPERAND_SYM.id());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,63 +19,54 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
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
|
||||
* current address
|
||||
*/
|
||||
public class StartSymbol extends SpecificSymbol {
|
||||
|
||||
private PatternExpression patexp;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
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
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getCurSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = walker.getAddr().getOffset();
|
||||
hand.size = hand.space.getPointerSize();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = walker.getAddr().getOffset();
|
||||
return "0x" + Long.toHexString(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
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
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("start_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int element = decoder.openElement(ELEM_START_SYM);
|
||||
patexp = new StartInstructionValue();
|
||||
parser.end(element);
|
||||
decoder.closeElement(ELEM_START_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,18 +19,18 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
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 static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
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
|
||||
* 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 DecisionNode decisiontree; // The decision tree for this table
|
||||
|
||||
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)
|
||||
*/
|
||||
public DecisionNode getDecisionNode() {
|
||||
return decisiontree;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public int getNumConstructors() { return construct.length; }
|
||||
public Constructor getConstructor(int i) { return construct[i]; }
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
|
||||
public int getNumConstructors() {
|
||||
return construct.length;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
public Constructor getConstructor(int i) {
|
||||
return construct[i];
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public PatternExpression getPatternExpression() {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
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
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("subtable_sym");
|
||||
int numct = SpecXmlUtils.decodeInt(el.getAttribute("numct"));
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
}
|
||||
|
||||
@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
|
||||
// before restoring constructors
|
||||
for(int i=0;i<numct;++i) {
|
||||
// before restoring constructors
|
||||
for (int i = 0; i < numct; ++i) {
|
||||
Constructor ct = new Constructor();
|
||||
ct.setId(i);
|
||||
construct[i] = ct;
|
||||
ct.restoreXml(parser,sleigh);
|
||||
ct.decode(decoder, sleigh);
|
||||
}
|
||||
if (!parser.peek().isEnd()) {
|
||||
if (decoder.peekElement() != 0) {
|
||||
decisiontree = new DecisionNode();
|
||||
decisiontree.restoreXml(parser,null,this);
|
||||
decisiontree.decode(decoder, null, this);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(ELEM_SUBTABLE_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,32 +19,39 @@
|
||||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Base class for symbols in sleigh
|
||||
*/
|
||||
public abstract class Symbol {
|
||||
private String name;
|
||||
private int id; // Unique id across all symbols
|
||||
private int scopeid; // id of scope this symbol is in
|
||||
|
||||
public String getName() { return name; }
|
||||
public int getId() { return id; }
|
||||
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 String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
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
Reference in New Issue
Block a user