/* ### * 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 "override.hh" #include "funcdata.hh" ElementId ELEM_DEADCODEDELAY = ElementId("deadcodedelay",218); ElementId ELEM_FLOW = ElementId("flow",219); ElementId ELEM_FORCEGOTO = ElementId("forcegoto",220); ElementId ELEM_INDIRECTOVERRIDE = ElementId("indirectoverride",221); ElementId ELEM_MULTISTAGEJUMP = ElementId("multistagejump",222); ElementId ELEM_OVERRIDE = ElementId("override",223); ElementId ELEM_PROTOOVERRIDE = ElementId("protooverride",224); void Override::clear(void) { map
::iterator iter; for(iter=protoover.begin();iter!=protoover.end();++iter) delete (*iter).second; forcegoto.clear(); deadcodedelay.clear(); indirectover.clear(); protoover.clear(); multistagejump.clear(); flowoverride.clear(); } /// \brief Generate \e warning message related to a dead code delay /// /// This is triggered by the insertDeadcodeDelay() command on a specific address space /// \param index is the index of the address space /// \param glb is the Architecture object /// \return the generated message string Override::generateDeadcodeDelayMessage(int4 index,Architecture *glb) { AddrSpace *spc = glb->getSpace(index); string res = "Restarted to delay deadcode elimination for space: " + spc->getName(); return res; } /// \brief Force a specific branch instruction to be an unstructured \e goto /// /// The command is specified as the address of the branch instruction and /// the destination address of the branch. The decompiler will automatically /// mark this as a \e unstructured, when trying to structure the control-flow /// \param targetpc is the address of the branch instruction /// \param destpc is the destination address of the branch void Override::insertForceGoto(const Address &targetpc,const Address &destpc) { forcegoto[targetpc] = destpc; } /// \brief Override the number of passes that are executed before \e dead-code elimination starts /// /// Every address space has an assigned \e delay (which may be zero) before a PcodeOp /// involving a Varnode in that address space can be eliminated. This command allows the /// delay for a specific address space to be increased so that new Varnode accesses can be discovered. /// \param spc is the address space to modify /// \param delay is the size of the delay (in passes) void Override::insertDeadcodeDelay(AddrSpace *spc,int4 delay) { while(deadcodedelay.size() <= spc->getIndex()) deadcodedelay.push_back(-1); deadcodedelay[spc->getIndex()] = delay; } /// \brief Check if a delay override is already installed for an address space /// /// \param spc is the address space /// \return \b true if an override has already been installed bool Override::hasDeadcodeDelay(AddrSpace *spc) const { int4 index = spc->getIndex(); if (index >= deadcodedelay.size()) return false; int4 val = deadcodedelay[index]; if (val == -1) return false; return (val != spc->getDeadcodeDelay()); } /// \brief Override an indirect call turning it into a direct call /// /// The command consists of the address of the indirect call instruction and /// the target address of the direct address /// \param callpoint is the address of the indirect call /// \param directcall is the target address of the direct call void Override::insertIndirectOverride(const Address &callpoint,const Address &directcall) { indirectover[callpoint] = directcall; } /// \brief Override the assumed function prototype at a specific call site /// /// The exact input and output storage locations are overridden for a /// specific call instruction (direct or indirect). /// \param callpoint is the address of the call instruction /// \param p is the overriding function prototype void Override::insertProtoOverride(const Address &callpoint,FuncProto *p) { map::iterator iter; iter = protoover.find(callpoint); if (iter != protoover.end()) // Check for pre-existing override delete (*iter).second; // and delete it p->setOverride(true); // Mark this as an override protoover[callpoint] = p; // Take ownership of the object } /// \brief Flag an indirect jump for multistage analysis /// /// \param addr is the address of the indirect jump void Override::insertMultistageJump(const Address &addr) { multistagejump.push_back(addr); } /// \brief Mark a branch instruction with a different flow type /// /// Change the interpretation of a BRANCH, CALL, or RETURN /// \param addr is the address of the branch instruction /// \param type is the type of flow that should be forced void Override::insertFlowOverride(const Address &addr,uint4 type) { flowoverride[addr] = type; } /// \brief Look for and apply a function prototype override /// /// Given a call point, look for a prototype override and copy /// the call specification in /// \param data is the (calling) function /// \param fspecs is a reference to the call specification void Override::applyPrototype(Funcdata &data,FuncCallSpecs &fspecs) const { if (!protoover.empty()) { map::const_iterator iter = protoover.find(fspecs.getOp()->getAddr()); if (iter != protoover.end()) { fspecs.copy(*(*iter).second); } } } /// \brief Look for and apply destination overrides of indirect calls /// /// Given an indirect call, look for any overrides, then copy in /// the overriding target address of the direct call /// \param data is (calling) function /// \param fspecs is a reference to the call specification void Override::applyIndirect(Funcdata &data,FuncCallSpecs &fspecs) const { if (!indirectover.empty()) { map::const_iterator iter = indirectover.find(fspecs.getOp()->getAddr()); if (iter != indirectover.end()) fspecs.setAddress( (*iter).second ); } } /// \brief Check for a multistage marker for a specific indirect jump /// /// Given the address of an indirect jump, look for the multistate command /// \param addr is the address of the indirect jump bool Override::queryMultistageJumptable(const Address &addr) const { for(int4 i=0;i