Fix to idiom19 and fixFloatEmulation()

This commit is contained in:
Artur K 2012-07-15 20:17:16 +02:00
parent c19231a1bd
commit ca129c5177
13 changed files with 119 additions and 72 deletions

View File

@ -65,6 +65,8 @@ struct LivenessSet : public std::bitset<32>
{ {
return test(r-rAX); return test(r-rAX);
} }
private:
void postProcessCompositeRegs();
}; };
extern LivenessSet duReg[30]; extern LivenessSet duReg[30];

View File

@ -37,6 +37,8 @@ struct Idiom18 : public Idiom
protected: protected:
iICODE m_icodes[4]; iICODE m_icodes[4];
bool m_is_dec; bool m_is_dec;
/* type of variable: 1 = reg-var, 2 = local */
int m_idiom_type;
public: public:
Idiom18(Function *f) : Idiom(f) Idiom18(Function *f) : Idiom(f)
{ {
@ -64,7 +66,7 @@ struct Idiom20 : public Idiom
{ {
protected: protected:
iICODE m_icodes[4]; iICODE m_icodes[4];
bool m_is_dec; condNodeType m_is_dec;
public: public:
Idiom20(Function *f) : Idiom(f) Idiom20(Function *f) : Idiom(f)
{ {

View File

@ -75,8 +75,11 @@ public:
} }
static eReg subRegH(eReg reg); static eReg subRegH(eReg reg);
static eReg subRegL(eReg reg); static eReg subRegL(eReg reg);
static bool isMemOff(eReg r); static bool isMemOff(eReg r);
static bool isSubRegisterOf(eReg reg, eReg parent); static bool isSubRegisterOf(eReg reg, eReg parent);
static bool hasSubregisters(eReg reg);
static bool isPartOfComposite(eReg reg);
static eReg compositeParent(eReg reg);
}; };

View File

@ -16,6 +16,7 @@ def perform_test(exepath,filepath,outname,args)
printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n") printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n")
result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}` result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}` result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}`
result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}`
puts result puts result
p $? p $?
end end

View File

@ -297,7 +297,7 @@ void Function::codeGen (std::ostream &fs)
/* Recursive procedure. Displays the procedure's code in depth-first order /* Recursive procedure. Displays the procedure's code in depth-first order
* of the call graph. */ * of the call graph. */
static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &_ios) static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
{ {
// IFace.Yield(); /* This is a good place to yield to other apps */ // IFace.Yield(); /* This is a good place to yield to other apps */
@ -311,7 +311,7 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
/* Dfs if this procedure has any successors */ /* Dfs if this procedure has any successors */
for (size_t i = 0; i < pcallGraph->outEdges.size(); i++) for (size_t i = 0; i < pcallGraph->outEdges.size(); i++)
{ {
backBackEnd (filename, pcallGraph->outEdges[i], _ios); backBackEnd (pcallGraph->outEdges[i], _ios);
} }
/* Generate code for this procedure */ /* Generate code for this procedure */
@ -346,14 +346,14 @@ void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
printf ("dcc: Writing C beta file %s\n", outNam.c_str()); printf ("dcc: Writing C beta file %s\n", outNam.c_str());
/* Header information */ /* Header information */
writeHeader (fs, fileName); writeHeader (fs, option.filename);
/* Initialize total Icode instructions statistics */ /* Initialize total Icode instructions statistics */
stats.totalLL = 0; stats.totalLL = 0;
stats.totalHL = 0; stats.totalHL = 0;
/* Process each procedure at a time */ /* Process each procedure at a time */
backBackEnd (fileName, pcallGraph, fs); backBackEnd (pcallGraph, fs);
/* Close output file */ /* Close output file */
fs.close(); fs.close();

View File

@ -492,7 +492,7 @@ bool LibCheck(Function & pProc)
pProc.flg |= PROC_IS_FUNC; pProc.flg |= PROC_IS_FUNC;
switch (pProc.retVal.type) { switch (pProc.retVal.type) {
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
pProc.liveOut.setReg(rDX) |= duReg[rAX]; pProc.liveOut.setReg(rDX).addReg(rAX);
break; break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
pProc.liveOut.setReg(rAX); pProc.liveOut.setReg(rAX);
@ -500,8 +500,12 @@ bool LibCheck(Function & pProc)
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
pProc.liveOut.setReg(rAL); pProc.liveOut.setReg(rAL);
break; break;
case TYPE_PTR:
fprintf(stderr,"Warning assuming Large memory model\n");
pProc.liveOut.setReg(rAX).addReg(rDS);
break;
default: default:
fprintf(stderr,"Unknown retval type %d in LibCheck\n",pProc.retVal.type); fprintf(stderr,"Unknown retval type %d for %s in LibCheck\n",pProc.retVal.type,pProc.name.c_str());
/*** other types are not considered yet ***/ /*** other types are not considered yet ***/
} }
} }

View File

@ -4,16 +4,18 @@
* Purpose: Data flow analysis module. * Purpose: Data flow analysis module.
* (C) Cristina Cifuentes * (C) Cristina Cifuentes
****************************************************************************/ ****************************************************************************/
#include <stdint.h>
#include "dcc.h" #include <cstring>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <boost/range.hpp> #include <boost/range.hpp>
#include <boost/range/adaptors.hpp> #include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp> #include <boost/range/algorithm.hpp>
#include <boost/assign.hpp> #include <boost/assign.hpp>
#include <string.h>
#include <iostream> #include "dcc.h"
#include <iomanip>
#include <stdio.h>
using namespace boost; using namespace boost;
using namespace boost::adaptors; using namespace boost::adaptors;
struct ExpStack struct ExpStack
@ -232,11 +234,11 @@ void Function::elimCondCodes ()
/** Generates the LiveUse() and Def() sets for each basic block in the graph. /** Generates the LiveUse() and Def() sets for each basic block in the graph.
* Note: these sets are constant and could have been constructed during \note these sets are constant and could have been constructed during
* the construction of the graph, but since the code hasn't been the construction of the graph, but since the code hasn't been
* analyzed yet for idioms, the procedure preamble misleads the analyzed yet for idioms, the procedure preamble misleads the
* analysis (eg: push si, would include si in LiveUse; although it analysis (eg: push si, would include si in LiveUse; although it
* is not really meant to be a register that is used before defined). */ is not really meant to be a register that is used before defined). */
void Function::genLiveKtes () void Function::genLiveKtes ()
{ {
BB * pbb; BB * pbb;
@ -291,7 +293,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
{ {
/* Get current liveIn() and liveOut() sets */ /* Get current liveIn() and liveOut() sets */
prevLiveIn = pbb->liveIn; prevLiveIn = pbb->liveIn;
prevLiveOut = pbb->liveOut; prevLiveOut = pbb->liveOut;
/* liveOut(b) = U LiveIn(s); where s is successor(b) /* liveOut(b) = U LiveIn(s); where s is successor(b)
@ -503,22 +505,22 @@ void BB::genDU1()
assert(0!=Parent); assert(0!=Parent);
ICODE::TypeFilter<HIGH_LEVEL> select_high_level; ICODE::TypeFilter<HIGH_LEVEL> select_high_level;
auto all_high_levels = instructions | filtered(select_high_level); auto all_high_levels = instructions | filtered(select_high_level);
printf("\n");
for (auto picode=all_high_levels.begin(); picode!=all_high_levels.end(); ++picode) for (auto picode=all_high_levels.begin(); picode!=all_high_levels.end(); ++picode)
{ {
ICODE &ic = *picode;
int defRegIdx = 0; int defRegIdx = 0;
// foreach defined register // foreach defined register
for (int k = 0; k < INDEX_BX_SI; k++) for (int k = rAX; k < INDEX_BX_SI; k++)
{ {
if (not picode->du.def.test(k)) if (not ic.du.def.testReg(k))
continue; continue;
eReg regi = (eReg)(k + 1); /* Register that was defined */ eReg regi = (eReg)(k); /* Register that was defined */
picode->du1.regi[defRegIdx] = regi; picode->du1.regi[defRegIdx] = regi;
if(FindUseBeforeDef(regi,defRegIdx, picode.base())) if(FindUseBeforeDef(regi,defRegIdx, picode.base()))
continue; continue;
ProcessUseDefForFunc(regi, defRegIdx,*picode); ProcessUseDefForFunc(regi, defRegIdx,ic);
RemoveUnusedDefs(regi, defRegIdx, picode.base()); RemoveUnusedDefs(regi, defRegIdx, picode.base());
defRegIdx++; defRegIdx++;
@ -541,8 +543,7 @@ void Function::genDU1 ()
} }
/* Substitutes the rhs (or lhs if rhs not possible) of ticode for the rhs /* Substitutes the rhs (or lhs if rhs not possible) of ticode for the rhs of picode. */
* of picode. */
void LOCAL_ID::forwardSubs (COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const void LOCAL_ID::forwardSubs (COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const
{ {
bool res; bool res;
@ -570,8 +571,7 @@ void LOCAL_ID::forwardSubs (COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICOD
} }
/* Substitutes the rhs (or lhs if rhs not possible) of ticode for the /* Substitutes the rhs (or lhs if rhs not possible) of ticode for the expression exp given */
* expression exp given */
static void forwardSubsLong (int longIdx, COND_EXPR *_exp, iICODE picode, iICODE ticode, int *numHlIcodes) static void forwardSubsLong (int longIdx, COND_EXPR *_exp, iICODE picode, iICODE ticode, int *numHlIcodes)
{ {
bool res; bool res;

View File

@ -44,18 +44,21 @@ int main(int argc, char *argv[])
DccFrontend fe(option.filename); DccFrontend fe(option.filename);
if(false==fe.FrontEnd ()) if(false==fe.FrontEnd ())
return -1; return -1;
if(option.asm1)
return 0;
/* In the middle is a so called Universal Decompiling Machine. /* In the middle is a so called Universal Decompiling Machine.
* It processes the procedure list and I-code and attaches where it can * It processes the procedure list and I-code and attaches where it can
* to each procedure an optimised cfg and ud lists * to each procedure an optimised cfg and ud lists
*/ */
udm(); udm();
if(option.asm2)
return 0;
/* Back end converts each procedure into C using I-code, interval /* Back end converts each procedure into C using I-code, interval
* analysis, data flow etc. and outputs it to output file ready for * analysis, data flow etc. and outputs it to output file ready for
* re-compilation. * re-compilation.
*/ */
BackEnd(option.filename, Project::get()->callGraph); BackEnd(asm1_name ? asm1_name:option.filename, Project::get()->callGraph);
Project::get()->callGraph->write(); Project::get()->callGraph->write();

View File

@ -95,65 +95,68 @@ bool Idiom18::match(iICODE picode)
for(int i=0; i<4; ++i) for(int i=0; i<4; ++i)
m_icodes[i] =picode++; m_icodes[i] =picode++;
m_idiom_type=-1;
m_is_dec = m_icodes[1]->ll()->match(iDEC); m_is_dec = m_icodes[1]->ll()->match(iDEC);
int type = -1; /* type of variable: 1 = reg-var, 2 = local */
uint8_t regi; /* register of the MOV */ uint8_t regi; /* register of the MOV */
/* Get variable */ /* Get variable */
if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */ if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */
{ {
/* not supported yet */ /* not supported yet */
type = 0; m_idiom_type = 0;
} }
else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */ else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */
{ {
if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR)) if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
type = 1; m_idiom_type = 1;
else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR)) else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
type = 1; m_idiom_type = 1;
} }
else if (m_icodes[1]->ll()->dst.off) /* local variable */ else if (m_icodes[1]->ll()->dst.off) /* local variable */
type = 2; m_idiom_type = 2;
else /* indexed */ else /* indexed */
{ {
type=3; m_idiom_type=3;
/* not supported yet */ /* not supported yet */
printf("Unsupported idiom18 type: indexed"); ICODE &ic(*picode);
const Function *my_proc(ic.getParent()->getParent());
printf("Unsupported idiom18 type at %x in %s:%x : indexed\n",ic.loc_ip,my_proc->name.c_str(),my_proc->procEntry);
} }
switch(type) switch(m_idiom_type)
{ {
case 0: // global case 0: // global
printf("Unsupported idiom18 type: global variable"); printf("Unsupported idiom18 type at %x : global variable\n",picode->loc_ip);
break; break;
case 1: /* register variable */ case 1: /* register variable */
/* Check previous instruction for a MOV */ /* Check previous instruction for a MOV */
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi)) if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi))
{
regi = m_icodes[0]->ll()->dst.regi;
if ( m_icodes[0]->ll()->dst.isReg() )
{ {
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) && regi = m_icodes[0]->ll()->dst.regi;
m_icodes[3]->ll()->conditionalJump() ) if ( m_icodes[0]->ll()->dst.isReg() )
return true; {
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
m_icodes[3]->ll()->conditionalJump() )
return true;
}
} }
} break;
break; case 2: /* local */
case 2: /* local */ if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off))
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off))
{
regi = m_icodes[0]->ll()->dst.regi;
if ( m_icodes[0]->ll()->dst.isReg() )
{ {
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) && regi = m_icodes[0]->ll()->dst.regi;
m_icodes[3]->ll()->conditionalJump() ) if ( m_icodes[0]->ll()->dst.isReg() )
return true; {
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
m_icodes[3]->ll()->conditionalJump() )
return true;
}
} }
} break;
break; case 3: // indexed
case 3: // indexed printf("Unsupported idiom18 type: indexed");
printf("Unsupported idiom18 type: indexed"); break;
break;
} }
return false; return false;
} }
@ -188,6 +191,7 @@ bool Idiom19::match(iICODE picode)
{ {
if(std::distance(picode,m_end)<2) if(std::distance(picode,m_end)<2)
return false; return false;
ICODE &ic(*picode);
for(int i=0; i<2; ++i) for(int i=0; i<2; ++i)
m_icodes[i] =picode++; m_icodes[i] =picode++;
@ -215,7 +219,8 @@ bool Idiom19::match(iICODE picode)
int Idiom19::action() int Idiom19::action()
{ {
COND_EXPR *lhs,*rhs,*expr; COND_EXPR *lhs,*rhs,*expr;
lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE); ICODE &ic1(*m_icodes[1]);
lhs = COND_EXPR::id (*m_icodes[0]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs); lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
rhs = COND_EXPR::idKte (0, 2); rhs = COND_EXPR::idKte (0, 2);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]); expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
@ -248,7 +253,7 @@ bool Idiom20::match(iICODE picode)
for(int i=0; i<4; ++i) for(int i=0; i<4; ++i)
m_icodes[i] =picode++; m_icodes[i] =picode++;
m_is_dec = m_icodes[0]->ll()->match(iDEC); m_is_dec = m_icodes[0]->ll()->match(iDEC) ? PRE_DEC : PRE_INC;
LLOperand &ll_dest(m_icodes[0]->ll()->dst); LLOperand &ll_dest(m_icodes[0]->ll()->dst);
/* Get variable */ /* Get variable */
@ -306,7 +311,7 @@ int Idiom20::action()
{ {
COND_EXPR *lhs,*rhs,*expr; COND_EXPR *lhs,*rhs,*expr;
lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE); lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs); lhs = COND_EXPR::unary (m_is_dec, lhs);
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE); rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]); expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
m_icodes[3]->setJCond(expr); m_icodes[3]->setJCond(expr);

View File

@ -161,7 +161,6 @@ int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
{ {
/* Insert icode index in list */ /* Insert icode index in list */
entry.idx.push_back(ix_); entry.idx.push_back(ix_);
//entry.idx.insert(ix_);
return (idx); return (idx);
} }
} }
@ -169,7 +168,7 @@ int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
/* Not in the table, create new identifier */ /* Not in the table, create new identifier */
newIdent (t, REG_FRAME); newIdent (t, REG_FRAME);
id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_); id_arr[id_arr.size()-1].idx.push_back(ix_);
idx = id_arr.size() - 1; idx = id_arr.size() - 1;
id_arr[idx].id.longId.h = regH; id_arr[idx].id.longId.h = regH;
id_arr[idx].id.longId.l = regL; id_arr[idx].id.longId.l = regL;

View File

@ -17,7 +17,7 @@ static const std::string regNames[] = {
Machine_X86::Machine_X86() Machine_X86::Machine_X86()
{ {
static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG, static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG,
"Reg count not equal number of strings"); "Reg count not equal number of strings");
} }
const std::string &Machine_X86::regName(eReg r) const std::string &Machine_X86::regName(eReg r)
@ -109,3 +109,26 @@ bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent)
return false; // only AX -> BX are coverede by subregisters return false; // only AX -> BX are coverede by subregisters
return ((reg==subRegH(parent)) || (reg == subRegL(parent))); return ((reg==subRegH(parent)) || (reg == subRegL(parent)));
} }
bool Machine_X86::hasSubregisters(eReg reg)
{
return ((reg >= rAX) && (reg <= rBX));
}
bool Machine_X86::isPartOfComposite(eReg reg)
{
return ((reg >= rAL) && (reg <= rBH));
}
eReg Machine_X86::compositeParent(eReg reg)
{
switch(reg)
{
case rAL: case rAH: return rAX;
case rCL: case rCH: return rCX;
case rDL: case rDH: return rDX;
case rBL: case rBH: return rBX;
default:
return rUNDEF;
}
return rUNDEF;
}

View File

@ -350,6 +350,8 @@ static void convertUsedFlags(x86_insn_t &from,ICODE &to)
****************************************************************************/ ****************************************************************************/
static void fixFloatEmulation(x86_insn_t &insn) static void fixFloatEmulation(x86_insn_t &insn)
{ {
if(insn.operand_count==0)
return;
if(insn.group!=x86_insn_t::insn_interrupt) if(insn.group!=x86_insn_t::insn_interrupt)
return; return;
PROG &prog(Project::get()->prog); PROG &prog(Project::get()->prog);

View File

@ -31,6 +31,7 @@ void Function::buildCFG(Disassembler &ds)
if (option.asm2) if (option.asm2)
{ {
ds.disassem(this); // Print 2nd pass assembler listing ds.disassem(this); // Print 2nd pass assembler listing
return;
} }
/* Idiom analysis and propagation of long type */ /* Idiom analysis and propagation of long type */
@ -78,6 +79,8 @@ void udm(void)
{ {
iter->buildCFG(ds); iter->buildCFG(ds);
} }
if (option.asm2)
return;
/* Data flow analysis - eliminate condition codes, extraneous registers /* Data flow analysis - eliminate condition codes, extraneous registers