pentiumfrontend.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1998-2001, The University of Queensland
00003  * Copyright (C) 2002, Trent Waddington
00004  *
00005  * See the file "LICENSE.TERMS" for information on usage and
00006  * redistribution of this file, and for a DISCLAIMER OF ALL
00007  * WARRANTIES.
00008  *
00009  */
00010 
00011 /*==============================================================================
00012  * FILE:       frontend/pentiumfrontend.cpp
00013  * OVERVIEW:   This file contains routines to manage the decoding of pentium instructions and the instantiation to RTLs.
00014  *             These functions replace frontend.cpp for decoding pentium instructions.
00015  *============================================================================*/
00016 
00017 /*
00018  * $Revision: 1.68 $    // 1.51.2.3
00019  *
00020  * 21 Oct 98 - Mike: converted from frontsparc.cc
00021  * 21 May 02 - Mike: Mods for boomerang
00022  * 27 Nov 02 - Mike: Fixed a bug in the floating point fixup code, which was screwing up registers in flag calls
00023  * 30 Sep 03 - Mike: processFloatCode ORs mask with 0x04 for compilers that ignore the C1 status bit (e.g. MSVC).
00024  *              Also more JE cases
00025  * 04 Aug 04 - Mike: Quick and dirty hack for overlapped registers (X86 only)
00026  * 31 Jul 06 - Tamlin: Fixed overlapped register processing for esi/edi/ebp plus a bug in ah/bh/ch/dh processing
00027 */
00028 
00029 #include <assert.h>
00030 #if defined(_MSC_VER) && _MSC_VER <= 1200
00031 #pragma warning(disable:4786)
00032 #endif
00033 
00034 #include <sstream>
00035 #include "types.h"
00036 #include "BinaryFile.h"
00037 #include "frontend.h"
00038 #include "pentiumfrontend.h"
00039 #include "rtl.h"
00040 #include "decoder.h"        // prototype for decodeInstruction()
00041 #include "pentiumdecoder.h"
00042 #include "register.h"
00043 #include "type.h"
00044 #include "cfg.h"
00045 #include "exp.h"
00046 #include "proc.h"
00047 #include "signature.h"
00048 #include "prog.h"           // For findProc()
00049 #include "BinaryFile.h"     // For SymbolByAddress()
00050 #include "boomerang.h"
00051 #include "log.h"
00052 
00053 /*==============================================================================
00054  * Forward declarations.
00055  *============================================================================*/
00056 
00057 #define FSW 40              // Numeric registers
00058 #define AH 12
00059 
00060 /*==============================================================================
00061  * FUNCTION:      isStoreFsw
00062  * OVERVIEW:      Return true if the given Statement is an assignment that stores the FSW (Floating point Status Word)
00063  *                  reg
00064  * PARAMETERS:    s - Ptr to the given Statement
00065  * RETURNS:       True if it is
00066  *============================================================================*/
00067 bool PentiumFrontEnd::isStoreFsw(Statement* s) {
00068     if (!s->isAssign()) return false;
00069     Exp* rhs = ((Assign*)s)->getRight();
00070     Exp* result;
00071     bool res = rhs->search(Location::regOf(FSW), result);
00072     return res;
00073 }
00074 /*==============================================================================
00075  * FUNCTION:      isDecAh
00076  * OVERVIEW:      Return true if the given RTL is a decrement of register AH
00077  * PARAMETERS:    r - Ptr to the given RTL
00078  * RETURNS:       True if it is
00079  *============================================================================*/
00080 bool PentiumFrontEnd::isDecAh(RTL* r) {
00081     // Check for decrement; RHS of middle Exp will be r[12]{8} - 1
00082     if (r->getNumStmt() != 3) return false;
00083     Statement* mid = r->elementAt(1);
00084     if (!mid->isAssign()) return false;
00085     Assign* asgn = (Assign*)mid;
00086     Exp* rhs = asgn->getRight();
00087     Binary ahm1(opMinus,
00088         new Binary(opSize,
00089             new Const(8),
00090             Location::regOf(12)),
00091         new Const(1));
00092     return *rhs == ahm1;
00093 }
00094 /*==============================================================================
00095  * FUNCTION:      isSetX
00096  * OVERVIEW:      Return true if the given Statement is a setX instruction
00097  * PARAMETERS:    s - Ptr to the given Statement
00098  * RETURNS:       True if it is
00099  *============================================================================*/
00100 bool PentiumFrontEnd::isSetX(Statement* s) {
00101     // Check for SETX, i.e. <exp> ? 1 : 0
00102     // i.e. ?: <exp> Const 1 Const 0
00103     if (!s->isAssign()) return false;
00104     Assign* asgn = (Assign*)s;
00105     Exp* lhs = asgn->getLeft();
00106     // LHS must be a register
00107     if (!lhs->isRegOf()) return false;
00108     Exp* rhs = asgn->getRight();
00109     if (rhs->getOper() != opTern) return false;
00110     Exp* s2 = ((Ternary*)rhs)->getSubExp2();
00111     Exp* s3 = ((Ternary*)rhs)->getSubExp3();
00112     if (!s2->isIntConst() || s3->isIntConst()) return false;
00113     return ((Const*)s2)->getInt() == 1 && ((Const*)s3)->getInt() == 0;
00114 }
00115 /*==============================================================================
00116  * FUNCTION:      isAssignFromTern
00117  * OVERVIEW:      Return true if the given Statement is an expression whose RHS is a ?: ternary
00118  * PARAMETERS:    e - Ptr to the given Statement
00119  * RETURNS:       True if it is
00120  *============================================================================*/
00121 bool PentiumFrontEnd::isAssignFromTern(Statement* s) {
00122     if (!s->isAssign()) return false;
00123     Assign* asgn = (Assign*)s;
00124     Exp* rhs = asgn->getRight();
00125     return rhs->getOper() == opTern;
00126 }
00127 /*==============================================================================
00128  * FUNCTION:        PentiumFrontEnd::bumpRegisterAll
00129  * OVERVIEW:        Finds a subexpression within this expression of the form
00130  *                    r[ int x] where min <= x <= max, and replaces it with
00131  *                    r[ int y] where y = min + (x - min + delta & mask)
00132  * PARAMETERS:      e: Expression to modify
00133  *                  min, max: minimum and maximum register numbers before any change is considered
00134  *                  delta: amount to bump up the register number by
00135  *                  mask: see above
00136  * APPLICATION:     Used to "flatten" stack floating point arithmetic (e.g. Pentium floating point code)
00137  *                    If registers are not replaced "all at once" like this, there can be subtle errors from
00138  *                    re-replacing already replaced registers
00139  * RETURNS:         Nothing
00140  *============================================================================*/
00141 void PentiumFrontEnd::bumpRegisterAll(Exp* e, int min, int max, int delta, int mask) {
00142     std::list<Exp**> li;
00143     std::list<Exp**>::iterator it;
00144     Exp* exp = e;
00145     // Use doSearch, which is normally an internal method of Exp, to avoid problems of replacing the wrong
00146     // subexpression (in some odd cases)
00147     Exp::doSearch(Location::regOf(new Terminal(opWild)), exp, li, false);
00148     for (it = li.begin(); it != li.end(); it++) {
00149         int reg = ((Const*)((Unary*)**it)->getSubExp1())->getInt();
00150         if ((min <= reg) && (reg <= max)) {
00151             // Replace the K in r[ K] with a new K
00152             // **it is a reg[K]
00153             Const* K = (Const*)((Unary*)**it)->getSubExp1();
00154             K->setInt(min + (reg - min + delta & mask));
00155         }
00156     }
00157 }
00158 /*==============================================================================
00159  * FUNCTION:      PentiumFrontEnd::processProc
00160  * OVERVIEW:      Process a procedure, given a native (source machine) address.
00161  * PARAMETERS:    address - the address at which the procedure starts
00162  *                pProc - the procedure object
00163  *                os - output stream for rtl output
00164  *                frag - true if decoding only a fragment of the proc
00165  *                spec - true if a speculative decode
00166  * RETURNS:       True if successful decode
00167  *============================================================================*/
00168 bool PentiumFrontEnd::processProc(ADDRESS uAddr, UserProc* pProc, std::ofstream &os, bool frag /* = false */,
00169         bool spec /* = false */) {
00170 
00171     // Call the base class to do most of the work
00172     if (!FrontEnd::processProc(uAddr, pProc, os, frag, spec))
00173         return false;
00174 
00175     // Need a post-cfg pass to remove the FPUSH and FPOP instructions, and to transform various code after floating
00176     // point compares to generate floating point branches.
00177     // processFloatCode() will recurse to process its out-edge BBs (if not already processed)
00178     Cfg* pCfg = pProc->getCFG();
00179     pCfg->unTraverse();         // Reset all the "traversed" flags (needed soon)
00180     // This will get done twice; no harm
00181     pProc->setEntryBB();
00182 
00183     processFloatCode(pCfg);
00184 
00185     int tos = 0;
00186     processFloatCode(pProc->getEntryBB(), tos, pCfg); 
00187 
00188     // Process away %rpt and %skip
00189     processStringInst(pProc);
00190 
00191     // Process code for side effects of overlapped registers
00192     processOverlapped(pProc);
00193 
00194     return true;
00195 }
00196 
00197 std::vector<Exp*> &PentiumFrontEnd::getDefaultParams()
00198 {
00199     static std::vector<Exp*> params;
00200     if (params.size() == 0) {
00201         params.push_back(Location::regOf(24/*eax*/));
00202         params.push_back(Location::regOf(25/*ecx*/));
00203         params.push_back(Location::regOf(26/*edx*/));
00204         params.push_back(Location::regOf(27/*ebx*/));
00205         params.push_back(Location::regOf(28/*esp*/));
00206         params.push_back(Location::regOf(29/*ebp*/));
00207         params.push_back(Location::regOf(30/*esi*/));
00208         params.push_back(Location::regOf(31/*edi*/));
00209         params.push_back(Location::memOf(Location::regOf(28)));
00210     }
00211     return params;
00212 }
00213 
00214 std::vector<Exp*> &PentiumFrontEnd::getDefaultReturns()
00215 {
00216     static std::vector<Exp*> returns;
00217     if (returns.size() == 0) {
00218         returns.push_back(Location::regOf(24/*eax*/));
00219         returns.push_back(Location::regOf(25/*ecx*/));
00220         returns.push_back(Location::regOf(26/*edx*/));
00221         returns.push_back(Location::regOf(27/*ebx*/));
00222         returns.push_back(Location::regOf(28/*esp*/));
00223         returns.push_back(Location::regOf(29/*ebp*/));
00224         returns.push_back(Location::regOf(30/*esi*/));
00225         returns.push_back(Location::regOf(31/*edi*/));
00226         returns.push_back(Location::regOf(32/*st0*/));
00227         returns.push_back(Location::regOf(33/*st1*/));
00228         returns.push_back(Location::regOf(34/*st2*/));
00229         returns.push_back(Location::regOf(35/*st3*/));
00230         returns.push_back(Location::regOf(36/*st4*/));
00231         returns.push_back(Location::regOf(37/*st5*/));
00232         returns.push_back(Location::regOf(38/*st6*/));
00233         returns.push_back(Location::regOf(39/*st7*/));
00234         returns.push_back(new Terminal(opPC));
00235     }
00236     return returns;
00237 }
00238 
00239 void PentiumFrontEnd::processFloatCode(Cfg* pCfg)
00240 {
00241     BB_IT it;
00242     for (PBB pBB = pCfg->getFirstBB(it); pBB; pBB = pCfg->getNextBB(it)) {
00243         std::list<RTL*>::iterator rit;
00244         Statement* st;
00245 
00246         // Loop through each RTL this BB
00247         std::list<RTL*>* BB_rtls = pBB->getRTLs();
00248         if (BB_rtls == 0) {
00249             // For example, incomplete BB
00250             return;
00251         }
00252         rit = BB_rtls->begin();
00253         while (rit != BB_rtls->end()) {
00254             for (int i=0; i < (*rit)->getNumStmt(); i++) {
00255                 // Get the current Exp
00256                 st = (*rit)->elementAt(i);
00257                 if (st->isFpush()) {
00258                     (*rit)->insertStmt(new Assign(new FloatType(80),
00259                         Location::tempOf(new Const("tmpD9")), 
00260                         Location::regOf(39)), i++);
00261                     (*rit)->insertStmt(new Assign(new FloatType(80),
00262                         Location::regOf(39), 
00263                         Location::regOf(38)), i++);
00264                     (*rit)->insertStmt(new Assign(new FloatType(80),
00265                         Location::regOf(38), 
00266                         Location::regOf(37)), i++);
00267                     (*rit)->insertStmt(new Assign(new FloatType(80),
00268                         Location::regOf(37), 
00269                         Location::regOf(36)), i++);
00270                     (*rit)->insertStmt(new Assign(new FloatType(80),
00271                         Location::regOf(36), 
00272                         Location::regOf(35)), i++);
00273                     (*rit)->insertStmt(new Assign(new FloatType(80),
00274                         Location::regOf(35), 
00275                         Location::regOf(34)), i++);
00276                     (*rit)->insertStmt(new Assign(new FloatType(80),
00277                         Location::regOf(34), 
00278                         Location::regOf(33)), i++);
00279                     (*rit)->insertStmt(new Assign(new FloatType(80),
00280                         Location::regOf(33), 
00281                         Location::regOf(32)), i++);
00282                     (*rit)->insertStmt(new Assign(new FloatType(80),
00283                         Location::regOf(32), 
00284                         Location::tempOf(new Const("tmpD9"))), i++);
00285                     // Remove the FPUSH
00286                     (*rit)->deleteStmt(i);
00287                     i--;
00288                     continue;
00289                 }
00290                 else if (st->isFpop()) {
00291                     (*rit)->insertStmt(new Assign(new FloatType(80),
00292                         Location::tempOf(new Const("tmpD9")), 
00293                         Location::regOf(32)), i++);
00294                     (*rit)->insertStmt(new Assign(new FloatType(80),
00295                         Location::regOf(32), 
00296                         Location::regOf(33)), i++);
00297                     (*rit)->insertStmt(new Assign(new FloatType(80),
00298                         Location::regOf(33), 
00299                         Location::regOf(34)), i++);
00300                     (*rit)->insertStmt(new Assign(new FloatType(80),
00301                         Location::regOf(34), 
00302                         Location::regOf(35)), i++);
00303                     (*rit)->insertStmt(new Assign(new FloatType(80),
00304                         Location::regOf(35), 
00305                         Location::regOf(36)), i++);
00306                     (*rit)->insertStmt(new Assign(new FloatType(80),
00307                         Location::regOf(36), 
00308                         Location::regOf(37)), i++);
00309                     (*rit)->insertStmt(new Assign(new FloatType(80),
00310                         Location::regOf(37), 
00311                         Location::regOf(38)), i++);
00312                     (*rit)->insertStmt(new Assign(new FloatType(80),
00313                         Location::regOf(38), 
00314                         Location::regOf(39)), i++);
00315                     (*rit)->insertStmt(new Assign(new FloatType(80),
00316                         Location::regOf(39), 
00317                         Location::tempOf(new Const("tmpD9"))), i++);
00318                     // Remove the FPOP
00319                     (*rit)->deleteStmt(i);
00320                     i--;
00321                     continue;
00322                 }
00323             }
00324             rit++;
00325         }
00326     }
00327 }
00328 
00329 /*==============================================================================
00330  * FUNCTION:      processFloatCode
00331  * OVERVIEW:      Process a basic block, and all its successors, for floating point code.
00332  *                  Remove FPUSH/FPOP, instead decrementing or incrementing respectively the tos value to be used from
00333  *                  here down. Note: tos has to be a parameter, not a global, to get the right value at any point in
00334  *                  the call tree
00335  * PARAMETERS:    pBB: pointer to the current BB
00336  *                tos: reference to the value of the "top of stack" pointer currently. Starts at zero, and is
00337  *                  decremented to 7 with the first load, so r[39] should be used first, then r[38] etc. However, it is
00338  *                  reset to 0 for calls, so that if a function returns a float, then it will always appear in r[32]
00339  * RETURNS:       <nothing>
00340  *============================================================================*/
00341 void PentiumFrontEnd::processFloatCode(PBB pBB, int& tos, Cfg* pCfg)
00342 {
00343     std::list<RTL*>::iterator rit;
00344     Statement* st;
00345 
00346     // Loop through each RTL this BB
00347     std::list<RTL*>* BB_rtls = pBB->getRTLs();
00348     if (BB_rtls == 0) {
00349         // For example, incomplete BB
00350         return;
00351     }
00352     rit = BB_rtls->begin();
00353     while (rit != BB_rtls->end()) {
00354         // Check for call.
00355         if ((*rit)->isCall()) {
00356             // Reset the "top of stack" index. If this is not done, then after a sequence of calls to functions
00357             // returning floats, the value will appear to be returned in registers r[32], then r[33], etc.
00358             tos = 0;
00359         }
00360         if ((*rit)->getNumStmt() == 0) { rit++; continue; }
00361 #if PROCESS_FNSTSW
00362         // Check for f(n)stsw
00363         if (isStoreFsw((*rit)->elementAt(0))) {
00364             // Check the register - at present we only handle AX
00365             Exp* lhs = ((Assign*)(*rit)->elementAt(0))->getLeft();
00366             Exp* ax = Location::regOf(0);
00367             assert(*lhs == *ax);
00368             delete ax;
00369 
00370             // Process it
00371             if (processStsw(rit, BB_rtls, pBB, pCfg)) {
00372                 // If returned true, must abandon this BB.
00373                 break;
00374             }
00375             // Else we have already skiped past the stsw, and/or any instructions that replace it, so process rest of
00376             // this BB
00377             continue;
00378         }
00379 #endif
00380         for (int i=0; i < (*rit)->getNumStmt(); i++) {
00381             // Get the current Exp
00382             st = (*rit)->elementAt(i);
00383             if (!st->isFlagAssgn()) {
00384                 // We are interested in either FPUSH/FPOP, or r[32..39] appearing in either the left or right hand
00385                 // sides, or calls
00386                 if (st->isFpush()) {
00387                     tos = (tos - 1) & 7;
00388                     // Remove the FPUSH
00389                     (*rit)->deleteStmt(i);
00390                     i--;            // Adjust the index
00391                     continue;
00392                 }
00393                 else if (st->isFpop()) {
00394                     tos = (tos + 1) & 7;
00395                     // Remove the FPOP
00396                     (*rit)->deleteStmt(i);
00397                     i--;            // Adjust the index
00398                     continue;
00399                 }
00400                 else if (st->isAssign()) {
00401                     Assign* asgn = (Assign*)st;
00402                     Exp* lhs = asgn->getLeft();
00403                     Exp* rhs = asgn->getRight();
00404                     if (tos != 0) {
00405                         // Substitute all occurrences of r[x] (where 32 <= x <= 39) with r[y] where
00406                         // y = 32 + (x + tos) & 7
00407                         bumpRegisterAll(lhs, 32, 39, tos, 7);
00408                         bumpRegisterAll(rhs, 32, 39, tos, 7);
00409                     }
00410                 }
00411             }
00412             else {
00413                 // st is a flagcall
00414                 // We are interested in any register parameters in the range 32 - 39
00415                 Binary* cur;
00416                 for (cur = (Binary*)((Assign*)st)->getRight(); !cur->isNil(); cur = (Binary*)cur->getSubExp2()) {
00417 // I dont understand why we want typed exps in the flag calls so much. If we're going to replace opSize with TypedExps
00418 // then we need to do it for everything, not just the flag calls.. so that should be in the sslparser.  If that is the
00419 // case then we cant assume that opLists of flag calls will always contain TypedExps, so this code is wrong.
00420 // - trent 9/6/2002
00421 //                  TypedExp* te = (TypedExp*)cur->getSubExp1();
00422                     Exp* s = cur->getSubExp1();
00423                     if (s->isRegOfK()) {
00424                         Const* c = (Const*)((Unary*)s)->getSubExp1();
00425                         int K = c->getInt();        // Old register number
00426                         // Change to new register number, if in range
00427                         if ((K >= 32) && (K <= 39))
00428                             s->setSubExp1(new Const(32 + (K - 32 + tos & 7)));
00429                     }
00430                 }
00431                         
00432             }
00433         }
00434         rit++;
00435     }
00436     pBB->setTraversed(true);
00437 
00438     // Now recurse to process my out edges, if not already processed
00439     const std::vector<PBB>& outs = pBB->getOutEdges();
00440     unsigned n;
00441     do {
00442         n = outs.size();
00443         for (unsigned o=0; o<n; o++) {
00444             PBB anOut = outs[o];
00445             if (!anOut->isTraversed()) {
00446                 processFloatCode(anOut, tos, pCfg);
00447                 if (outs.size() != n)
00448                     // During the processing, we have added or more likely deleted a BB, and the vector of out edges
00449                     // has changed.  It's safe to just start the inner for loop again
00450                     break;
00451             }
00452         }
00453     } while (outs.size() != n);            
00454 }
00455 
00456 
00457 
00458 // Emit Rtl of the form *8* lhs = [cond ? 1 : 0]
00459 // Insert before rit
00460 void PentiumFrontEnd::emitSet(std::list<RTL*>* BB_rtls, std::list<RTL*>::iterator& rit, ADDRESS uAddr, Exp* lhs,
00461         Exp* cond) {
00462 
00463     Statement* asgn = new Assign(
00464         lhs,
00465         new Ternary(opTern,
00466             cond,
00467             new Const(1),
00468             new Const(0)));
00469     RTL* pRtl = new RTL(uAddr);
00470     pRtl->appendStmt(asgn);
00471 //  std::cout << "Emit "; pRtl->print(); std::cout << std::endl;
00472     // Insert the new RTL before rit
00473     BB_rtls->insert(rit, pRtl);
00474 }
00475 
00476 /*==============================================================================
00477  * FUNCTION:        helperFunc
00478  * OVERVIEW:        Checks for pentium specific helper functions like __xtol which have specific sematics.
00479  * NOTE:            This needs to be handled in a resourcable way.
00480  * PARAMETERS:      dest - the native destination of this call
00481  *                  addr - the native address of this call instruction
00482  *                  lrtl - pointer to a list of RTL pointers for this BB
00483  * RETURNS:         true if a helper function is converted; false otherwise
00484  *============================================================================*/
00485 bool PentiumFrontEnd::helperFunc(ADDRESS dest, ADDRESS addr, std::list<RTL*>* lrtl)
00486 {
00487     if (dest == NO_ADDRESS) return false;
00488 
00489     const char* p = pBF->SymbolByAddress(dest);
00490     if (p == NULL) return false;
00491     std::string name(p);
00492     // I believe that __xtol is for gcc, _ftol for earlier MSVC compilers, _ftol2 for MSVC V7
00493     if (name == "__xtol" || name == "_ftol" || name == "_ftol2") {
00494         // This appears to pop the top of stack, and converts the result to a 64 bit integer in edx:eax.
00495         // Truncates towards zero
00496         // r[tmpl] = ftoi(80, 64, r[32])
00497         // r[24] = trunc(64, 32, r[tmpl])
00498         // r[26] = r[tmpl] >> 32
00499         Statement* a = new Assign(new IntegerType(64),
00500             Location::tempOf(new Const("tmpl")),
00501             new Ternary(opFtoi,
00502                 new Const(64),
00503                 new Const(32),
00504                 Location::regOf(32)));
00505         RTL* pRtl = new RTL(addr);
00506         pRtl->appendStmt(a);
00507         a = new Assign(
00508             Location::regOf(24),
00509             new Ternary(opTruncs,
00510                 new Const(64),
00511                 new Const(32),
00512                 Location::tempOf(new Const("tmpl"))));
00513         pRtl->appendStmt(a);
00514         a = new Assign(
00515             Location::regOf(26),
00516             new Binary(opShiftR,
00517                 Location::tempOf(new Const("tmpl")),
00518                 new Const(32)));
00519         pRtl->appendStmt(a);
00520         // Append this RTL to the list of RTLs for this BB
00521         lrtl->push_back(pRtl);
00522         // Return true, so the caller knows not to create a HLCall
00523         return true;
00524 
00525     } else if (name == "__mingw_allocstack") {
00526         RTL* pRtl = new RTL(addr);
00527         Statement* a = new Assign(
00528                 Location::regOf(28),
00529                 new Binary(opMinus,
00530                     Location::regOf(28),
00531                     Location::regOf(24)));
00532         pRtl->appendStmt(a);
00533         lrtl->push_back(pRtl);
00534         prog->removeProc(name.c_str());
00535         return true;
00536     } else if (name == "__mingw_frame_init" || name == "__mingw_cleanup_setup" || name == "__mingw_frame_end") {
00537         LOG << "found removable call to static lib proc " << name << " at " << addr << "\n";
00538         prog->removeProc(name.c_str());
00539         return true;
00540     } else {
00541         // Will be other cases in future
00542     }
00543     return false;
00544 }
00545 
00546 /*==============================================================================
00547  * FUNCTION:      construct
00548  * OVERVIEW:      Construct a new instance of PentiumFrontEnd
00549  * PARAMETERS:    Same as the FrontEnd constructor, except decoder is **
00550  * RETURNS:       <nothing>
00551  *============================================================================*/
00552 #ifdef DYNAMIC
00553 extern "C" {
00554     PentiumFrontEnd* construct(Prog *prog, NJMCDecoder** decoder) {
00555         PentiumFrontEnd *fe = new PentiumFrontEnd(prog);
00556         *decoder = fe->getDecoder();
00557         return fe;
00558     }
00559 }
00560 #endif
00561 
00562 /*==============================================================================
00563  * FUNCTION:      PentiumFrontEnd::PentiumFrontEnd
00564  * OVERVIEW:      PentiumFrontEnd constructor
00565  * NOTE:          Seems to be necessary to put this here; forces the vtable
00566  *                  entries to point to this dynamic linked library
00567  * PARAMETERS:    Same as the FrontEnd constructor
00568  * RETURNS:       <N/A>
00569  *============================================================================*/
00570 PentiumFrontEnd::PentiumFrontEnd(BinaryFile *pBF, Prog* prog, BinaryFileFactory* pbff) : FrontEnd(pBF, prog, pbff),
00571         idPF(-1) {
00572     decoder = new PentiumDecoder(prog);
00573 }
00574 
00575 // destructor
00576 PentiumFrontEnd::~PentiumFrontEnd()
00577 {
00578 }
00579 
00580 /*==============================================================================
00581  * FUNCTION:    GetMainEntryPoint
00582  * OVERVIEW:    Locate the starting address of "main" in the code section
00583  * PARAMETERS:  None
00584  * RETURNS:     Native pointer if found; NO_ADDRESS if not
00585  *============================================================================*/
00586 ADDRESS PentiumFrontEnd::getMainEntryPoint(bool& gotMain) {
00587     gotMain = true;
00588     ADDRESS start = pBF->GetMainEntryPoint();
00589     if( start != NO_ADDRESS ) return start;
00590 
00591     gotMain = false;
00592     start = pBF->GetEntryPoint();
00593     if (start == 0 || start == NO_ADDRESS)
00594         return NO_ADDRESS;
00595     
00596     int instCount = 100;
00597     int conseq = 0;
00598     ADDRESS addr = start;
00599         
00600     // Look for 3 calls in a row in the first 100 instructions, with no other instructions between them.
00601     // This is the "windows" pattern. Another windows pattern: call to GetModuleHandleA followed by
00602     // a push of eax and then the call to main.  Or a call to __libc_start_main
00603     ADDRESS dest;
00604     do {
00605         DecodeResult inst = decodeInstruction(addr);
00606         if (inst.rtl == NULL)
00607             // Must have gotten out of step
00608             break;
00609         CallStatement* cs = NULL;
00610         if (inst.rtl->getList().size())
00611             cs = (CallStatement*)(inst.rtl->getList().back());
00612         if (cs && cs->getKind() == STMT_CALL &&
00613                 cs->getDest()->getOper() == opMemOf &&
00614                 cs->getDest()->getSubExp1()->getOper() == opIntConst &&
00615                 pBF->IsDynamicLinkedProcPointer(((Const*)cs->getDest() ->getSubExp1())->getAddr()) &&
00616                 !strcmp(pBF->GetDynamicProcName(((Const*)cs->getDest()->getSubExp1())->getAddr()), "GetModuleHandleA"))
00617         {
00618 #if 0
00619             std::cerr << "consider " << std::hex << addr << " " <<
00620                 pBF->GetDynamicProcName(((Const*)cs->getDest()->getSubExp1())->getAddr()) << std::endl;
00621 #endif
00622             int oNumBytes = inst.numBytes;
00623             inst = decodeInstruction(addr + oNumBytes);
00624             if (inst.valid && inst.rtl->getNumStmt() == 2) {
00625                 Assign* a = dynamic_cast<Assign*>(inst.rtl->elementAt(1));
00626                 if (a && *a->getRight() == *Location::regOf(24)) {
00627 #if 0
00628                     std::cerr << "is followed by push eax.. " << "good" << std::endl;
00629 #endif
00630                     inst = decodeInstruction(addr + oNumBytes + inst.numBytes);
00631                     if (inst.rtl->getList().size()) {
00632                         CallStatement *toMain = dynamic_cast<CallStatement*>(inst.rtl->getList().back());
00633                         if (toMain && toMain->getFixedDest() != NO_ADDRESS) {
00634                             pBF->AddSymbol(toMain->getFixedDest(), "WinMain");
00635                             gotMain = true;
00636                             return toMain->getFixedDest();
00637                         }
00638                     }
00639                 }
00640             }
00641         }
00642         if ((cs && cs->getKind() == STMT_CALL) && ((dest = (cs->getFixedDest())) != NO_ADDRESS)) {
00643             if (++conseq == 3 && 0) { // FIXME: this isn't working!
00644                 // Success. Return the target of the last call
00645                 gotMain = true;
00646                 return cs->getFixedDest();
00647             }
00648             if (pBF->SymbolByAddress(dest) &&
00649                     strcmp(pBF->SymbolByAddress(dest), "__libc_start_main") == 0) {
00650                 // This is a gcc 3 pattern. The first parameter will be a pointer to main.
00651                 // Assume it's the 5 byte push immediately preceeding this instruction
00652                 // Note: the RTL changed recently from esp = esp-4; m[esp] = K tp m[esp-4] = K; esp = esp-4
00653                 inst = decodeInstruction(addr-5);
00654                 assert(inst.valid);
00655                 assert(inst.rtl->getNumStmt() == 2);
00656                 Assign* a = (Assign*) inst.rtl->elementAt(0);       // Get m[esp-4] = K
00657                 Exp* rhs = a->getRight();
00658                 assert(rhs->isIntConst());
00659                 gotMain = true;
00660                 return (ADDRESS)((Const*)rhs)->getInt();
00661             }
00662         }
00663         else 
00664             conseq = 0;         // Must be consequitive
00665         GotoStatement* gs = (GotoStatement*)cs;
00666         if (gs && gs->getKind() == STMT_GOTO)
00667             // Example: Borland often starts with a branch around some debug
00668             // info
00669             addr = gs->getFixedDest();
00670         else
00671             addr += inst.numBytes;
00672     } while (--instCount);
00673 
00674     // Last chance check: look for _main (e.g. Borland programs)
00675     ADDRESS umain = pBF->GetAddressByName("_main");
00676     if (umain != NO_ADDRESS) return umain;
00677 
00678     // Not ideal; we must return start
00679     std::cerr << "main function not found\n";
00680 
00681     this->AddSymbol(start, "_start");
00682 
00683     return start;
00684 }
00685 
00686 void toBranches(ADDRESS a, bool lastRtl, Cfg* cfg, RTL* rtl, PBB bb, BB_IT& it)
00687 {
00688     BranchStatement* br1 = new BranchStatement;
00689     assert(rtl->getList().size() >= 4);     // They vary; at least 5 or 6
00690     Statement* s1 = *rtl->getList().begin();
00691     Statement* s6 = *(--rtl->getList().end());
00692     if (s1->isAssign())
00693         br1->setCondExpr(((Assign*)s1)->getRight());
00694     else
00695         br1->setCondExpr(NULL);
00696     br1->setDest(a+2);
00697     BranchStatement* br2 = new BranchStatement;
00698     if (s6->isAssign())
00699         br2->setCondExpr(((Assign*)s6)->getRight());
00700     else
00701         br2->setCondExpr(NULL);
00702     br2->setDest(a);
00703     cfg->splitForBranch(bb, rtl, br1, br2, it);
00704 }
00705 
00706 void PentiumFrontEnd::processStringInst(UserProc* proc) {
00707     Cfg::iterator it;
00708     Cfg* cfg = proc->getCFG();
00709     // For each BB this proc
00710     for (it = cfg->begin(); it != cfg->end(); /* no increment! */) {
00711         bool noinc = false;
00712         PBB bb = *it;
00713         std::list<RTL*> *rtls = bb->getRTLs();
00714         if (rtls == NULL)
00715             break;
00716         ADDRESS prev, addr = 0;
00717         bool lastRtl = true;
00718         // For each RTL this BB
00719         for (std::list<RTL*>::iterator rit = rtls->begin(); rit != rtls->end(); rit++) {
00720             RTL *rtl = *rit;
00721             prev = addr;
00722             addr = rtl->getAddress();
00723             if (rtl->getList().size()) {
00724                 Statement* firstStmt = *rtl->getList().begin();
00725                 if (firstStmt->isAssign()) {
00726                     Exp* lhs = ((Assign*)firstStmt)->getLeft();
00727                     if (lhs->isMachFtr()) {
00728                         Const* sub = (Const*)((Unary*)lhs)->getSubExp1();
00729                         char* str = sub->getStr();
00730                         if (strncmp(str, "%SKIP", 5) == 0) {
00731                             toBranches(addr, lastRtl, cfg, rtl, bb, it);
00732                             noinc = true;       // toBranches inc's it
00733                             // Abandon this BB; if there are other string instr this BB, they will appear in new BBs
00734                             // near the end of the list
00735                             break;
00736                         }
00737                         else
00738                             LOG << "Unhandled machine feature " << str << "\n";
00739                     }
00740                 }
00741             }
00742             lastRtl = false;
00743         }
00744         if (!noinc) it++;
00745     }
00746 }
00747 
00748 void PentiumFrontEnd::processOverlapped(UserProc* proc) {
00749 
00750     // first, lets look for any uses of the registers
00751     std::set<int> usedRegs;
00752     StatementList stmts;
00753     proc->getStatements(stmts);
00754     StatementList::iterator it;
00755     for (it = stmts.begin(); it != stmts.end(); it++) {
00756         Statement* s = *it;
00757         LocationSet locs;
00758         s->addUsedLocs(locs);
00759         for (LocationSet::iterator li = locs.begin(); li != locs.end(); li++) {
00760             Exp *l = *li;
00761             if (!l->isRegOfK())
00762                 continue;
00763             int n = ((Const*)l->getSubExp1())->getInt();
00764             usedRegs.insert(n);
00765         }
00766     }
00767 
00768     std::set<PBB> bbs;
00769 
00770     // For each statement, we are looking for assignments to registers in
00771     //   these ranges:
00772     // eax - ebx (24-27) (eax, ecx, edx, ebx)
00773     //  ax -  bx ( 0- 3) ( ax,  cx,  dx,  bx)
00774     //  al -  bl ( 8-11) ( al,  cl,  dl,  bl)
00775     //  ah -  bh (12-15) ( ah,  ch,  dh,  bh)
00776     // if found we want to generate assignments to the overlapping registers,
00777     // but only if they are used in this procedure.
00778     //
00779     // TMN: 2006-007-31. This code had been completely forgotten about:
00780     // esi/si, edi/di and ebp/bp. For now, let's hope we never encounter esp/sp. :-)
00781     // ebp (29)  bp (5)
00782     // esi (30)  si (6)
00783     // edi (31)  di (7)
00784     for (it = stmts.begin(); it != stmts.end(); it++) {
00785         Statement* s = *it;
00786         if (s->getBB()->overlappedRegProcessingDone)   // never redo processing
00787             continue;
00788         bbs.insert(s->getBB());
00789         if (!s->isAssignment()) continue;
00790         Exp* lhs = ((Assignment*)s)->getLeft();
00791         if (!lhs->isRegOf()) continue;
00792         Const* c = (Const*)((Location*)lhs)->getSubExp1();
00793         assert(c->isIntConst());
00794         int r = c->getInt();
00795         int off = r&3;        // Offset into the array of 4 registers
00796         int off_mod8 = r&7;   // Offset into the array of 8 registers; for ebp, esi, edi
00797         Assign* a;
00798         switch (r) {
00799             case 24: case 25: case 26: case 27:
00800             //  eax      ecx      edx      ebx
00801             // Emit *16* r<off> := trunc(32, 16, r<24+off>)
00802             if (usedRegs.find(off) != usedRegs.end()) {
00803                 a = new Assign(
00804                     new IntegerType(16),
00805                     Location::regOf(off),
00806                     new Ternary(opTruncu,
00807                         new Const(32),
00808                         new Const(16),
00809                         Location::regOf(24+off)));
00810                 proc->insertStatementAfter(s, a);
00811             }
00812 
00813             // Emit *8* r<8+off> := trunc(32, 8, r<24+off>)
00814             if (usedRegs.find(8+off) != usedRegs.end()) {
00815                 a = new Assign(
00816                     new IntegerType(8),
00817                     Location::regOf(8+off),
00818                     new Ternary(opTruncu,
00819                         new Const(32),
00820                         new Const(8),
00821                         Location::regOf(24+off)));
00822                 proc->insertStatementAfter(s, a);
00823             }
00824 
00825             // Emit *8* r<12+off> := r<24+off>@[15:8]
00826             if (usedRegs.find(12+off) != usedRegs.end()) {
00827                 a = new Assign(
00828                     new IntegerType(8),
00829                     Location::regOf(12+off),
00830                     new Ternary(opAt,
00831                         Location::regOf(24+off),
00832                         new Const(15),
00833                         new Const(8)));
00834                 proc->insertStatementAfter(s, a);
00835             }
00836             break;
00837 
00838             case 0: case 1: case 2: case 3:
00839             //  ax      cx      dx      bx
00840             // Emit *32* r<24+off> := r<24+off>@[31:16] | zfill(16, 32, r<off>)
00841             if (usedRegs.find(24+off) != usedRegs.end()) {
00842                 a = new Assign(
00843                     new IntegerType(32),
00844                     Location::regOf(24+off),
00845                     new Binary(opBitOr,
00846                         new Ternary(opAt,
00847                             Location::regOf(24+off),
00848                             new Const(31),
00849                             new Const(16)),
00850                         new Ternary(opZfill,
00851                             new Const(16),
00852                             new Const(32),
00853                             Location::regOf(off))));
00854                 proc->insertStatementAfter(s, a);
00855             }
00856             
00857             // Emit *8* r<8+off> := trunc(16, 8, r<off>)
00858             if (usedRegs.find(8+off) != usedRegs.end()) {
00859                 a = new Assign(
00860                     new IntegerType(8),
00861                     Location::regOf(8+off),
00862                     new Ternary(opTruncu,
00863                         new Const(16),
00864                         new Const(8),
00865                         Location::regOf(24+off)));
00866                 proc->insertStatementAfter(s, a);
00867             }
00868 
00869             // Emit *8* r<12+off> := r<off>@[15:8]
00870             if (usedRegs.find(12+off) != usedRegs.end()) {
00871                 a = new Assign(
00872                     new IntegerType(8),
00873                     Location::regOf(12+off),
00874                     new Ternary(opAt,
00875                         Location::regOf(off),
00876                         new Const(15),
00877                         new Const(8)));
00878                 proc->insertStatementAfter(s, a);
00879             }
00880             break;
00881 
00882 
00883             case 8: case 9: case 10: case 11:
00884             //  al      cl       dl       bl
00885             // Emit *32* r<24+off> := r<24+off>@[31:8] | zfill(8, 32, r<8+off>)
00886             if (usedRegs.find(24+off) != usedRegs.end()) {
00887                 a = new Assign(
00888                     new IntegerType(32),
00889                     Location::regOf(24+off),
00890                     new Binary(opBitOr,
00891                         new Ternary(opAt,
00892                             Location::regOf(24+off),
00893                             new Const(31),
00894                             new Const(8)),
00895                         new Ternary(opZfill,
00896                             new Const(8),
00897                             new Const(32),
00898                             Location::regOf(8+off))));
00899                 proc->insertStatementAfter(s, a);
00900             }
00901 
00902             // Emit *16* r<off> := r<off>@[15:8] | zfill(8, 16, r<8+off>)
00903             if (usedRegs.find(off) != usedRegs.end()) {
00904                 a = new Assign(
00905                     new IntegerType(16),
00906                     Location::regOf(off),
00907                     new Binary(opBitOr,
00908                         new Ternary(opAt,
00909                             Location::regOf(off),
00910                             new Const(15),
00911                             new Const(8)),
00912                         new Ternary(opZfill,
00913                             new Const(8),
00914                             new Const(16),
00915                             Location::regOf(8+off))));
00916                 proc->insertStatementAfter(s, a);
00917             }
00918             break;
00919 
00920             case 12: case 13: case 14: case 15:
00921             //   ah       ch       dh       bh
00922             // Emit *32* r<24+off> := r<24+off> & 0xFFFF00FF
00923             //      *32* r<24+off> := r<24+off> | r<12+off> << 8
00924             if (usedRegs.find(24+off) != usedRegs.end()) {
00925                 a = new Assign(
00926                     new IntegerType(32),
00927                     Location::regOf(24+off),
00928                     new Binary(opBitOr,
00929                         Location::regOf(24+off),
00930                         new Binary(opShiftL,
00931                             Location::regOf(12+off),
00932                             new Const(8))));
00933                 proc->insertStatementAfter(s, a);
00934                 a = new Assign(
00935                     new IntegerType(32),
00936                     Location::regOf(24+off),
00937                     new Binary(opBitAnd,
00938                         Location::regOf(24+off),
00939                         new Const(0xFFFF00FF)));
00940                 proc->insertStatementAfter(s, a);
00941             }
00942 
00943             // Emit *16* r<off> := r<off> & 0x00FF
00944             //      *16* r<off> := r<off> | r<12+off> << 8
00945             if (usedRegs.find(off) != usedRegs.end()) {
00946                 a = new Assign(
00947                     new IntegerType(16),
00948                     Location::regOf(off),
00949                     new Binary(opBitOr,
00950                         Location::regOf(off),
00951                         new Binary(opShiftL,
00952                             Location::regOf(12+off),
00953                             new Const(8))));
00954                 proc->insertStatementAfter(s, a);
00955                 a = new Assign(
00956                     new IntegerType(16),
00957                     Location::regOf(off),
00958                     new Binary(opBitAnd,
00959                         Location::regOf(off),
00960                         new Const(0x00FF)));
00961                 proc->insertStatementAfter(s, a);
00962             }
00963             break;
00964 
00965             case 5: case 6: case 7:
00966             //  bp      si      di
00967             // Emit *32* r<24+off_mod8> := r<24+off_mod8>@[31:16] | zfill(16, 32, r<off_mod8>)
00968             if (usedRegs.find(24+off_mod8) != usedRegs.end()) {
00969                 a = new Assign(
00970                     new IntegerType(32),
00971                     Location::regOf(24+off_mod8),
00972                     new Binary(opBitOr,
00973                         new Ternary(opAt,
00974                             Location::regOf(24+off_mod8),
00975                             new Const(31),
00976                             new Const(16)),
00977                         new Ternary(opZfill,
00978                             new Const(16),
00979                             new Const(32),
00980                             Location::regOf(off_mod8))));
00981                 proc->insertStatementAfter(s, a);
00982             }
00983             break;
00984 
00985             case 29: case 30: case 31:
00986             //  ebp      esi      edi
00987             // Emit *16* r<off_mod8> := trunc(32, 16, r<24+off_mod8>)
00988             if (usedRegs.find(off_mod8) != usedRegs.end()) {
00989                 a = new Assign(
00990                     new IntegerType(16),
00991                     Location::regOf(off_mod8),
00992                     new Ternary(opTruncu,
00993                         new Const(32),
00994                         new Const(16),
00995                         Location::regOf(24+off_mod8)));
00996                 proc->insertStatementAfter(s, a);
00997             }
00998             break;
00999         }
01000     }
01001 
01002     // set a flag for every BB we've processed so we don't do them again
01003     for (std::set<PBB>::iterator bit = bbs.begin(); bit != bbs.end(); bit++)
01004         (*bit)->overlappedRegProcessingDone = true;
01005 }
01006 
01007 DecodeResult& PentiumFrontEnd::decodeInstruction(ADDRESS pc)
01008 {
01009     int n = pBF->readNative1(pc);
01010     if (n == (int)(char)0xee) {
01011         // out dx, al
01012         static DecodeResult r;
01013         r.reset();
01014         r.numBytes = 1;
01015         r.valid = true;
01016         r.type = NCT;
01017         r.reDecode = false;
01018         r.rtl = new RTL(pc);
01019         Exp *dx = Location::regOf(decoder->getRTLDict().RegMap["%dx"]);
01020         Exp *al = Location::regOf(decoder->getRTLDict().RegMap["%al"]);
01021         CallStatement *call = new CallStatement();
01022         call->setDestProc(prog->getLibraryProc("outp"));
01023         call->setArgumentExp(0, dx);
01024         call->setArgumentExp(1, al);
01025         r.rtl->appendStmt(call);
01026         return r;
01027     }
01028     if (n == (int)(char)0x0f && pBF->readNative1(pc+1) == (int)(char)0x0b) {
01029         static DecodeResult r;
01030         r.reset();
01031         r.numBytes = 2;
01032         r.valid = true;
01033         r.type = NCT;
01034         r.reDecode = false;
01035         r.rtl = new RTL(pc);
01036         CallStatement *call = new CallStatement();
01037         call->setDestProc(prog->getLibraryProc("invalid_opcode"));
01038         r.rtl->appendStmt(call);
01039         return r;
01040     }
01041     return FrontEnd::decodeInstruction(pc);
01042 }
01043 
01044 // EXPERIMENTAL: can we find function pointers in arguments to calls this early?
01045 void PentiumFrontEnd::extraProcessCall(CallStatement *call, std::list<RTL*> *BB_rtls)
01046 {
01047     if (call->getDestProc()) {
01048 
01049         // looking for function pointers
01050         Signature *calledSig = call->getDestProc()->getSignature();
01051         for (unsigned int i = 0; i < calledSig->getNumParams(); i++) {
01052             // check param type
01053             Type *paramType = calledSig->getParamType(i);
01054             Type *points_to;
01055             CompoundType *compound = NULL;
01056             bool paramIsFuncPointer = false, paramIsCompoundWithFuncPointers = false;
01057             if (paramType->resolvesToPointer()) {
01058                 points_to = paramType->asPointer()->getPointsTo();
01059                 if (points_to->resolvesToFunc())
01060                     paramIsFuncPointer = true;
01061                 else if (points_to->resolvesToCompound()) {
01062                     compound = points_to->asCompound();
01063                     for (unsigned int n = 0; n < compound->getNumTypes(); n++) {
01064                         if (    compound->getType(n)->resolvesToPointer() &&
01065                                 compound->getType(n)->asPointer()->getPointsTo()->resolvesToFunc())
01066                             paramIsCompoundWithFuncPointers = true;
01067                     }
01068                 }
01069             }
01070             if (paramIsFuncPointer == false && paramIsCompoundWithFuncPointers == false)
01071                 continue;
01072 
01073             // count pushes backwards to find arg
01074             Exp *found = NULL;
01075             std::list<RTL*>::reverse_iterator itr;
01076             unsigned int pushcount = 0;
01077             for (itr = BB_rtls->rbegin(); itr != BB_rtls->rend() && !found; itr++) {
01078                 RTL *rtl = *itr;
01079                 for (int n = rtl->getNumStmt() - 1; n >= 0; n--) {
01080                     Statement *stmt = rtl->elementAt(n);
01081                     if (stmt->isAssign()) {
01082                         Assign *asgn = (Assign*)stmt;
01083                         if (asgn->getLeft()->isRegN(28) && asgn->getRight()->getOper() == opMinus)
01084                             pushcount++;
01085                         else if (pushcount == i + 2 && asgn->getLeft()->isMemOf() && 
01086                                  asgn->getLeft()->getSubExp1()->getOper() == opMinus &&
01087                                  asgn->getLeft()->getSubExp1()->getSubExp1()->isRegN(28) &&
01088                                  asgn->getLeft()->getSubExp1()->getSubExp2()->isIntConst()) {
01089                             found = asgn->getRight();
01090                             break;
01091                         }
01092                     }
01093                 }
01094             }
01095             if (found == NULL)
01096                 continue;
01097 
01098             ADDRESS a;
01099             if (found->isIntConst())
01100                 a = ((Const*)found)->getInt();
01101             else if (found->isAddrOf() && found->getSubExp1()->isGlobal()) {
01102                 const char *name = ((Const*)found->getSubExp1()->getSubExp1())->getStr();
01103                 if (prog->getGlobal((char*)name) == NULL)
01104                     continue;
01105                 a = prog->getGlobalAddr((char*)name);
01106             } else
01107                 continue;
01108 
01109             // found one.
01110             if (paramIsFuncPointer) {
01111                 if (VERBOSE)
01112                     LOG << "found a new procedure at address " << a << " from inspecting parameters of call to " <<
01113                         call->getDestProc()->getName() << ".\n";
01114                 Proc *proc = prog->setNewProc(a);
01115                 Signature *sig = paramType->asPointer()->getPointsTo()->asFunc()->getSignature()->clone();
01116                 sig->setName(proc->getName());
01117                 sig->setForced(true);
01118                 proc->setSignature(sig);
01119                 continue;
01120             }
01121 
01122             // linkers putting rodata in data sections is a continual annoyance
01123             // we just have to assume the pointers don't change before we pass them at least once.
01124             //if (!prog->isReadOnly(a))             
01125             //  continue;
01126 
01127             for (unsigned int n = 0; n < compound->getNumTypes(); n++) {
01128                 if (compound->getType(n)->resolvesToPointer() &&
01129                         compound->getType(n)->asPointer()->getPointsTo()->resolvesToFunc()) {
01130                     ADDRESS d = pBF->readNative4(a);
01131                     if (VERBOSE)
01132                         LOG << "found a new procedure at address " << d << " from inspecting parameters of call to " << 
01133                             call->getDestProc()->getName() << ".\n";
01134                     Proc *proc = prog->setNewProc(d);
01135                     Signature *sig = compound->getType(n)->asPointer()->getPointsTo()->asFunc()->getSignature()->
01136                         clone();
01137                     sig->setName(proc->getName());
01138                     sig->setForced(true);
01139                     proc->setSignature(sig);
01140                 }
01141                 a += compound->getType(n)->getSize() / 8;
01142             }                               
01143         }
01144 
01145         // some pentium specific ellipsis processing
01146         if (calledSig->hasEllipsis()) {
01147             // count pushes backwards to find a push of 0
01148             bool found = false;
01149             std::list<RTL*>::reverse_iterator itr;
01150             int pushcount = 0;
01151             for (itr = BB_rtls->rbegin(); itr != BB_rtls->rend() && !found; itr++) {
01152                 RTL *rtl = *itr;
01153                 for (int n = rtl->getNumStmt() - 1; n >= 0; n--) {
01154                     Statement *stmt = rtl->elementAt(n);
01155                     if (stmt->isAssign()) {
01156                         Assign *asgn = (Assign*)stmt;
01157                         if (asgn->getLeft()->isRegN(28) && asgn->getRight()->getOper() == opMinus)
01158                             pushcount++;
01159                         else if (asgn->getLeft()->isMemOf() && 
01160                                  asgn->getLeft()->getSubExp1()->getOper() == opMinus &&
01161                                  asgn->getLeft()->getSubExp1()->getSubExp1()->isRegN(28) &&
01162                                  asgn->getLeft()->getSubExp1()->getSubExp2()->isIntConst()) {
01163                             if (asgn->getRight()->isIntConst()) { 
01164                                 int n = ((Const*)asgn->getRight())->getInt();
01165                                 if (n == 0) {
01166                                     found = true;
01167                                     break;
01168                                 }
01169                             }
01170                         }
01171                     }
01172                 }
01173             }
01174             if (found && pushcount > 1) {
01175                 call->setSigArguments();
01176                 call->setNumArguments(pushcount - 1);
01177             }
01178         }
01179     }
01180 }

Generated on Tue Sep 19 21:18:29 2006 for Boomerang by  doxygen 1.4.6