/* ILEngineer - Crummy .NET Decompiler * Copyright (C) 2001-2002 Jay Freeman (saurik) */ /* * Redistribution and use in source and binary * forms, with or without modification, are permitted * provided that the following conditions are met: * * 1. Redistributions of source code must retain the * above copyright notice, this list of conditions * and the following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions * and the following disclaimer in the documentation * and/or other materials provided with the * distribution. * 3. The name of the author may not be used to endorse * or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "stdafx.h" #include "ilengineer/Operation.h" #include "ilengineer/Blocks/Method.h" #include "ilengineer/Ops/MSIL/Duplicate.h" #include "ilengineer/Ops/MSIL/LoadConstant.h" #include "ilengineer/Ops/MSIL/LoadNull.h" #include "ilengineer/Ops/ILE/CompareNotEqual.h" #include "ilengineer/Ops/ILE/LoadConstant.h" bool isOpen(false); int del(0); namespace ILEngineer { Stack::~Stack() { while (!empty()) { delete top(); pop(); } } Operation::Operation(Blocks::Method *method, uint8_t *offset, bool skip, bool garbage) : m_Method(method), m_Offset(offset), m_Skip(skip), m_Garbage(garbage), m_Parent(NULL), m_Scope(false) {} Operation::~Operation() { if (isOpen && isBroken) del++; if (!m_Garbage) { if (isOpen && isBroken) std::cout << "deleting opr: " << del << std::endl; for (OperationVector::iterator opI(m_Operations.begin()); opI != m_Operations.end(); opI++) { if (isOpen && isBroken) std::cout << "delete(" << del << "): " << typeid(**opI).name() << std::endl; delete *opI; } } if (isOpen && isBroken) del--; } void Operation::Find(const type_info &type, Operation::Reference::Vector &ops) { for (OperationVector::iterator opI(m_Operations.begin()); opI != m_Operations.end(); opI++) { (*opI)->Find(type, ops); if (!(*opI)->isSkip() && typeid(**opI) == type) ops.push_back(Operation::Reference(&m_Operations, opI)); } } bool Operation::Find(const type_info &type, Operation::Reference &ref) { for (OperationVector::iterator opI(m_Operations.begin()); opI != m_Operations.end(); opI++) { if ((*opI)->Find(type, ref)) return true; if (!(*opI)->isSkip() && typeid(**opI) == type) { ref = Operation::Reference(&m_Operations, opI); return true; } } return false; } bool Operation::Find(const uint8_t *offset, Operation::Reference &ref) { for (OperationVector::iterator opI(m_Operations.begin()); opI != m_Operations.end(); opI++) { if (!(*opI)->isSkip() && (*opI)->getOffset() == offset) { ref = Operation::Reference(&m_Operations, opI); return true; } if ((*opI)->Find(offset, ref)) return true; } return false; } bool Operation::FindDup(Ops::MSIL::Duplicate *dup1, Operation::Reference &ref) { for (OperationVector::iterator opI(m_Operations.begin()); opI != m_Operations.end(); opI++) { if ((*opI)->FindDup(dup1, ref)) return true; Ops::MSIL::Duplicate *dup2 = dynamic_cast(*opI); if (dup2 != NULL && dup1->isOrig() != dup2->isOrig() && dup1->getValue() == dup2->getValue()) { ref = Operation::Reference(&m_Operations, opI); return true; } } return false; } void Operation::Tack(Operation *tack, Chordata::Element::Type type) { const type_info &info = typeid(*tack); Operation *rep = NULL; switch (type) { case Chordata::Element::Boolean: if (info == typeid(Ops::MSIL::LoadI4Constant)) rep = new Ops::ILE::LoadBoolConstant(m_Method, tack->getOffset(), dynamic_cast(tack)->getConstant() != 0); else if (tack->getType()) { Chordata::Element::Type from(tack->getType()->getIntrinsic()); switch (from) { case Chordata::Element::I4: case Chordata::Element::ValueType: rep = new Ops::ILE::CompareNotEqual(m_Method, tack, new Ops::MSIL::LoadI4Constant(m_Method, NULL, 0)); tack = NULL; break; case Chordata::Element::Class: case Chordata::Element::Object: case Chordata::Element::String: case Chordata::Element::SZArray: rep = new Ops::ILE::CompareNotEqual(m_Method, tack, new Ops::MSIL::LoadNull(m_Method, NULL)); tack = NULL; break; } } break; case Chordata::Element::Char: if (info == typeid(Ops::MSIL::LoadI4Constant)) rep = new Ops::ILE::LoadCharConstant(m_Method, tack->getOffset(), (wchar_t) dynamic_cast(tack)->getConstant()); break; }; if (rep == NULL) Tack(tack); else { if (tack != NULL) delete tack; Tack(rep); } } }