Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz
2026-05-15 11:49:18 -04:00
41 changed files with 1518 additions and 1393 deletions
@@ -624,8 +624,9 @@ void Architecture::postSpecFile(void)
void Architecture::restoreFromSpec(DocumentStorage &store)
{
Translate *newtrans = buildTranslator(store); // Once language is described we can build translator
newtrans->initialize(store);
unique_ptr<Translate> utrans(buildTranslator(store)); // Once language is described we can build translator
utrans->initialize(store);
Translate *newtrans = utrans.release();
translate = newtrans;
modifySpaces(newtrans); // Give architecture chance to modify spaces, before copying
copySpaces(newtrans);
@@ -741,23 +742,21 @@ void Architecture::decodeDynamicRule(Decoder &decoder)
ProtoModel *Architecture::decodeProto(Decoder &decoder)
{
ProtoModel *res;
unique_ptr<ProtoModel> model;
uint4 elemId = decoder.peekElement();
if (elemId == ELEM_PROTOTYPE)
res = new ProtoModel(this);
model.reset(new ProtoModel(this));
else if (elemId == ELEM_RESOLVEPROTOTYPE)
res = new ProtoModelMerged(this);
model.reset(new ProtoModelMerged(this));
else
throw LowlevelError("Expecting <prototype> or <resolveprototype> tag");
res->decode(decoder);
model->decode(decoder);
ProtoModel *other = getModel(res->getName());
if (other != (ProtoModel *)0) {
string errMsg = "Duplicate ProtoModel name: " + res->getName();
delete res;
throw LowlevelError(errMsg);
}
ProtoModel *other = getModel(model->getName());
if (other != (ProtoModel *)0)
throw LowlevelError("Duplicate ProtoModel name: " + model->getName());
ProtoModel *res = model.release();
protoModels[res->getName()] = res;
return res;
}
@@ -5,9 +5,9 @@
* 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.
@@ -67,19 +67,19 @@ bool BfdArchitectureCapability::isXmlMatch(Document *doc) const
void BfdArchitecture::buildLoader(DocumentStorage &store)
{
LoadImageBfd *ldr;
unique_ptr<LoadImageBfd> ldr;
collectSpecFiles(*errorstream);
if (getTarget().find("binary")==0)
ldr = new LoadImageBfd(getFilename(),"binary");
ldr.reset(new LoadImageBfd(getFilename(),"binary"));
else if (getTarget().find("default")==0)
ldr = new LoadImageBfd(getFilename(),"default");
ldr.reset(new LoadImageBfd(getFilename(),"default"));
else
ldr = new LoadImageBfd(getFilename(),getTarget());
ldr.reset(new LoadImageBfd(getFilename(),getTarget()));
ldr->open();
if (adjustvma!=0)
ldr->adjustVma(adjustvma);
loader = ldr;
loader = ldr.release();
}
void BfdArchitecture::resolveArchitecture(void)
@@ -1402,7 +1402,7 @@ void BlockGraph::decodeBody(Decoder &decoder)
{
BlockMap newresolver;
vector<FlowBlock *> tmplist;
vector<unique_ptr<FlowBlock> > tmplist;
for(;;) {
uint4 subId = decoder.peekElement();
@@ -1411,15 +1411,14 @@ void BlockGraph::decodeBody(Decoder &decoder)
int4 newindex = decoder.readSignedInteger(ATTRIB_INDEX);
FlowBlock *bl = newresolver.createBlock(decoder.readString(ATTRIB_TYPE));
bl->index = newindex; // Need to set index here for sort
tmplist.push_back(bl);
tmplist.push_back(unique_ptr<FlowBlock>(bl));
decoder.closeElement(subId);
}
newresolver.sortList();
for(int4 i=0;i<tmplist.size();++i) {
FlowBlock *bl = tmplist[i];
bl->decode(decoder,newresolver);
addBlock(bl);
tmplist[i]->decode(decoder,newresolver);
addBlock(tmplist[i].release());
}
}
@@ -1905,12 +1904,13 @@ BlockSwitch *BlockGraph::newBlockSwitch(const vector<FlowBlock *> &cs,bool hasEx
{
FlowBlock *rootbl = cs[0];
BlockSwitch *ret = new BlockSwitch(rootbl);
unique_ptr<BlockSwitch> uret( new BlockSwitch(rootbl) );
const FlowBlock *leafbl = rootbl->getExitLeaf();
if ((leafbl == (const FlowBlock *)0)||(leafbl->getType() != FlowBlock::t_copy))
throw LowlevelError("Could not get switch leaf");
ret->grabCaseBasic(leafbl->subBlock(0),cs); // Must be called before the identifyInternal
identifyInternal(ret,cs);
uret->grabCaseBasic(leafbl->subBlock(0),cs); // Must be called before the identifyInternal
identifyInternal(uret.get(),cs);
BlockSwitch *ret = uret.release();
addBlock(ret);
if (hasExit)
ret->forceOutputNum(1); // If there is an exit, there should be exactly 1 out edge
@@ -4,9 +4,9 @@
* 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.
@@ -206,43 +206,38 @@ int main(int argc,char **argv)
startDecompilerLibrary(ghidraroot.c_str(), extrapaths);
}
IfaceStatus *status;
int4 retval = 2;
try {
status = new IfaceTerm("[decomp]> ",cin,cout); // Set up interface
} catch(IfaceError &err) {
cerr << "Interface error during setup: " << err.explain << endl;
exit(1);
}
IfaceCapability::registerAllCommands(status); // Register commands for decompiler and all modules
unique_ptr<IfaceStatus> status(new IfaceTerm("[decomp]> ",cin,cout)); // Set up interface
IfaceCapability::registerAllCommands(status.get()); // Register commands for decompiler and all modules
// Extra commands specific to the console application
status->registerCom(new IfcLoadFile(),"load","file");
status->registerCom(new IfcAddpath(),"addpath");
status->registerCom(new IfcSave(),"save");
status->registerCom(new IfcRestore(),"restore");
// Extra commands specific to the console application
status->registerCom(new IfcLoadFile(),"load","file");
status->registerCom(new IfcAddpath(),"addpath");
status->registerCom(new IfcSave(),"save");
status->registerCom(new IfcRestore(),"restore");
if (initscript != (const char *)0) {
try {
status->pushScript(initscript,"init> ");
} catch(IfaceParseError &err) {
*status->optr << err.explain << endl;
status->done = true;
if (initscript != (const char *)0) {
try {
status->pushScript(initscript,"init> ");
} catch(IfaceParseError &err) {
*status->optr << err.explain << endl;
status->done = true;
}
}
}
if (!status->done)
mainloop(status);
int4 retval = status->isInError() ? 1 : 0;
if (!status->done)
mainloop(status.get());
retval = status->isInError() ? 1 : 0;
#ifdef CPUI_STATISTICS
IfaceDecompData *decompdata = (IfaceDecompData *)status->getData("decompile");
decompdata->conf->stats->printResults(cout);
IfaceDecompData *decompdata = (IfaceDecompData *)status->getData("decompile");
decompdata->conf->stats->printResults(cout);
#endif
try {
delete status;
} catch(IfaceError &err) {
cerr << err.explain << endl;
cerr << "Interface error: " << err.explain << endl;
retval = 2;
}
shutdownDecompilerLibrary();
@@ -132,7 +132,10 @@ void CPoolRecord::decode(Decoder &decoder,TypeFactory &typegrp)
if (subId == ELEM_TOKEN)
token = decoder.readString(ATTRIB_CONTENT);
else {
byteDataLen = decoder.readSignedInteger(ATTRIB_LENGTH);
int8 val = decoder.readSignedInteger(ATTRIB_LENGTH);
if (val < 0 || val >= MAX_STRING_SIZE)
throw LowlevelError("Bad constant pool record: bad <data> size");
byteDataLen = val;
istringstream s3(decoder.readString(ATTRIB_CONTENT));
byteData = new uint1[byteDataLen];
for(int4 i=0;i<byteDataLen;++i) {
@@ -4,9 +4,9 @@
* 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.
@@ -79,6 +79,7 @@ private:
Datatype *type; ///< Data-type associated with the object
uint1 *byteData; ///< For string literals, the raw byte data of the string
int4 byteDataLen; ///< The number of bytes in the data for a string literal
static constexpr int8 MAX_STRING_SIZE = 0x100000; ///< Maximum allowed bytes of string in pool
public:
CPoolRecord(void) { type = (Datatype *)0; byteData = (uint1 *)0; } ///< Construct an empty record
~CPoolRecord(void) { if (byteData != (uint1 *)0) delete [] byteData; } ///< Destructor
@@ -1589,7 +1589,7 @@ Symbol *Scope::addMapSym(Decoder &decoder)
throw LowlevelError("Unknown symbol type");
try { // Protect against duplicate scope errors
sym->decode(decoder);
} catch(RecovError &err) {
} catch(...) {
delete sym;
throw;
}
@@ -2950,12 +2950,13 @@ Database::~Database(void)
void Database::attachScope(Scope *newscope,Scope *parent)
{
unique_ptr<Scope> owner(newscope);
if (parent == (Scope *)0) {
if (globalscope != (Scope *)0)
throw LowlevelError("Multiple global scopes");
if (newscope->name.size() != 0)
throw LowlevelError("Global scope does not have empty name");
globalscope = newscope;
globalscope = owner.release();
idmap[globalscope->uniqueId] = globalscope;
return;
}
@@ -2964,14 +2965,9 @@ void Database::attachScope(Scope *newscope,Scope *parent)
pair<uint8,Scope *> value(newscope->uniqueId,newscope);
pair<ScopeMap::iterator,bool> res;
res = idmap.insert(value);
if (res.second==false) {
ostringstream s;
s << "Duplicate scope id: ";
s << newscope->getFullName();
delete newscope;
throw RecovError(s.str());
}
parent->attachScope(newscope);
if (res.second==false)
throw RecovError("Duplicate scope id: " + newscope->getFullName());
parent->attachScope(owner.release());
}
/// Give \b this database the chance to inform existing scopes of any change to the
@@ -3379,17 +3375,18 @@ void Database::decode(Decoder &decoder)
void Database::decodeScope(Decoder &decoder,Scope *newScope)
{
unique_ptr<Scope> owner(newScope);
uint4 elemId = decoder.openElement();
if (elemId == ELEM_SCOPE) {
Scope *parentScope = parseParentTag(decoder);
attachScope(newScope,parentScope);
attachScope(owner.release(),parentScope);
newScope->decode(decoder);
}
else {
newScope->decodeWrappingAttributes(decoder);
uint4 subId = decoder.openElement(ELEM_SCOPE);
Scope *parentScope = parseParentTag(decoder);
attachScope(newScope,parentScope);
attachScope(owner.release(),parentScope);
newScope->decode(decoder);
decoder.closeElement(subId);
}
@@ -33,6 +33,7 @@
#include <algorithm>
#include <cstring>
#include <cctype>
#include <memory>
namespace ghidra {
@@ -65,6 +66,7 @@ using std::max;
using std::to_string;
using std::piecewise_construct;
using std::forward_as_tuple;
using std::unique_ptr;
/// \brief The lowest level error generated by the decompiler
@@ -682,8 +682,8 @@ bool FlowInfo::setupCallSpecs(PcodeOp *op,FuncCallSpecs *fc)
{
FuncCallSpecs *res;
res = new FuncCallSpecs(op);
data.opSetInput(op,data.newVarnodeCallSpecs(res),0);
qlst.push_back(res);
data.opSetInput(op,data.newVarnodeCallSpecs(res),0);
data.getOverride().applyPrototype(data,*res);
queryCall(*res);
@@ -615,9 +615,9 @@ void Funcdata::decodeJumpTable(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_JUMPTABLELIST);
while(decoder.peekElement() != 0) {
JumpTable *jt = new JumpTable();
unique_ptr<JumpTable> jt(new JumpTable());
jt->decode(decoder);
jumpvec.push_back(jt);
jumpvec.push_back(jt.release());
}
decoder.closeElement(elemId);
}
@@ -47,14 +47,6 @@ ElementId ELEM_COMMAND_GETSTRINGDATA = ElementId("command_getstringdata",255);
ElementId ELEM_COMMAND_GETTRACKEDREGISTERS = ElementId("command_gettrackedregisters",256);
ElementId ELEM_COMMAND_GETUSEROPNAME = ElementId("command_getuseropname",257);
/// Catch the signal so the OS doesn't pop up a dialog
/// \param sig is the OS signal (should always be SIGSEGV)
void ArchitectureGhidra::segvHandler(int4 sig)
{
exit(1); // Just die - prevents OS from popping-up a dialog
}
/// All communications between the Ghidra client and the decompiler are surrounded
/// by alignment bursts. A burst is 1 or more zero bytes followed by
/// an 0x01 byte, then followed by a code byte.
@@ -746,6 +738,8 @@ void ArchitectureGhidra::getBytes(uint1 *buf,int4 size,const Address &inaddr)
if (type == 12) {
uint1 *dblbuf = new uint1[size * 2];
sin.read((char *)dblbuf,size*2);
if (sin.gcount() != size*2)
throw JavaError("alignment","Could not read expected number of bytes");
for (int4 i=0; i < size; i++) {
buf[i] = ((dblbuf[i*2]-'A') << 4) | (dblbuf[i*2 + 1]-'A');
}
@@ -4,9 +4,9 @@
* 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.
@@ -155,7 +155,6 @@ public:
void getStringData(vector<uint1> &buffer,const Address &addr,Datatype *ct,int4 maxBytes,bool &isTrunc);
virtual void printMessage(const string &message) const;
static void segvHandler(int4 sig); ///< Handler for a segment violation (SIGSEGV) signal
static int4 readToAnyBurst(istream &s); ///< Read the next message protocol marker
static bool readBoolStream(istream &s); ///< Read a boolean value from the client
static void readStringStream(istream &s,string &res); ///< Receive a string from the client
@@ -4,9 +4,9 @@
* 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.
@@ -505,6 +505,14 @@ void GhidraDecompCapability::initialize(void)
commandmap["setOptions"] = new SetOptions();
}
/// Catch the signal so the OS doesn't pop up a dialog
/// \param sig is the OS signal (should always be SIGSEGV)
static void segvHandler(int4 sig)
{
_exit(1); // Don't do any cleanup, just die - prevents OS from popping-up a dialog
}
} // End namespace ghidra
int main(int argc,char **argv)
@@ -512,7 +520,7 @@ int main(int argc,char **argv)
{
using namespace ghidra;
signal(SIGSEGV, &ArchitectureGhidra::segvHandler); // Exit on SEGV errors
signal(SIGSEGV, &segvHandler); // Exit on SEGV errors
#ifdef _WINDOWS
// Force i/o streams to be in binary mode
_setmode(_fileno(stdin), _O_BINARY);
@@ -1856,12 +1856,12 @@ void IfcProtooverride::execute(istream &s)
PrototypePieces pieces;
parse_protopieces(pieces,s,dcp->conf); // Parse the prototype from stream
FuncProto *newproto = new FuncProto();
unique_ptr<FuncProto> newproto(new FuncProto());
// Make proto whose storage is internal, not backed by a real scope
newproto->setInternal(pieces.model,dcp->conf->types->getTypeVoid());
newproto->setPieces(pieces);
dcp->fd->getOverride().insertProtoOverride(callpoint,newproto);
dcp->fd->getOverride().insertProtoOverride(callpoint,newproto.release());
dcp->fd->clear(); // Clear any analysis (this leaves overrides intact)
}
@@ -4,9 +4,9 @@
* 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.
@@ -249,7 +249,7 @@ void IfaceTerm::pushScript(istream *iptr,const string &newprompt)
{
inputstack.push_back(sptr);
sptr = iptr;
IfaceStatus::pushScript(iptr,newprompt);
IfaceStatus::pushScript((istream *)0,newprompt);
}
void IfaceTerm::popScript(void)
@@ -4,9 +4,9 @@
* 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.
@@ -145,8 +145,10 @@ void IfaceStatus::pushScript(const string &filename,const string &newprompt)
{
ifstream *s = new ifstream(filename.c_str());
if (!*s)
if (!*s) {
delete s;
throw IfaceParseError("Unable to open script file: "+filename);
}
pushScript(s,newprompt);
}
@@ -159,6 +161,10 @@ void IfaceStatus::pushScript(const string &filename,const string &newprompt)
void IfaceStatus::pushScript(istream *iptr,const string &newprompt)
{
if (iptr != (istream *)0) {
delete iptr;
throw IfaceExecutionError("Unable to read script from stream on this interface");
}
promptstack.push_back(prompt);
uint4 flags = 0;
if (errorisdone)
@@ -2482,11 +2482,11 @@ void JumpTable::setOverride(const vector<Address> &addrtable,const Address &nadd
if (jmodel != (JumpModel *)0)
delete jmodel;
JumpBasicOverride *override;
jmodel = override = new JumpBasicOverride(this);
override->setAddresses(addrtable);
override->setNorm(naddr,h);
override->setStartingValue(sv);
JumpBasicOverride *jumpOverride;
jmodel = jumpOverride = new JumpBasicOverride(this);
jumpOverride->setAddresses(addrtable);
jumpOverride->setNorm(naddr,h);
jumpOverride->setStartingValue(sv);
}
/// \brief Get the index of the i-th address table entry that corresponds to the given basic-block
@@ -4,9 +4,9 @@
* 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.
@@ -30,8 +30,6 @@ uint1 *LoadImage::load(int4 size,const Address &addr)
{
uint1 *buf = new uint1[ size ];
if (buf == (uint1 *)0)
throw LowlevelError("Out of memory");
loadFill(buf,size,addr);
return buf;
}
@@ -62,6 +60,7 @@ void RawLoadImage::open(void)
thefile = new ifstream(filename.c_str());
if (!(*thefile)) {
string errmsg = "Unable to open raw image file: "+filename;
delete thefile;
throw LowlevelError(errmsg);
}
thefile->seekg(0,ios::end);
@@ -689,7 +689,10 @@ void PackedDecode::endIngest(int4 bufPos)
}
uint1 *buf = inStream.back().start;
buf[bufPos] = ELEMENT_END;
} else {
throw DecoderError("Ended ingestion without any input");
}
}
PackedDecode::~PackedDecode(void)
@@ -961,11 +964,10 @@ string PackedDecode::readString(void)
attributeRead = true;
throw DecoderError("Expecting string attribute");
}
int4 length = readLengthCode(typeByte);
length = readInteger(length);
uint8 length = readInteger(readLengthCode(typeByte));
attributeRead = true;
int4 curLen = curPos.end - curPos.current;
uint8 curLen = curPos.end - curPos.current;
if (curLen >= length) {
string res((const char *)curPos.current,length);
advancePosition(curPos, length);
@@ -1002,10 +1004,12 @@ AddrSpace *PackedDecode::readSpace(void)
getNextByte(curPos);
uint1 typeByte = getNextByte(curPos);
uint4 typeCode = typeByte >> TYPECODE_SHIFT;
int4 res;
AddrSpace *spc;
if (typeCode == TYPECODE_ADDRESSSPACE) {
res = readInteger(readLengthCode(typeByte));
uint8 res = readInteger(readLengthCode(typeByte));
if (res >= spcManager->numSpaces())
throw DecoderError("Invalid address space index");
spc = spcManager->getSpace(res);
if (spc == (AddrSpace *)0)
throw DecoderError("Unknown address space index");
@@ -536,7 +536,7 @@ private:
uint1 getByte(Position &pos) { return *pos.current; } ///< Get the byte at the current position, do not advance
uint1 getBytePlus1(Position &pos); ///< Get the byte following the current byte, do not advance position
uint1 getNextByte(Position &pos); ///< Get the byte at the current position and advance to the next byte
void advancePosition(Position &pos,int4 skip); ///< Advance the position by the given number of bytes
void advancePosition(Position &pos,uint4 skip); ///< Advance the position by the given number of bytes
uint8 readInteger(int4 len); ///< Read an integer from the \e current position given its length in bytes
uint4 readLengthCode(uint1 typeByte) { return ((uint4)typeByte & PackedFormat::LENGTHCODE_MASK); } ///< Extract length code from type byte
void findMatchingAttribute(const AttributeId &attribId); ///< Find attribute matching the given id in open element
@@ -631,7 +631,7 @@ inline uint1 PackedDecode::getNextByte(Position &pos)
/// An exception is thrown of position is advanced past the end of the stream
/// \param pos is the position being advanced
/// \param skip is the number of bytes to advance
inline void PackedDecode::advancePosition(Position &pos,int4 skip)
inline void PackedDecode::advancePosition(Position &pos,uint4 skip)
{
while(pos.end - pos.current <= skip) {
@@ -252,23 +252,23 @@ PrimitiveExtractor::PrimitiveExtractor(Datatype *dt,bool unionIllegal,int offset
DatatypeFilter *DatatypeFilter::decodeFilter(Decoder &decoder)
{
DatatypeFilter *filter;
unique_ptr<DatatypeFilter> filter;
uint4 elemId = decoder.openElement(ELEM_DATATYPE);
string nm = decoder.readString(ATTRIB_NAME);
if (nm == "any") {
filter = new SizeRestrictedFilter();
filter.reset(new SizeRestrictedFilter());
}
else if (nm == "homogeneous-float-aggregate") {
filter = new HomogeneousAggregate(TYPE_FLOAT,4,0,0);
filter.reset(new HomogeneousAggregate(TYPE_FLOAT,4,0,0));
}
else {
// If no other name matches, assume this is a metatype
type_metatype meta = string2metatype(nm);
filter = new MetaTypeFilter(meta);
filter.reset(new MetaTypeFilter(meta));
}
filter->decode(decoder);
decoder.closeElement(elemId);
return filter;
return filter.release();
}
/// Parse the given string as a comma or space separated list of decimal integers,
@@ -451,18 +451,18 @@ void HomogeneousAggregate::decode(Decoder &decoder)
QualifierFilter *QualifierFilter::decodeFilter(Decoder &decoder)
{
QualifierFilter *filter;
unique_ptr<QualifierFilter> filter;
uint4 elemId = decoder.peekElement();
if (elemId == ELEM_VARARGS)
filter = new VarargsFilter();
filter.reset(new VarargsFilter());
else if (elemId == ELEM_POSITION)
filter = new PositionMatchFilter(-1);
filter.reset(new PositionMatchFilter(-1));
else if (elemId == ELEM_DATATYPE_AT)
filter = new DatatypeMatchFilter();
filter.reset(new DatatypeMatchFilter());
else
return (QualifierFilter *)0;
filter->decode(decoder);
return filter;
return filter.release();
}
/// The AndFilter assumes ownership of all the filters in the array and the original vector is cleared
@@ -592,32 +592,32 @@ bool AssignAction::fillinOutputMap(ParamActive *active) const
AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandard *res)
{
AssignAction *action;
unique_ptr<AssignAction> action;
uint4 elemId = decoder.peekElement();
if (elemId == ELEM_GOTO_STACK)
action = new GotoStack(res,0);
action.reset(new GotoStack(res,0));
else if (elemId == ELEM_JOIN) {
action = new MultiSlotAssign(res);
action.reset(new MultiSlotAssign(res));
}
else if (elemId == ELEM_CONSUME) {
action = new ConsumeAs(TYPECLASS_GENERAL,res);
action.reset(new ConsumeAs(TYPECLASS_GENERAL,res));
}
else if (elemId == ELEM_CONVERT_TO_PTR) {
action = new ConvertToPointer(res);
action.reset(new ConvertToPointer(res));
}
else if (elemId == ELEM_HIDDEN_RETURN) {
action = new HiddenReturnAssign(res,hiddenret_specialreg);
action.reset(new HiddenReturnAssign(res,hiddenret_specialreg));
}
else if (elemId == ELEM_JOIN_PER_PRIMITIVE) {
action = new MultiMemberAssign(TYPECLASS_GENERAL,false,res->isBigEndian(),res);
action.reset(new MultiMemberAssign(TYPECLASS_GENERAL,false,res->isBigEndian(),res));
}
else if (elemId == ELEM_JOIN_DUAL_CLASS) {
action = new MultiSlotDualAssign(res);
action.reset(new MultiSlotDualAssign(res));
}
else
throw DecoderError("Expecting model rule action");
action->decode(decoder);
return action;
return action.release();
}
/// \brief Read the next model rule precondition element from the stream
@@ -629,18 +629,18 @@ AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandar
/// \return the new precondition, or null if no more preconditions are in the stream
AssignAction *AssignAction::decodePrecondition(Decoder &decoder,const ParamListStandard *res)
{
AssignAction *action;
unique_ptr<AssignAction> action;
uint4 elemId = decoder.peekElement();
if (elemId == ELEM_CONSUME_EXTRA) {
action = new ConsumeExtra(res);
action.reset(new ConsumeExtra(res));
}
else {
return (AssignAction *)0;
}
action->decode(decoder);
return action;
return action.release();
}
/// \brief Read the next model rule sideeffect element from the stream
@@ -653,22 +653,22 @@ AssignAction *AssignAction::decodePrecondition(Decoder &decoder,const ParamListS
AssignAction *AssignAction::decodeSideeffect(Decoder &decoder,const ParamListStandard *res)
{
AssignAction *action;
unique_ptr<AssignAction> action;
uint4 elemId = decoder.peekElement();
if (elemId == ELEM_CONSUME_EXTRA) {
action = new ConsumeExtra(res);
action.reset(new ConsumeExtra(res));
}
else if (elemId == ELEM_EXTRA_STACK) {
action = new ExtraStack(res);
action.reset(new ExtraStack(res));
}
else if (elemId == ELEM_CONSUME_REMAINING) {
action = new ConsumeRemaining(res);
action.reset(new ConsumeRemaining(res));
}
else
throw DecoderError("Expecting model rule sideeffect");
action->decode(decoder);
return action;
return action.release();
}
/// \brief Truncate a tiling by a given number of bytes
@@ -1695,9 +1695,9 @@ void ModelRule::decode(Decoder &decoder,const ParamListStandard *res)
qualifier = new AndFilter(qualifiers);
}
for (;;) {
AssignAction *precond = AssignAction::decodePrecondition(decoder, res);
if (precond == (AssignAction *)0)
break;
AssignAction *precond = AssignAction::decodePrecondition(decoder, res);
if (precond == (AssignAction *)0)
break;
preconditions.push_back(precond);
}
assign = AssignAction::decodeAction(decoder, res);
@@ -4,9 +4,9 @@
* 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.
@@ -231,7 +231,7 @@ static void shift_right(uint4 *arr,int4 size,int4 sa)
///
/// The numerator and denominator, expressed in 32-bit \e digits, are provided.
/// The algorithm calculates the quotient and the remainder is left in the array originally
/// containing the numerator.
/// containing the numerator. We assume m > n > 0 and u[n-1] >= v[n-1] > 0.
/// \param m is the number of 32-bit digits in the numerator
/// \param n is the number of 32-bit digits in the denominator
/// \param u is the numerator and will hold the remainder
@@ -311,8 +311,6 @@ void udiv128(uint8 *numer,uint8 *denom,uint8 *quotient_res,uint8 *remainder_res)
remainder_res[1] = numer[1];
return;
}
u[m] = 0;
m += 1; // Extend u array by 1 to account for normalization
if (n == 1) {
uint4 d = v[0];
uint4 rem = 0;
@@ -325,10 +323,13 @@ void udiv128(uint8 *numer,uint8 *denom,uint8 *quotient_res,uint8 *remainder_res)
u[0] = rem; // Last carry is final remainder
}
else {
u[m] = 0;
m += 1; // Temporarily extend u array by 1 to allow for normalization
knuth_algorithm_d(m,n,u,v,q);
m -= 1; // Remove the extension
}
pack32_64(2,m-n,quotient_res,q);
pack32_64(2,m-1,remainder_res,u);
pack32_64(2,m-n+1,quotient_res,q);
pack32_64(2,m,remainder_res,u);
}
} // End namespace ghidra
@@ -4,9 +4,9 @@
* 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.
@@ -367,10 +367,10 @@ void Override::decode(Decoder &decoder,Architecture *glb)
}
else if (subId == ELEM_PROTOOVERRIDE) {
Address callpoint = Address::decode(decoder);
FuncProto *fp = new FuncProto();
unique_ptr<FuncProto> fp(new FuncProto());
fp->setInternal(glb->defaultfp,glb->types->getTypeVoid());
fp->decode(decoder,glb);
insertProtoOverride(callpoint,fp);
insertProtoOverride(callpoint,fp.release());
}
else if (subId == ELEM_FORCEGOTO) {
Address targetpc = Address::decode(decoder);
@@ -96,7 +96,7 @@ bool VarnodeData::isContiguous(const VarnodeData &lo) const
OpCode PcodeOpRaw::decode(Decoder &decoder,int4 isize,VarnodeData *invar,VarnodeData **outvar)
{
OpCode opcode = (OpCode)decoder.readSignedInteger(ATTRIB_CODE);
OpCode opcode = decoder.readOpcode(ATTRIB_CODE);
uint4 subId = decoder.peekElement();
if (subId == ELEM_VOID) {
decoder.openElement();
@@ -4,9 +4,9 @@
* 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.
@@ -55,14 +55,12 @@ bool RawBinaryArchitectureCapability::isXmlMatch(Document *doc) const
void RawBinaryArchitecture::buildLoader(DocumentStorage &store)
{
RawLoadImage *ldr;
collectSpecFiles(*errorstream);
ldr = new RawLoadImage(getFilename());
unique_ptr<RawLoadImage> ldr(new RawLoadImage(getFilename()));
ldr->open();
if (adjustvma != 0)
ldr->adjustVma(adjustvma);
loader = ldr;
loader = ldr.release();
}
void RawBinaryArchitecture::resolveArchitecture(void)
@@ -721,8 +721,8 @@ void OpTpl::decode(Decoder &decoder)
}
while(decoder.peekElement() != 0) {
VarnodeTpl *vn = new VarnodeTpl();
vn->decode(decoder);
input.push_back(vn);
vn->decode(decoder);
}
decoder.closeElement(el);
}
@@ -915,8 +915,8 @@ int4 ConstructTpl::decode(Decoder &decoder)
}
while(decoder.peekElement() != 0) {
OpTpl *op = new OpTpl();
op->decode(decoder);
vec.push_back(op);
op->decode(decoder);
}
decoder.closeElement(el);
return sectionid;
@@ -142,7 +142,7 @@ class OpTpl {
OpCode opc;
vector<VarnodeTpl *> input;
public:
OpTpl(void) {}
OpTpl(void) : output(nullptr) {}
OpTpl(OpCode oc) { opc = oc; output = (VarnodeTpl *)0; }
~OpTpl(void);
VarnodeTpl *getOut(void) const { return output; }
@@ -452,9 +452,9 @@ void DisassemblyCache::initialize(int4 min,int4 hashsize)
nextfree = 0;
hashtable = new ParserContext *[hashsize];
for(int4 i=0;i<minimumreuse;++i) {
ParserContext *pos = new ParserContext(contextcache,translate);
pos->initialize(constspace);
list[i] = pos;
ParserContext *pos = new ParserContext(contextcache,translate);
list[i] = pos;
pos->initialize(constspace);
}
ParserContext *pos = list[0];
for(int4 i=0;i<hashsize;++i)
@@ -39,6 +39,37 @@ SectionVector::SectionVector(ConstructTpl *rtl,SymbolScope *scope)
main.scope = scope;
}
SectionVector::~SectionVector(void)
{
if (main.section != (ConstructTpl *)0)
delete main.section;
for(int4 i=0;i<named.size();++i) {
ConstructTpl *section = named[i].section;
if (section != (ConstructTpl *)0)
delete section;
}
}
/// \return the p-code template for the main section
ConstructTpl *SectionVector::releaseMainSection(void)
{
ConstructTpl *res = main.section;
main.section = (ConstructTpl *)0;
return res;
}
/// \param index is the index of the requested section
/// \return the p-code template for the section
ConstructTpl *SectionVector::releaseNamedSection(int4 index)
{
ConstructTpl *res = named[index].section;
named[index].section = (ConstructTpl *)0;
return res;
}
/// Associate the new section with \b nextindex, established prior to parsing
/// \param rtl is the \e named section of p-code
/// \param scope is the associated symbol scope
@@ -3671,10 +3702,10 @@ void SleighCompile::buildConstructor(Constructor *big,PatternEquation *pateq,vec
if (vec != (SectionVector *)0) { // If the sections were implemented
noerrors = finalizeSections(big,vec);
if (noerrors) { // Attach the sections to the Constructor
big->setMainSection(vec->getMainSection());
big->setMainSection(vec->releaseMainSection());
int4 max = vec->getMaxId();
for(int4 i=0;i<max;++i) {
ConstructTpl *section = vec->getNamedSection(i);
ConstructTpl *section = vec->releaseNamedSection(i);
if (section != (ConstructTpl *)0)
big->setNamedSection(section,i);
}
@@ -3691,6 +3722,9 @@ void SleighCompile::buildConstructor(Constructor *big,PatternEquation *pateq,vec
delete contvec;
}
}
else {
PatternEquation::release(pateq);
}
symtab.popScope(); // In all cases pop scope
}
@@ -3751,6 +3785,7 @@ int4 SleighCompile::run_compilation(const string &filein,const string &fileout)
try {
int4 parseres = sleighparse(); // Try to parse
fclose(sleighin);
sleighlex_destroy(); // Make sure lexer is reset so we can parse multiple files
if (parseres==0)
process(); // Do all the post-processing
if ((parseres==0)&&(numErrors()==0)) { // If no errors
@@ -3777,7 +3812,6 @@ int4 SleighCompile::run_compilation(const string &filein,const string &fileout)
cerr << "No output produced" <<endl;
return 2;
}
sleighlex_destroy(); // Make sure lexer is reset so we can parse multiple files
} catch(LowlevelError &err) {
cerr << "Unrecoverable error: " << err.explain << endl;
return 2;
@@ -60,14 +60,15 @@ class SectionVector {
RtlPair main; ///< The main section
vector<RtlPair> named; ///< Named sections accessed by index
public:
SectionVector(ConstructTpl *rtl,SymbolScope *scope); ///< Constructor
ConstructTpl *getMainSection(void) const { return main.section; } ///< Get the \e main section
ConstructTpl *getNamedSection(int4 index) const { return named[index].section; } ///< Get a \e named section by index
RtlPair getMainPair(void) const { return main; } ///< Get the \e main section/namespace pair
RtlPair getNamedPair(int4 i) const { return named[i]; } ///< Get a \e named section/namespace pair by index
void setNextIndex(int4 i) { nextindex = i; } ///< Set the index of the currently parsing \e named section
int4 getMaxId(void) const { return named.size(); } ///< Get the maximum (exclusive) named section index
void append(ConstructTpl *rtl,SymbolScope *scope); ///< Add a new \e named section
SectionVector(ConstructTpl *rtl,SymbolScope *scope); ///< Constructor
~SectionVector(void); ///< Destructor
ConstructTpl *releaseMainSection(void); ///< Get the \e main section, giving up ownership
ConstructTpl *releaseNamedSection(int4 index); ///< Get a \e named section by index, giving up ownership
RtlPair getMainPair(void) const { return main; } ///< Get the \e main section/namespace pair
RtlPair getNamedPair(int4 i) const { return named[i]; } ///< Get a \e named section/namespace pair by index
void setNextIndex(int4 i) { nextindex = i; } ///< Set the index of the currently parsing \e named section
int4 getMaxId(void) const { return named.size(); } ///< Get the maximum (exclusive) named section index
void append(ConstructTpl *rtl,SymbolScope *scope); ///< Add a new \e named section
};
/// \brief Qualities associated (via parsing) with an address space
File diff suppressed because it is too large Load Diff
@@ -4,16 +4,16 @@
* 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.
*/
/* A Bison parser, made by GNU Bison 3.5.1. */
/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C
@@ -46,8 +46,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Undocumented macros, especially those whose name start with YY_,
are private implementation details. Do not rely on them. */
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_SLEIGH_SLGHPARSE_HH_INCLUDED
# define YY_SLEIGH_SLGHPARSE_HH_INCLUDED
@@ -67,123 +68,128 @@
extern int sleighdebug;
#endif
/* Token type. */
/* Token kinds. */
#ifndef SLEIGHTOKENTYPE
# define SLEIGHTOKENTYPE
enum sleightokentype
{
OP_BOOL_OR = 258,
OP_BOOL_AND = 259,
OP_BOOL_XOR = 260,
OP_OR = 261,
OP_XOR = 262,
OP_AND = 263,
OP_EQUAL = 264,
OP_NOTEQUAL = 265,
OP_FEQUAL = 266,
OP_FNOTEQUAL = 267,
OP_GREATEQUAL = 268,
OP_LESSEQUAL = 269,
OP_SLESS = 270,
OP_SGREATEQUAL = 271,
OP_SLESSEQUAL = 272,
OP_SGREAT = 273,
OP_FLESS = 274,
OP_FGREAT = 275,
OP_FLESSEQUAL = 276,
OP_FGREATEQUAL = 277,
OP_LEFT = 278,
OP_RIGHT = 279,
OP_SRIGHT = 280,
OP_FADD = 281,
OP_FSUB = 282,
OP_SDIV = 283,
OP_SREM = 284,
OP_FMULT = 285,
OP_FDIV = 286,
OP_ZEXT = 287,
OP_CARRY = 288,
OP_BORROW = 289,
OP_SEXT = 290,
OP_SCARRY = 291,
OP_SBORROW = 292,
OP_NAN = 293,
OP_ABS = 294,
OP_SQRT = 295,
OP_CEIL = 296,
OP_FLOOR = 297,
OP_ROUND = 298,
OP_INT2FLOAT = 299,
OP_FLOAT2FLOAT = 300,
OP_TRUNC = 301,
OP_CPOOLREF = 302,
OP_NEW = 303,
OP_POPCOUNT = 304,
OP_LZCOUNT = 305,
BADINTEGER = 306,
GOTO_KEY = 307,
CALL_KEY = 308,
RETURN_KEY = 309,
IF_KEY = 310,
DEFINE_KEY = 311,
ATTACH_KEY = 312,
MACRO_KEY = 313,
SPACE_KEY = 314,
TYPE_KEY = 315,
RAM_KEY = 316,
DEFAULT_KEY = 317,
REGISTER_KEY = 318,
ENDIAN_KEY = 319,
WITH_KEY = 320,
ALIGN_KEY = 321,
OP_UNIMPL = 322,
TOKEN_KEY = 323,
SIGNED_KEY = 324,
NOFLOW_KEY = 325,
HEX_KEY = 326,
DEC_KEY = 327,
BIG_KEY = 328,
LITTLE_KEY = 329,
SIZE_KEY = 330,
WORDSIZE_KEY = 331,
OFFSET_KEY = 332,
NAMES_KEY = 333,
VALUES_KEY = 334,
VARIABLES_KEY = 335,
PCODEOP_KEY = 336,
IS_KEY = 337,
LOCAL_KEY = 338,
DELAYSLOT_KEY = 339,
CROSSBUILD_KEY = 340,
EXPORT_KEY = 341,
BUILD_KEY = 342,
CONTEXT_KEY = 343,
ELLIPSIS_KEY = 344,
GLOBALSET_KEY = 345,
BITRANGE_KEY = 346,
CHAR = 347,
INTEGER = 348,
INTB = 349,
STRING = 350,
SYMBOLSTRING = 351,
SPACESYM = 352,
SECTIONSYM = 353,
TOKENSYM = 354,
USEROPSYM = 355,
VALUESYM = 356,
VALUEMAPSYM = 357,
CONTEXTSYM = 358,
NAMESYM = 359,
VARSYM = 360,
BITSYM = 361,
SPECSYM = 362,
VARLISTSYM = 363,
OPERANDSYM = 364,
JUMPSYM = 365,
MACROSYM = 366,
LABELSYM = 367,
SUBTABLESYM = 368
SLEIGHEMPTY = -2,
SLEIGHEOF = 0, /* "end of file" */
SLEIGHerror = 256, /* error */
SLEIGHUNDEF = 257, /* "invalid token" */
OP_BOOL_OR = 258, /* OP_BOOL_OR */
OP_BOOL_AND = 259, /* OP_BOOL_AND */
OP_BOOL_XOR = 260, /* OP_BOOL_XOR */
OP_OR = 261, /* OP_OR */
OP_XOR = 262, /* OP_XOR */
OP_AND = 263, /* OP_AND */
OP_EQUAL = 264, /* OP_EQUAL */
OP_NOTEQUAL = 265, /* OP_NOTEQUAL */
OP_FEQUAL = 266, /* OP_FEQUAL */
OP_FNOTEQUAL = 267, /* OP_FNOTEQUAL */
OP_GREATEQUAL = 268, /* OP_GREATEQUAL */
OP_LESSEQUAL = 269, /* OP_LESSEQUAL */
OP_SLESS = 270, /* OP_SLESS */
OP_SGREATEQUAL = 271, /* OP_SGREATEQUAL */
OP_SLESSEQUAL = 272, /* OP_SLESSEQUAL */
OP_SGREAT = 273, /* OP_SGREAT */
OP_FLESS = 274, /* OP_FLESS */
OP_FGREAT = 275, /* OP_FGREAT */
OP_FLESSEQUAL = 276, /* OP_FLESSEQUAL */
OP_FGREATEQUAL = 277, /* OP_FGREATEQUAL */
OP_LEFT = 278, /* OP_LEFT */
OP_RIGHT = 279, /* OP_RIGHT */
OP_SRIGHT = 280, /* OP_SRIGHT */
OP_FADD = 281, /* OP_FADD */
OP_FSUB = 282, /* OP_FSUB */
OP_SDIV = 283, /* OP_SDIV */
OP_SREM = 284, /* OP_SREM */
OP_FMULT = 285, /* OP_FMULT */
OP_FDIV = 286, /* OP_FDIV */
OP_ZEXT = 287, /* OP_ZEXT */
OP_CARRY = 288, /* OP_CARRY */
OP_BORROW = 289, /* OP_BORROW */
OP_SEXT = 290, /* OP_SEXT */
OP_SCARRY = 291, /* OP_SCARRY */
OP_SBORROW = 292, /* OP_SBORROW */
OP_NAN = 293, /* OP_NAN */
OP_ABS = 294, /* OP_ABS */
OP_SQRT = 295, /* OP_SQRT */
OP_CEIL = 296, /* OP_CEIL */
OP_FLOOR = 297, /* OP_FLOOR */
OP_ROUND = 298, /* OP_ROUND */
OP_INT2FLOAT = 299, /* OP_INT2FLOAT */
OP_FLOAT2FLOAT = 300, /* OP_FLOAT2FLOAT */
OP_TRUNC = 301, /* OP_TRUNC */
OP_CPOOLREF = 302, /* OP_CPOOLREF */
OP_NEW = 303, /* OP_NEW */
OP_POPCOUNT = 304, /* OP_POPCOUNT */
OP_LZCOUNT = 305, /* OP_LZCOUNT */
BADINTEGER = 306, /* BADINTEGER */
GOTO_KEY = 307, /* GOTO_KEY */
CALL_KEY = 308, /* CALL_KEY */
RETURN_KEY = 309, /* RETURN_KEY */
IF_KEY = 310, /* IF_KEY */
DEFINE_KEY = 311, /* DEFINE_KEY */
ATTACH_KEY = 312, /* ATTACH_KEY */
MACRO_KEY = 313, /* MACRO_KEY */
SPACE_KEY = 314, /* SPACE_KEY */
TYPE_KEY = 315, /* TYPE_KEY */
RAM_KEY = 316, /* RAM_KEY */
DEFAULT_KEY = 317, /* DEFAULT_KEY */
REGISTER_KEY = 318, /* REGISTER_KEY */
ENDIAN_KEY = 319, /* ENDIAN_KEY */
WITH_KEY = 320, /* WITH_KEY */
ALIGN_KEY = 321, /* ALIGN_KEY */
OP_UNIMPL = 322, /* OP_UNIMPL */
TOKEN_KEY = 323, /* TOKEN_KEY */
SIGNED_KEY = 324, /* SIGNED_KEY */
NOFLOW_KEY = 325, /* NOFLOW_KEY */
HEX_KEY = 326, /* HEX_KEY */
DEC_KEY = 327, /* DEC_KEY */
BIG_KEY = 328, /* BIG_KEY */
LITTLE_KEY = 329, /* LITTLE_KEY */
SIZE_KEY = 330, /* SIZE_KEY */
WORDSIZE_KEY = 331, /* WORDSIZE_KEY */
OFFSET_KEY = 332, /* OFFSET_KEY */
NAMES_KEY = 333, /* NAMES_KEY */
VALUES_KEY = 334, /* VALUES_KEY */
VARIABLES_KEY = 335, /* VARIABLES_KEY */
PCODEOP_KEY = 336, /* PCODEOP_KEY */
IS_KEY = 337, /* IS_KEY */
LOCAL_KEY = 338, /* LOCAL_KEY */
DELAYSLOT_KEY = 339, /* DELAYSLOT_KEY */
CROSSBUILD_KEY = 340, /* CROSSBUILD_KEY */
EXPORT_KEY = 341, /* EXPORT_KEY */
BUILD_KEY = 342, /* BUILD_KEY */
CONTEXT_KEY = 343, /* CONTEXT_KEY */
ELLIPSIS_KEY = 344, /* ELLIPSIS_KEY */
GLOBALSET_KEY = 345, /* GLOBALSET_KEY */
BITRANGE_KEY = 346, /* BITRANGE_KEY */
CHAR = 347, /* CHAR */
INTEGER = 348, /* INTEGER */
INTB = 349, /* INTB */
STRING = 350, /* STRING */
SYMBOLSTRING = 351, /* SYMBOLSTRING */
SPACESYM = 352, /* SPACESYM */
SECTIONSYM = 353, /* SECTIONSYM */
TOKENSYM = 354, /* TOKENSYM */
USEROPSYM = 355, /* USEROPSYM */
VALUESYM = 356, /* VALUESYM */
VALUEMAPSYM = 357, /* VALUEMAPSYM */
CONTEXTSYM = 358, /* CONTEXTSYM */
NAMESYM = 359, /* NAMESYM */
VARSYM = 360, /* VARSYM */
BITSYM = 361, /* BITSYM */
SPECSYM = 362, /* SPECSYM */
VARLISTSYM = 363, /* VARLISTSYM */
OPERANDSYM = 364, /* OPERANDSYM */
JUMPSYM = 365, /* JUMPSYM */
MACROSYM = 366, /* MACROSYM */
LABELSYM = 367, /* LABELSYM */
SUBTABLESYM = 368 /* SUBTABLESYM */
};
typedef enum sleightokentype sleightoken_kind_t;
#endif
/* Value type. */
@@ -151,6 +151,14 @@ extern int sleigherror(const char *str );
%type <specsym> specificsymbol
%type <subtablesym> id_or_nil
%destructor { delete $$; } INTEGER INTB STRING SYMBOLSTRING
%destructor { delete $$; } paramlist rtl rtlmid rtlbody rtlfirstsection rtlcontinue statement expr
%destructor { delete $$; } varnode integervarnode exportvarnode lhsvarnode jumpdest charstring
%destructor { if ($$) PatternEquation::release($$); } pequation elleq ellrt atomic constraint bitpat_or_nil
%destructor { PatternExpression::release($$); } pexpression
%destructor { delete $$; } spaceprop fielddef contextfielddef sizedstar stringlist stringpart anystringlist anystringpart
%destructor { delete $$; } oplist intblist intbpart valuelist valuepart varlist varpart contextlist contextblock
%%
spec: endiandef
| spec aligndef
@@ -193,13 +201,13 @@ contextprop: DEFINE_KEY CONTEXT_KEY VARSYM { $$ = $3; }
{ slgh->reportError("All context definitions must come before constructors"); YYERROR; } }
;
fielddef: STRING '=' '(' INTEGER ',' INTEGER ')' { $$ = new FieldQuality($1,$4,$6); }
| anysymbol '=' '(' INTEGER ',' INTEGER ')' { delete $4; delete $6; string errmsg = $1->getName()+": redefined as field"; slgh->reportError(errmsg); YYERROR; }
| anysymbol '=' '(' INTEGER ',' INTEGER ')' { $$ = (FieldQuality *)0; delete $4; delete $6; string errmsg = $1->getName()+": redefined as field"; slgh->reportError(errmsg); YYERROR; }
| fielddef SIGNED_KEY { $$ = $1; $$->signext = true; }
| fielddef HEX_KEY { $$ = $1; $$->hex = true; }
| fielddef DEC_KEY { $$ = $1; $$->hex = false; }
;
contextfielddef: STRING '=' '(' INTEGER ',' INTEGER ')' { $$ = new FieldQuality($1,$4,$6); }
| anysymbol '=' '(' INTEGER ',' INTEGER ')' { delete $4; delete $6; string errmsg = $1->getName()+": redefined as field"; slgh->reportError(errmsg); YYERROR; }
| anysymbol '=' '(' INTEGER ',' INTEGER ')' { $$ = (FieldQuality *)0; delete $4; delete $6; string errmsg = $1->getName()+": redefined as field"; slgh->reportError(errmsg); YYERROR; }
| contextfielddef SIGNED_KEY { $$ = $1; $$->signext = true; }
| contextfielddef NOFLOW_KEY { $$ = $1; $$->flow = false; }
| contextfielddef HEX_KEY { $$ = $1; $$->hex = true; }
@@ -208,7 +216,7 @@ contextfielddef: STRING '=' '(' INTEGER ',' INTEGER ')' { $$ = new FieldQuality(
spacedef: spaceprop ';' { slgh->newSpace($1); }
;
spaceprop: DEFINE_KEY SPACE_KEY STRING { $$ = new SpaceQuality(*$3); delete $3; }
| DEFINE_KEY SPACE_KEY anysymbol { string errmsg = $3->getName()+": redefined as space"; slgh->reportError(errmsg); YYERROR; }
| DEFINE_KEY SPACE_KEY anysymbol { $$ = (SpaceQuality *)0; string errmsg = $3->getName()+": redefined as space"; slgh->reportError(errmsg); YYERROR; }
| spaceprop TYPE_KEY '=' RAM_KEY { $$ = $1; $$->type = SpaceQuality::ramtype; }
| spaceprop TYPE_KEY '=' REGISTER_KEY { $$ = $1; $$->type = SpaceQuality::registertype; }
| spaceprop SIZE_KEY '=' INTEGER { $$ = $1; $$->size = *$4; delete $4; }
@@ -330,11 +338,11 @@ contextblock: { $$ = (vector<ContextChange *> *)0; }
| '[' contextlist ']' { $$ = $2; }
;
contextlist: { $$ = new vector<ContextChange *>; }
| contextlist CONTEXTSYM '=' pexpression ';' { $$ = $1; if (!slgh->contextMod($1,$2,$4)) { string errmsg="Cannot use 'inst_next' or 'inst_next2' to set context variable: "+$2->getName(); slgh->reportError(errmsg); YYERROR; } }
| contextlist CONTEXTSYM '=' pexpression ';' { $$ = $1; if (!slgh->contextMod($1,$2,$4)) { string errmsg="Cannot use 'inst_next' or 'inst_next2' to set context variable: "+$2->getName(); slgh->reportError(errmsg); delete $1; $4->layClaim(); PatternExpression::release($4); YYERROR; } }
| contextlist GLOBALSET_KEY '(' familysymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
| contextlist GLOBALSET_KEY '(' specificsymbol ',' CONTEXTSYM ')' ';' { $$ = $1; slgh->contextSet($1,$4,$6); }
| contextlist OPERANDSYM '=' pexpression ';' { $$ = $1; slgh->defineOperand($2,$4); }
| contextlist STRING { string errmsg="Expecting context symbol, not "+*$2; delete $2; slgh->reportError(errmsg); YYERROR; }
| contextlist STRING { $$ = (vector<ContextChange *> *)0; delete $1; string errmsg="Expecting context symbol, not "+*$2; delete $2; slgh->reportError(errmsg); YYERROR; }
;
section_def: OP_LEFT STRING OP_RIGHT { $$ = slgh->newSectionSymbol( *$2 ); delete $2; }
| OP_LEFT SECTIONSYM OP_RIGHT { $$ = $2; }
@@ -347,11 +355,11 @@ rtlcontinue: rtlfirstsection { $$ = $1; }
rtl: rtlmid { $$ = $1; if ($$->getOpvec().empty() && ($$->getResult() == (HandleTpl *)0)) slgh->recordNop(); }
| rtlmid EXPORT_KEY exportvarnode ';' { $$ = slgh->setResultVarnode($1,$3); }
| rtlmid EXPORT_KEY sizedstar lhsvarnode ';' { $$ = slgh->setResultStarVarnode($1,$3,$4); }
| rtlmid EXPORT_KEY STRING { string errmsg="Unknown export varnode: "+*$3; delete $3; slgh->reportError(errmsg); YYERROR; }
| rtlmid EXPORT_KEY sizedstar STRING { string errmsg="Unknown pointer varnode: "+*$4; delete $3; delete $4; slgh->reportError(errmsg); YYERROR; }
| rtlmid EXPORT_KEY STRING { $$ = (ConstructTpl *)0; delete $1; string errmsg="Unknown export varnode: "+*$3; delete $3; slgh->reportError(errmsg); YYERROR; }
| rtlmid EXPORT_KEY sizedstar STRING { $$ = (ConstructTpl *)0; delete $1; string errmsg="Unknown pointer varnode: "+*$4; delete $3; delete $4; slgh->reportError(errmsg); YYERROR; }
;
rtlmid: /* EMPTY */ { $$ = slgh->enterSection(); }
| rtlmid statement { $$ = $1; if (!$$->addOpList(*$2)) { delete $2; slgh->reportError("Multiple delayslot declarations"); YYERROR; } delete $2; }
| rtlmid statement { $$ = $1; if (!$$->addOpList(*$2)) { delete $1; delete $2; slgh->reportError("Multiple delayslot declarations"); YYERROR; } delete $2; }
| rtlmid LOCAL_KEY STRING ';' { $$ = $1; slgh->pcode.newLocalDefinition($3); }
| rtlmid LOCAL_KEY STRING ':' INTEGER ';' { $$ = $1; slgh->pcode.newLocalDefinition($3,*$5); delete $5; }
;
@@ -365,8 +373,8 @@ statement: lhsvarnode '=' expr ';' { $3->setOutput($1); $$ = ExprTree::toVector(
| USEROPSYM '(' paramlist ')' ';' { $$ = slgh->pcode.createUserOpNoOut($1,$3); }
| lhsvarnode '[' INTEGER ',' INTEGER ']' '=' expr ';' { $$ = slgh->pcode.assignBitRange($1,(uint4)*$3,(uint4)*$5,$8); delete $3, delete $5; }
| BITSYM '=' expr ';' { $$=slgh->pcode.assignBitRange($1->getParentSymbol()->getVarnode(),$1->getBitOffset(),$1->numBits(),$3); }
| varnode ':' INTEGER '=' { delete $1; delete $3; slgh->reportError("Illegal truncation on left-hand side of assignment"); YYERROR; }
| varnode '(' INTEGER ')' { delete $1; delete $3; slgh->reportError("Illegal subpiece on left-hand side of assignment"); YYERROR; }
| varnode ':' INTEGER '=' { $$ = (vector<OpTpl *> *)0; delete $1; delete $3; slgh->reportError("Illegal truncation on left-hand side of assignment"); YYERROR; }
| varnode '(' INTEGER ')' { $$ = (vector<OpTpl *> *)0; delete $1; delete $3; slgh->reportError("Illegal subpiece on left-hand side of assignment"); YYERROR; }
| BUILD_KEY OPERANDSYM ';' { $$ = slgh->pcode.createOpConst(BUILD,$2->getIndex()); }
| CROSSBUILD_KEY varnode ',' SECTIONSYM ';' { $$ = slgh->createCrossBuild($2,$4); }
| CROSSBUILD_KEY varnode ',' STRING ';' { $$ = slgh->createCrossBuild($2,slgh->newSectionSymbol(*$4)); delete $4; }
@@ -376,7 +384,7 @@ statement: lhsvarnode '=' expr ';' { $3->setOutput($1); $$ = ExprTree::toVector(
| GOTO_KEY '[' expr ']' ';' { $$ = slgh->pcode.createOpNoOut(CPUI_BRANCHIND,$3); }
| CALL_KEY jumpdest ';' { $$ = slgh->pcode.createOpNoOut(CPUI_CALL,new ExprTree($2)); }
| CALL_KEY '[' expr ']' ';' { $$ = slgh->pcode.createOpNoOut(CPUI_CALLIND,$3); }
| RETURN_KEY ';' { slgh->reportError("Must specify an indirect parameter for return"); YYERROR; }
| RETURN_KEY ';' { $$ = (vector<OpTpl *> *)0; slgh->reportError("Must specify an indirect parameter for return"); YYERROR; }
| RETURN_KEY '[' expr ']' ';' { $$ = slgh->pcode.createOpNoOut(CPUI_RETURN,$3); }
| MACROSYM '(' paramlist ')' ';' { $$ = slgh->createMacroUse($1,$3); }
| label { $$ = slgh->pcode.placeLabel( $1 ); }
@@ -447,7 +455,7 @@ expr: varnode { $$ = new ExprTree($1); }
| specificsymbol '[' INTEGER ',' INTEGER ']' { $$ = slgh->pcode.createBitRange($1,(uint4)*$3,(uint4)*$5); delete $3, delete $5; }
| BITSYM { $$=slgh->pcode.createBitRange($1->getParentSymbol(),$1->getBitOffset(),$1->numBits()); }
| USEROPSYM '(' paramlist ')' { $$ = slgh->pcode.createUserOp($1,$3); }
| OP_CPOOLREF '(' paramlist ')' { if ((*$3).size() < 2) { string errmsg = "Must at least two inputs to cpool"; slgh->reportError(errmsg); YYERROR; } $$ = slgh->pcode.createVariadic(CPUI_CPOOLREF,$3); }
| OP_CPOOLREF '(' paramlist ')' { if ((*$3).size() < 2) { string errmsg = "Must be at least two inputs to cpool"; slgh->reportError(errmsg); delete $3; YYERROR; } $$ = slgh->pcode.createVariadic(CPUI_CPOOLREF,$3); }
;
sizedstar: '*' '[' SPACESYM ']' ':' INTEGER { $$ = new StarQuality; $$->size = *$6; delete $6; $$->id=ConstTpl($3->getSpace()); }
| '*' '[' SPACESYM ']' { $$ = new StarQuality; $$->size = 0; $$->id=ConstTpl($3->getSpace()); }
@@ -460,12 +468,12 @@ jumpdest: JUMPSYM { VarnodeTpl *sym = $1->getVarnode(); $$ = new VarnodeTpl(Con
| OPERANDSYM { $$ = $1->getVarnode(); $1->setCodeAddress(); }
| INTEGER '[' SPACESYM ']' { AddrSpace *spc = $3->getSpace(); $$ = new VarnodeTpl(ConstTpl(spc),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::real,spc->getAddrSize())); delete $1; }
| label { $$ = new VarnodeTpl(ConstTpl(slgh->getConstantSpace()),ConstTpl(ConstTpl::j_relative,$1->getIndex()),ConstTpl(ConstTpl::real,sizeof(uintm))); $1->incrementRefCount(); }
| STRING { string errmsg = "Unknown jump destination: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| STRING { $$ = (VarnodeTpl *)0; string errmsg = "Unknown jump destination: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
;
varnode: specificsymbol { $$ = $1->getVarnode(); }
| integervarnode { $$ = $1; }
| STRING { string errmsg = "Unknown varnode parameter: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| SUBTABLESYM { string errmsg = "Subtable not attached to operand: "+$1->getName(); slgh->reportError(errmsg); YYERROR; }
| STRING { $$ = (VarnodeTpl *)0; string errmsg = "Unknown varnode parameter: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| SUBTABLESYM { $$ = (VarnodeTpl *)0; string errmsg = "Subtable not attached to operand: "+$1->getName(); slgh->reportError(errmsg); YYERROR; }
;
integervarnode: INTEGER { $$ = new VarnodeTpl(ConstTpl(slgh->getConstantSpace()),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::real,0)); delete $1; }
| BADINTEGER { $$ = new VarnodeTpl(ConstTpl(slgh->getConstantSpace()),ConstTpl(ConstTpl::real,0),ConstTpl(ConstTpl::real,0)); slgh->reportError("Parsed integer is too big (overflow)"); }
@@ -474,8 +482,8 @@ integervarnode: INTEGER { $$ = new VarnodeTpl(ConstTpl(slgh->getConstantSpace()
| '&' ':' INTEGER varnode { $$ = slgh->pcode.addressOf($4,*$3); delete $3; }
;
lhsvarnode: specificsymbol { $$ = $1->getVarnode(); }
| STRING { string errmsg = "Unknown assignment varnode: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| SUBTABLESYM { string errmsg = "Subtable not attached to operand: "+$1->getName(); slgh->reportError(errmsg); YYERROR; }
| STRING { $$ = (VarnodeTpl *)0; string errmsg = "Unknown assignment varnode: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| SUBTABLESYM { $$ = (VarnodeTpl *)0; string errmsg = "Subtable not attached to operand: "+$1->getName(); slgh->reportError(errmsg); YYERROR; }
;
label: '<' LABELSYM '>' { $$ = $2; }
| '<' STRING '>' { $$ = slgh->pcode.defineLabel( $2 ); }
@@ -484,8 +492,8 @@ exportvarnode: specificsymbol { $$ = $1->getVarnode(); }
| '&' varnode { $$ = slgh->pcode.addressOf($2,0); }
| '&' ':' INTEGER varnode { $$ = slgh->pcode.addressOf($4,*$3); delete $3; }
| INTEGER ':' INTEGER { $$ = new VarnodeTpl(ConstTpl(slgh->getConstantSpace()),ConstTpl(ConstTpl::real,*$1),ConstTpl(ConstTpl::real,*$3)); delete $1; delete $3; }
| STRING { string errmsg="Unknown export varnode: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| SUBTABLESYM { string errmsg = "Subtable not attached to operand: "+$1->getName(); slgh->reportError(errmsg); YYERROR; }
| STRING { $$ = (VarnodeTpl *)0; string errmsg="Unknown export varnode: "+*$1; delete $1; slgh->reportError(errmsg); YYERROR; }
| SUBTABLESYM { $$ = (VarnodeTpl *)0; string errmsg = "Subtable not attached to operand: "+$1->getName(); slgh->reportError(errmsg); YYERROR; }
;
familysymbol: VALUESYM { $$ = $1; }
| VALUEMAPSYM { $$ = $1; }
@@ -511,7 +519,7 @@ intbpart: INTEGER { $$ = new vector<intb>; $$->push_back(intb(*$1)); delete $1;
$$ = new vector<intb>; $$->push_back((intb)0xBADBEEF); delete $1; }
| intbpart INTEGER { $$ = $1; $$->push_back(intb(*$2)); delete $2; }
| intbpart '-' INTEGER { $$ = $1; $$->push_back(-intb(*$3)); delete $3; }
| intbpart STRING { if (*$2!="_") { string errmsg = "Expecting integer but saw: "+*$2; delete $2; slgh->reportError(errmsg); YYERROR; }
| intbpart STRING { if (*$2!="_") { string errmsg = "Expecting integer but saw: "+*$2; delete $1; delete $2; slgh->reportError(errmsg); YYERROR; }
$$ = $1; $$->push_back((intb)0xBADBEEF); delete $2; }
;
stringlist: '[' stringpart ']' { $$ = $2; }
@@ -519,7 +527,7 @@ stringlist: '[' stringpart ']' { $$ = $2; }
;
stringpart: STRING { $$ = new vector<string>; $$->push_back( *$1 ); delete $1; }
| stringpart STRING { $$ = $1; $$->push_back(*$2); delete $2; }
| stringpart anysymbol { string errmsg = $2->getName()+": redefined"; slgh->reportError(errmsg); YYERROR; }
| stringpart anysymbol { $$ = (vector<string> *)0; delete $1; string errmsg = $2->getName()+": redefined"; slgh->reportError(errmsg); YYERROR; }
;
anystringlist: '[' anystringpart ']' { $$ = $2; }
;
@@ -536,7 +544,7 @@ valuepart: VALUESYM { $$ = new vector<SleighSymbol *>; $$->push_back( $1 ); }
| CONTEXTSYM { $$ = new vector<SleighSymbol *>; $$->push_back($1); }
| valuepart VALUESYM { $$ = $1; $$->push_back($2); }
| valuepart CONTEXTSYM { $$ = $1; $$->push_back($2); }
| valuepart STRING { string errmsg = *$2+": is not a value pattern"; delete $2; slgh->reportError(errmsg); YYERROR; }
| valuepart STRING { $$ = (vector<SleighSymbol *> *)0; delete $1; string errmsg = *$2+": is not a value pattern"; delete $2; slgh->reportError(errmsg); YYERROR; }
;
varlist: '[' varpart ']' { $$ = $2; }
| VARSYM { $$ = new vector<SleighSymbol *>; $$->push_back($1); }
@@ -545,7 +553,7 @@ varpart: VARSYM { $$ = new vector<SleighSymbol *>; $$->push_back($1); }
| STRING { if (*$1!="_") { string errmsg = *$1+": is not a varnode symbol"; delete $1; slgh->reportError(errmsg); YYERROR; }
$$ = new vector<SleighSymbol *>; $$->push_back((SleighSymbol *)0); delete $1; }
| varpart VARSYM { $$ = $1; $$->push_back($2); }
| varpart STRING { if (*$2!="_") { string errmsg = *$2+": is not a varnode symbol"; delete $2; slgh->reportError(errmsg); YYERROR; }
| varpart STRING { if (*$2!="_") { string errmsg = *$2+": is not a varnode symbol"; delete $1; delete $2; slgh->reportError(errmsg); YYERROR; }
$$ = $1; $$->push_back((SleighSymbol *)0); delete $2; }
;
paramlist: /* EMPTY */ { $$ = new vector<ExprTree *>; }
@@ -4,9 +4,9 @@
* 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.
@@ -503,9 +503,13 @@ PatternExpression *PatternExpression::decodeExpression(Decoder &decoder,Translat
else if (el == sla::ELEM_NOT_EXP)
res = new NotExpression();
else
return (PatternExpression *)0;
res->decode(decoder,trans);
throw DecoderError("Invalid pattern expression element");
try {
res->decode(decoder,trans);
} catch(...) {
delete res;
throw;
}
return res;
}
@@ -826,6 +830,9 @@ void OperandValue::decode(Decoder &decoder,Translate *trans)
uintm ctid = decoder.readUnsignedInteger(sla::ATTRIB_CT);
SleighBase *sleigh = (SleighBase *)trans;
SubtableSymbol *tab = dynamic_cast<SubtableSymbol *>(sleigh->findSymbol(tabid));
if (ctid >= tab->getNumConstructors()) {
throw DecoderError("Invalid constructor id");
}
ct = tab->getConstructor(ctid);
decoder.closeElement(el);
}
@@ -4,9 +4,9 @@
* 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.
@@ -141,16 +141,16 @@ bool DisjointPattern::resolvesIntersect(const DisjointPattern *op1,const Disjoin
DisjointPattern *DisjointPattern::decodeDisjoint(Decoder &decoder)
{ // DisjointPattern factory
DisjointPattern *res;
unique_ptr<DisjointPattern> res;
uint4 el = decoder.peekElement();
if (el == sla::ELEM_INSTRUCT_PAT)
res = new InstructionPattern();
res.reset(new InstructionPattern());
else if (el == sla::ELEM_CONTEXT_PAT)
res = new ContextPattern();
res.reset(new ContextPattern());
else
res = new CombinePattern();
res.reset(new CombinePattern());
res->decode(decoder);
return res;
return res.release();
}
void PatternBlock::normalize(void)
@@ -1128,9 +1128,9 @@ char *yytext;
* 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.
@@ -49,10 +49,12 @@ SymbolTable::~SymbolTable(void)
{
vector<SymbolScope *>::iterator iter;
for(iter=table.begin();iter!=table.end();++iter)
delete *iter;
if (*iter)
delete *iter;
vector<SleighSymbol *>::iterator siter;
for(siter=symbollist.begin();siter!=symbollist.end();++siter)
delete *siter;
if (*siter)
delete *siter;
}
void SymbolTable::addScope(void)
@@ -170,13 +172,33 @@ void SymbolTable::decode(Decoder &decoder,SleighBase *trans)
{
int4 el = decoder.openElement(sla::ELEM_SYMBOL_TABLE);
table.resize(decoder.readSignedInteger(sla::ATTRIB_SCOPESIZE), (SymbolScope *)0);
symbollist.resize(decoder.readSignedInteger(sla::ATTRIB_SYMBOLSIZE), (SleighSymbol *)0);
int8 tableSize = decoder.readSignedInteger(sla::ATTRIB_SCOPESIZE);
int8 symbolSize = decoder.readSignedInteger(sla::ATTRIB_SYMBOLSIZE);
if (tableSize < 0 || symbolSize < 0)
throw SleighError("Bad symbol table size");
if (tableSize > MAX_TABLES)
throw SleighError("Maximum scopes exceeded");
if (symbolSize > MAX_SYMBOLS)
throw SleighError("Maximum symbols exceeded");
table.resize(tableSize, (SymbolScope *)0);
symbollist.resize(symbolSize, (SleighSymbol *)0);
for(int4 i=0;i<table.size();++i) { // Decode the scopes
int4 subel = decoder.openElement(sla::ELEM_SCOPE);
uintm id = decoder.readUnsignedInteger(sla::ATTRIB_ID);
if (id >= table.size()) {
throw SleighError("Bad symbol scope id: exceeds symbol scope table size");
}
uintm parent = decoder.readUnsignedInteger(sla::ATTRIB_PARENT);
if (parent >= table.size()) {
throw SleighError("Bad symbol scope parent id: exceeds symbol scope table size");
}
SymbolScope *parscope = (parent==id) ? (SymbolScope *)0 : table[parent];
if (table[id]) {
throw SleighError("Bad symbol scope parent id: not unique");
}
table[id] = new SymbolScope( parscope, id );
decoder.closeElement(subel);
}
@@ -202,39 +224,58 @@ void SymbolTable::decodeSymbolHeader(Decoder &decoder)
{ // Put the shell of a symbol in the symbol table
// in order to allow recursion
SleighSymbol *sym;
unique_ptr<SleighSymbol> sym;
uint4 el = decoder.peekElement();
if (el == sla::ELEM_USEROP_HEAD)
sym = new UserOpSymbol();
sym.reset(new UserOpSymbol());
else if (el == sla::ELEM_EPSILON_SYM_HEAD)
sym = new EpsilonSymbol();
sym.reset(new EpsilonSymbol());
else if (el == sla::ELEM_VALUE_SYM_HEAD)
sym = new ValueSymbol();
sym.reset(new ValueSymbol());
else if (el == sla::ELEM_VALUEMAP_SYM_HEAD)
sym = new ValueMapSymbol();
sym.reset(new ValueMapSymbol());
else if (el == sla::ELEM_NAME_SYM_HEAD)
sym = new NameSymbol();
sym.reset(new NameSymbol());
else if (el == sla::ELEM_VARNODE_SYM_HEAD)
sym = new VarnodeSymbol();
sym.reset(new VarnodeSymbol());
else if (el == sla::ELEM_CONTEXT_SYM_HEAD)
sym = new ContextSymbol();
sym.reset(new ContextSymbol());
else if (el == sla::ELEM_VARLIST_SYM_HEAD)
sym = new VarnodeListSymbol();
sym.reset(new VarnodeListSymbol());
else if (el == sla::ELEM_OPERAND_SYM_HEAD)
sym = new OperandSymbol();
sym.reset(new OperandSymbol());
else if (el == sla::ELEM_START_SYM_HEAD)
sym = new StartSymbol();
sym.reset(new StartSymbol());
else if (el == sla::ELEM_END_SYM_HEAD)
sym = new EndSymbol();
sym.reset(new EndSymbol());
else if (el == sla::ELEM_NEXT2_SYM_HEAD)
sym = new Next2Symbol();
sym.reset(new Next2Symbol());
else if (el == sla::ELEM_SUBTABLE_SYM_HEAD)
sym = new SubtableSymbol();
sym.reset(new SubtableSymbol());
else
throw SleighError("Bad symbol xml");
sym->decodeHeader(decoder); // Restore basic elements of symbol
symbollist[sym->id] = sym; // Put the basic symbol in the table
table[sym->scopeid]->addSymbol(sym); // to allow recursion
if (sym->id >= symbollist.size()) {
throw SleighError("Bad symbol id: exceeds symbollist size");
}
if (symbollist[sym->id] != (SleighSymbol *)0) {
throw SleighError("Bad symbol id: not unique");
}
if (sym->scopeid >= table.size()) {
throw SleighError("Bad symbol scope id: too large");
}
if (table[sym->scopeid] == (SymbolScope *)0) {
throw SleighError("Bad symbol scope id: undefined");
}
SleighSymbol *res = sym.release();
symbollist[res->id] = res; // Put the basic symbol in the table
table[res->scopeid]->addSymbol(res); // to allow recursion
}
void SymbolTable::purge(void)
@@ -500,6 +541,9 @@ void ValueSymbol::encodeHeader(Encoder &encoder) const
void ValueSymbol::decode(Decoder &decoder,SleighBase *trans)
{
if (patval)
throw DecoderError("Already decoded symbol");
patval = (PatternValue *) PatternExpression::decodeExpression(decoder,trans);
patval->layClaim();
decoder.closeElement(sla::ELEM_VALUE_SYM.getId());
@@ -581,6 +625,9 @@ void ValueMapSymbol::encodeHeader(Encoder &encoder) const
void ValueMapSymbol::decode(Decoder &decoder,SleighBase *trans)
{
if (patval)
throw DecoderError("Already decoded symbol");
patval = (PatternValue *) PatternExpression::decodeExpression(decoder,trans);
patval->layClaim();
while(decoder.peekElement() != 0) {
@@ -660,6 +707,9 @@ void NameSymbol::encodeHeader(Encoder &encoder) const
void NameSymbol::decode(Decoder &decoder,SleighBase *trans)
{
if (patval)
throw DecoderError("Already decoded symbol");
patval = (PatternValue *) PatternExpression::decodeExpression(decoder,trans);
patval->layClaim();
while(decoder.peekElement() != 0) {
@@ -794,6 +844,10 @@ void ContextSymbol::decode(Decoder &decoder,SleighBase *trans)
if (lowMissing || highMissing) {
throw DecoderError("Missing high/low attributes");
}
if (patval)
throw DecoderError("Already decoded symbol");
patval = (PatternValue *) PatternExpression::decodeExpression(decoder,trans);
patval->layClaim();
decoder.closeElement(sla::ELEM_CONTEXT_SYM.getId());
@@ -898,6 +952,9 @@ void VarnodeListSymbol::encodeHeader(Encoder &encoder) const
void VarnodeListSymbol::decode(Decoder &decoder,SleighBase *trans)
{
if (patval)
throw DecoderError("Already decoded symbol");
patval = (PatternValue *) PatternExpression::decodeExpression(decoder,trans);
patval->layClaim();
while(decoder.peekElement() != 0) {
@@ -945,7 +1002,9 @@ void OperandSymbol::defineOperand(TripleSymbol *tri)
OperandSymbol::~OperandSymbol(void)
{
PatternExpression::release(localexp);
if (localexp != (PatternExpression *)0)
PatternExpression::release(localexp);
if (defexp != (PatternExpression *)0)
PatternExpression::release(defexp);
}
@@ -1040,6 +1099,9 @@ void OperandSymbol::encodeHeader(Encoder &encoder) const
void OperandSymbol::decode(Decoder &decoder,SleighBase *trans)
{
if (defexp || localexp)
throw DecoderError("Already decoded symbol");
defexp = (PatternExpression *)0;
triple = (TripleSymbol *)0;
flags = 0;
@@ -1631,28 +1693,28 @@ void Constructor::decode(Decoder &decoder,SleighBase *trans)
}
else if (subel == sla::ELEM_CONTEXT_OP) {
ContextOp *c_op = new ContextOp();
c_op->decode(decoder,trans);
context.push_back(c_op);
c_op->decode(decoder,trans);
}
else if (subel == sla::ELEM_COMMIT) {
ContextCommit *c_op = new ContextCommit();
c_op->decode(decoder,trans);
context.push_back(c_op);
c_op->decode(decoder,trans);
}
else {
ConstructTpl *cur = new ConstructTpl();
unique_ptr<ConstructTpl> cur(new ConstructTpl());
int4 sectionid = cur->decode(decoder);
if (sectionid < 0) {
if (templ != (ConstructTpl *)0)
throw LowlevelError("Duplicate main section");
templ = cur;
templ = cur.release();
}
else {
while(namedtempl.size() <= sectionid)
namedtempl.push_back((ConstructTpl *)0);
if (namedtempl[sectionid] != (ConstructTpl *)0)
throw LowlevelError("Duplicate named section");
namedtempl[sectionid] = cur;
namedtempl[sectionid] = cur.release();
}
}
subel = decoder.peekElement();
@@ -2334,6 +2396,9 @@ void DecisionNode::decode(Decoder &decoder,DecisionNode *par,SubtableSymbol *sub
if (subel == sla::ELEM_PAIR) {
decoder.openElement();
uintm id = decoder.readSignedInteger(sla::ATTRIB_ID);
if (id >= sub->getNumConstructors()) {
throw DecoderError("Invalid constructor id");
}
Constructor *ct = sub->getConstructor(id);
DisjointPattern *pat = DisjointPattern::decodeDisjoint(decoder);
list.push_back(pair<DisjointPattern *,Constructor *>(pat,ct));
@@ -2341,8 +2406,8 @@ void DecisionNode::decode(Decoder &decoder,DecisionNode *par,SubtableSymbol *sub
}
else if (subel == sla::ELEM_DECISION) {
DecisionNode *subnode = new DecisionNode();
subnode->decode(decoder,this,sub);
children.push_back(subnode);
subnode->decode(decoder,this,sub);
}
subel = decoder.peekElement();
}
@@ -4,9 +4,9 @@
* 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.
@@ -76,6 +76,8 @@ class SymbolTable {
SymbolScope *skipScope(int4 i) const;
SleighSymbol *findSymbolInternal(SymbolScope *scope,const string &nm) const;
void renumber(void);
static constexpr int8 MAX_TABLES = 0x100000;
static constexpr int8 MAX_SYMBOLS = 0x1000000;
public:
SymbolTable(void) { curscope = (SymbolScope *)0; }
~SymbolTable(void);
@@ -326,7 +328,7 @@ private:
void setVariableLength(void) { flags |= variable_len; }
bool isVariableLength(void) const { return ((flags&variable_len)!=0); }
public:
OperandSymbol(void) {} // For use with decode
OperandSymbol(void) : localexp(nullptr), defexp(nullptr) {} // For use with decode
OperandSymbol(const string &nm,int4 index,Constructor *ct);
uint4 getRelativeOffset(void) const { return reloffset; }
int4 getOffsetBase(void) const { return offsetbase; }
@@ -448,8 +450,8 @@ 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 decode
virtual ~ContextOp(void) { PatternExpression::release(patexp); }
ContextOp(void) : patexp(nullptr) {} // For use with decode
virtual ~ContextOp(void) { if (patexp) PatternExpression::release(patexp); }
virtual void validate(void) const;
virtual void encode(Encoder &encoder) const;
virtual void decode(Decoder &decoder,SleighBase *trans);
@@ -258,20 +258,20 @@ AddrSpace *AddrSpaceManager::decodeSpace(Decoder &decoder,const Translate *trans
{
uint4 elemId = decoder.peekElement();
AddrSpace *res;
unique_ptr<AddrSpace> res;
if (elemId == ELEM_SPACE_BASE)
res = new SpacebaseSpace(this,trans);
res.reset(new SpacebaseSpace(this,trans));
else if (elemId == ELEM_SPACE_UNIQUE)
res = new UniqueSpace(this,trans);
res.reset(new UniqueSpace(this,trans));
else if (elemId == ELEM_SPACE_OTHER)
res = new OtherSpace(this,trans);
res.reset(new OtherSpace(this,trans));
else if (elemId == ELEM_SPACE_OVERLAY)
res = new OverlaySpace(this,trans);
res.reset(new OverlaySpace(this,trans));
else
res = new AddrSpace(this,trans,IPTR_PROCESSOR);
res.reset(new AddrSpace(this,trans,IPTR_PROCESSOR));
res->decode(decoder);
return res;
return res.release();
}
/// This routine initializes (almost) all the address spaces used
@@ -352,49 +352,49 @@ void AddrSpaceManager::setReverseJustified(AddrSpace *spc)
void AddrSpaceManager::insertSpace(AddrSpace *spc)
{
bool nameTypeMismatch = false;
bool duplicateName = false;
bool duplicateId = false;
unique_ptr<AddrSpace> owner;
if (spc->refcount == 0)
owner.reset(spc); // Take ownership if this is the first reference
switch(spc->getType()) {
case IPTR_CONSTANT:
if (spc->getName() != ConstantSpace::NAME)
nameTypeMismatch = true;
throw LowlevelError("Space " + spc->getName() + " was initialized with wrong type");
if (spc->index != ConstantSpace::INDEX)
throw LowlevelError("const space must be assigned index 0");
constantspace = spc;
break;
case IPTR_INTERNAL:
if (spc->getName() != UniqueSpace::NAME)
nameTypeMismatch = true;
throw LowlevelError("Space " + spc->getName() + " was initialized with wrong type");
if (uniqspace != (AddrSpace *)0)
duplicateName = true;
throw LowlevelError("Space " + spc->getName() + " was initialized more than once");
uniqspace = spc;
break;
case IPTR_FSPEC:
if (spc->getName() != "fspec")
nameTypeMismatch = true;
throw LowlevelError("Space " + spc->getName() + " was initialized with wrong type");
if (fspecspace != (AddrSpace *)0)
duplicateName = true;
throw LowlevelError("Space " + spc->getName() + " was initialized more than once");
fspecspace = spc;
break;
case IPTR_JOIN:
if (spc->getName() != JoinSpace::NAME)
nameTypeMismatch = true;
throw LowlevelError("Space " + spc->getName() + " was initialized with wrong type");
if (joinspace != (AddrSpace *)0)
duplicateName = true;
throw LowlevelError("Space " + spc->getName() + " was initialized more than once");
joinspace = spc;
break;
case IPTR_IOP:
if (spc->getName() != "iop")
nameTypeMismatch = true;
throw LowlevelError("Space " + spc->getName() + " was initialized with wrong type");
if (iopspace != (AddrSpace *)0)
duplicateName = true;
throw LowlevelError("Space " + spc->getName() + " was initialized more than once");
iopspace = spc;
break;
case IPTR_SPACEBASE:
if (spc->getName() == "stack") {
if (stackspace != (AddrSpace *)0)
duplicateName = true;
throw LowlevelError("Space " + spc->getName() + " was initialized more than once");
stackspace = spc;
}
// fallthru
@@ -412,26 +412,14 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
if (baselist.size() <= spc->index)
baselist.resize(spc->index+1, (AddrSpace *)0);
duplicateId = baselist[spc->index] != (AddrSpace *)0;
if (baselist[spc->index] != (AddrSpace *)0)
throw LowlevelError("Space " + spc->getName() + " was assigned id duplicating: "+baselist[spc->index]->getName());
if (!nameTypeMismatch && !duplicateName && !duplicateId) {
duplicateName = !name2Space.insert(pair<string,AddrSpace *>(spc->getName(),spc)).second;
}
if (!name2Space.insert(pair<string,AddrSpace *>(spc->getName(),spc)).second)
throw LowlevelError("Space " + spc->getName() + " was initialized more than once");
if (nameTypeMismatch || duplicateName || duplicateId) {
string errMsg = "Space " + spc->getName();
if (nameTypeMismatch)
errMsg = errMsg + " was initialized with wrong type";
if (duplicateName)
errMsg = errMsg + " was initialized more than once";
if (duplicateId)
errMsg = errMsg + " was assigned as id duplicating: "+baselist[spc->index]->getName();
if (spc->refcount == 0)
delete spc;
spc = (AddrSpace *)0;
throw LowlevelError(errMsg);
}
baselist[spc->index] = spc;
owner.release();
spc->refcount += 1;
assignShortcut(spc);
}
@@ -1024,7 +1012,7 @@ const FloatFormat *Translate::getFloatFormat(int4 size) const
void PcodeEmit::decodeOp(const Address &addr,Decoder &decoder)
{
int4 opcode;
OpCode opcode;
int4 isize;
VarnodeData outvar;
VarnodeData invar[16];
@@ -1033,14 +1021,19 @@ void PcodeEmit::decodeOp(const Address &addr,Decoder &decoder)
uint4 elemId = decoder.openElement(ELEM_OP);
isize = decoder.readSignedInteger(ATTRIB_SIZE);
outptr = &outvar;
if (isize <= 16)
if (isize <= 16) {
if (isize < 0)
throw DecoderError("Bad <op> size attribute");
opcode = PcodeOpRaw::decode(decoder, isize, invar, &outptr);
decoder.closeElement(elemId);
dump(addr,opcode,outptr,invar,isize);
}
else {
vector<VarnodeData> varStorage(isize,VarnodeData());
opcode = PcodeOpRaw::decode(decoder, isize, varStorage.data(), &outptr);
decoder.closeElement(elemId);
dump(addr,opcode,outptr,varStorage.data(),isize);
}
decoder.closeElement(elemId);
dump(addr,(OpCode)opcode,outptr,invar,isize);
}
} // End namespace ghidra
@@ -4,9 +4,9 @@
* 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.
@@ -490,6 +490,7 @@ UserPcodeOp *UserOpManage::registerBuiltin(uint4 i)
void UserOpManage::registerOp(UserPcodeOp *op)
{
unique_ptr<UserPcodeOp> owner(op); // Take ownership
int4 ind = op->getIndex();
if (ind < 0) throw LowlevelError("UserOp not assigned an index");
@@ -509,7 +510,7 @@ void UserOpManage::registerOp(UserPcodeOp *op)
// We assume this registration customizes an existing userop
delete useroplist[ind]; // Delete the old spec
}
useroplist[ind] = op; // Index crossref
useroplist[ind] = owner.release(); // Index crossref
useropmap[op->getName()] = op; // Name crossref
SegmentOp *s_op = dynamic_cast<SegmentOp *>(op);
@@ -533,15 +534,9 @@ void UserOpManage::registerOp(UserPcodeOp *op)
void UserOpManage::decodeSegmentOp(Decoder &decoder,Architecture *glb)
{
SegmentOp *s_op;
s_op = new SegmentOp("",glb,useroplist.size());
try {
s_op->decode(decoder);
registerOp(s_op);
} catch(LowlevelError &err) {
delete s_op;
throw err;
}
unique_ptr<UserPcodeOp> s_op(new SegmentOp("",glb,useroplist.size()));
s_op->decode(decoder);
registerOp(s_op.release());
}
/// Create either a VolatileReadOp or VolatileWriteOp description object based on
@@ -589,14 +584,9 @@ void UserOpManage::decodeVolatile(Decoder &decoder,Architecture *glb)
void UserOpManage::decodeCallOtherFixup(Decoder &decoder,Architecture *glb)
{
InjectedUserOp *op = new InjectedUserOp("",glb,0,0);
try {
op->decode(decoder);
registerOp(op);
} catch(LowlevelError &err) {
delete op;
throw err;
}
unique_ptr<UserPcodeOp> op(new InjectedUserOp("",glb,0,0));
op->decode(decoder);
registerOp(op.release());
}
/// Create a JumpAssistOp description object based on the element
@@ -606,14 +596,9 @@ void UserOpManage::decodeCallOtherFixup(Decoder &decoder,Architecture *glb)
void UserOpManage::decodeJumpAssist(Decoder &decoder,Architecture *glb)
{
JumpAssistOp *op = new JumpAssistOp(glb);
try {
op->decode(decoder);
registerOp(op);
} catch(LowlevelError &err) {
delete op;
throw err;
}
unique_ptr<UserPcodeOp> op(new JumpAssistOp(glb));
op->decode(decoder);
registerOp(op.release());
}
/// \brief Manually install an InjectedUserOp given just names of the user defined op and the p-code snippet
@@ -637,12 +622,7 @@ void UserOpManage::manualCallOtherFixup(const string &useropname,const string &o
int4 injectid = glb->pcodeinjectlib->manualCallOtherFixup(useropname,outname,inname,snippet);
InjectedUserOp *op = new InjectedUserOp(useropname,glb,userop->getIndex(),injectid);
try {
registerOp(op);
} catch(LowlevelError &err) {
delete op;
throw err;
}
registerOp(op);
}
} // End namespace ghidra
@@ -0,0 +1,89 @@
/* ###
* 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 "test.hh"
#include "multiprecision.hh"
namespace ghidra {
static uint8 num1[2] = { 0xffffffffffffffff, 0xffffffffffffffff };
static uint8 denom1[2] = { 1, 0 };
static uint8 num2[2] = { 0x89a732a9fb157c4d, 0x4eada2039e48443e };
static uint8 denom2[2] = { 0xbabf3b71, 0 };
static uint8 num3[2] = { 0xf7df0315d584ad8d, 0xb9d55c0d1d5cfbbd };
static uint8 denom3[2] = { 0x8aa797dbccee6e96, 0x646be9 };
static uint8 a[2] = { 0x1a309a9df2ce836a, 0xd66f2248906d1bdf };
static uint8 b[2] = { 0xf6c190704eb1763e, 0xa05c42212dfba7c6 };
TEST(multiprec_udiv) {
uint8 q[2];
uint8 r[2];
udiv128(num1, denom1, q, r);
ASSERT_EQUALS(q[0],0xffffffffffffffff);
ASSERT_EQUALS(q[1],0xffffffffffffffff);
ASSERT_EQUALS(r[0],0);
ASSERT_EQUALS(r[1],0);
udiv128(num2, denom2, q, r);
ASSERT_EQUALS(q[0], 0x2a21eef2058d7e9a);
ASSERT_EQUALS(q[1], 0x6bdaed99);
ASSERT_EQUALS(r[0], 0x928d1c53);
ASSERT_EQUALS(r[1], 0);
udiv128(num2,num1,q,r);
ASSERT_EQUALS(q[0], 0);
ASSERT_EQUALS(q[1], 0);
ASSERT_EQUALS(r[0],num2[0]);
ASSERT_EQUALS(r[1],num2[1]);
udiv128(num3,denom3,q,r);
ASSERT_EQUALS(q[0], 0x1d9bc949e24);
ASSERT_EQUALS(q[1], 0);
ASSERT_EQUALS(r[0], 0x2e78197dc5048c75);
ASSERT_EQUALS(r[1], 0x24d9cc);
}
TEST(multiprec_add) {
uint8 res[2];
add128(a,b,res);
ASSERT_EQUALS(res[0], 0x10f22b0e417ff9a8);
ASSERT_EQUALS(res[1], 0x76cb6469be68c3a6);
}
TEST(multiprec_sub) {
uint8 res[2];
subtract128(a,b,res);
ASSERT_EQUALS(res[0], 0x236F0A2DA41D0D2C);
ASSERT_EQUALS(res[1], 0x3612E02762717418);
}
TEST(multiprec_left) {
uint8 res[2];
leftshift128(num2, res, 51);
ASSERT_EQUALS(res[0], 0xe268000000000000);
ASSERT_EQUALS(res[1], 0x21f44d39954fd8ab);
}
TEST(multiprec_less) {
ASSERT(!uless128(a,a));
ASSERT(uless128(num2,num3));
ASSERT(uless128(denom1,denom2));
ASSERT(ulessequal128(a,a));
ASSERT(ulessequal128(num2,num3));
ASSERT(ulessequal128(denom2,denom2));
}
} // End namespace ghidra