00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 #include <assert.h>
00030 #if defined(_MSC_VER) && _MSC_VER <= 1200
00031 #pragma warning(disable:4786)
00032 #endif
00033 
00034 #include "frontend.h"
00035 #include <queue>
00036 #include <stdarg.h>         
00037 #include <sstream>
00038 #ifndef _WIN32
00039 #include <dlfcn.h>          
00040 #endif
00041 
00042 #include "types.h"
00043 #include "exp.h"
00044 #include "cfg.h"
00045 #include "proc.h"
00046 #include "register.h"
00047 #include "rtl.h"
00048 #include "BinaryFile.h"
00049 #include "decoder.h"
00050 #include "sparcfrontend.h"
00051 #include "pentiumfrontend.h"
00052 #include "ppcfrontend.h"
00053 #include "st20frontend.h"
00054 #include "prog.h"
00055 #include "signature.h"
00056 #include "boomerang.h"
00057 #include "log.h"
00058 #include "ansi-c-parser.h"
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 FrontEnd::FrontEnd(BinaryFile *pBF, Prog* prog, BinaryFileFactory* pbff) : pBF(pBF), pbff(pbff), prog(prog)
00069 {}
00070 
00071 
00072 FrontEnd* FrontEnd::instantiate(BinaryFile *pBF, Prog* prog, BinaryFileFactory* pbff) {
00073     switch(pBF->GetMachine()) {
00074         case MACHINE_PENTIUM:
00075             return new PentiumFrontEnd(pBF, prog, pbff);
00076         case MACHINE_SPARC:
00077             return new SparcFrontEnd(pBF, prog, pbff);
00078         case MACHINE_PPC:
00079             return new PPCFrontEnd(pBF, prog, pbff);
00080         case MACHINE_ST20:
00081             return new ST20FrontEnd(pBF, prog, pbff);
00082         default:
00083             std::cerr << "Machine architecture not supported!\n";
00084     }
00085     return NULL;
00086 }
00087 
00088 FrontEnd* FrontEnd::Load(const char *fname, Prog* prog) {
00089     BinaryFileFactory* pbff = new BinaryFileFactory;
00090     if (pbff == NULL) return NULL;
00091     BinaryFile *pBF = pbff->Load(fname);
00092     if (pBF == NULL) return NULL;
00093     return instantiate(pBF, prog, pbff);
00094 }
00095 
00096 
00097 FrontEnd::~FrontEnd() {
00098     if (pbff)
00099         pbff->UnLoad();         
00100 }
00101 
00102 const char *FrontEnd::getRegName(int idx) { 
00103     std::map<std::string, int, std::less<std::string> >::iterator it;
00104     for (it = decoder->getRTLDict().RegMap.begin();  it != decoder->getRTLDict().RegMap.end(); it++)
00105         if ((*it).second == idx) 
00106             return (*it).first.c_str();
00107     return NULL;
00108 }
00109 
00110 int FrontEnd::getRegSize(int idx) {
00111     if (decoder->getRTLDict().DetRegMap.find(idx) == decoder->getRTLDict().DetRegMap.end())
00112         return 32;
00113     return decoder->getRTLDict().DetRegMap[idx].g_size();
00114 }
00115 
00116 bool FrontEnd::isWin32() {
00117     return pBF->GetFormat() == LOADFMT_PE;
00118 }
00119 
00120 bool FrontEnd::noReturnCallDest(const char *name)
00121 {
00122     return ((strcmp(name, "_exit") == 0) || (strcmp(name,   "exit") == 0) || (strcmp(name, "ExitProcess") == 0) || (strcmp(name, "abort") == 0) || (strcmp(name, "_assert") == 0));
00123 }
00124 
00125 
00126 FrontEnd *FrontEnd::createById(std::string &str, BinaryFile *pBF, Prog* prog) {
00127     if (str == "pentium")
00128         return new PentiumFrontEnd(pBF, prog, NULL);
00129     if (str == "sparc")
00130         return new SparcFrontEnd(pBF, prog, NULL);
00131     if (str == "ppc")
00132         return new PPCFrontEnd(pBF, prog, NULL);
00133     if (str == "st20")
00134         return new ST20FrontEnd(pBF, prog, NULL);
00135     return NULL;
00136 }
00137 
00138 void FrontEnd::readLibraryCatalog(const char *sPath) {
00139     std::ifstream inf(sPath);
00140     if (!inf.good()) {
00141         std::cerr << "can't open `" << sPath << "'\n";
00142         exit(1);
00143     }
00144 
00145     while (!inf.eof()) {
00146         std::string sFile;
00147         inf >> sFile;
00148         size_t j = sFile.find('#');
00149         if (j != (size_t)-1)
00150             sFile = sFile.substr(0, j);
00151         if (sFile.size() > 0 && sFile[sFile.size()-1] == '\n')
00152             sFile = sFile.substr(0, sFile.size()-1);
00153         if (sFile == "") continue;
00154         std::string sPath = Boomerang::get()->getProgPath() + "signatures/" + sFile;
00155         callconv cc = CONV_C;           
00156         if (sFile == "windows.h")   cc = CONV_PASCAL;       
00157         if (sFile == "mfc.h")       cc = CONV_THISCALL;     
00158         readLibrarySignatures(sPath.c_str(), cc);
00159     }
00160     inf.close();
00161 }
00162 
00163 void FrontEnd::readLibraryCatalog() {
00164     librarySignatures.clear();
00165     std::string sList = Boomerang::get()->getProgPath() + "signatures/common.hs";
00166 
00167     readLibraryCatalog(sList.c_str());
00168     sList = Boomerang::get()->getProgPath() + "signatures/" + Signature::platformName(getFrontEndId()) + ".hs";
00169     readLibraryCatalog(sList.c_str());
00170     if (isWin32()) {
00171         sList = Boomerang::get()->getProgPath() + "signatures/win32.hs";
00172         readLibraryCatalog(sList.c_str());
00173     }
00174 }
00175 
00176 std::vector<ADDRESS> FrontEnd::getEntryPoints()
00177 {
00178     std::vector<ADDRESS> entrypoints;
00179     bool gotMain = false;
00180     ADDRESS a = getMainEntryPoint(gotMain);
00181     if (a != NO_ADDRESS)
00182         entrypoints.push_back(a);
00183     else {  
00184         const char *fname = pBF->getFilename();
00185         
00186         if (!strcmp(fname + strlen(fname) - 6, "_drv.o")) {
00187             const char *p = fname + strlen(fname) - 6;
00188             while (*p != '/' && *p != '\\' && p != fname)
00189                 p--;
00190             if (p != fname) {
00191                 p++;
00192                 char *name = (char*)malloc(strlen(p) + 30);
00193                 strcpy(name, p);
00194                 name[strlen(name)-6] = 0;
00195                 strcat(name, "ModuleData");
00196                 ADDRESS a = pBF->GetAddressByName(name, true);
00197                 if (a != NO_ADDRESS) {
00198                     ADDRESS vers, setup, teardown;
00199                     vers = pBF->readNative4(a);
00200                     setup = pBF->readNative4(a+4);
00201                     teardown = pBF->readNative4(a+8);
00202                     if (setup) {
00203                         Type *ty = NamedType::getNamedType("ModuleSetupProc");
00204                         assert(ty->isFunc());
00205                         UserProc *proc = (UserProc*)prog->setNewProc(setup);
00206                         assert(proc);
00207                         Signature *sig = ty->asFunc()->getSignature()->clone();
00208                         const char *sym = pBF->SymbolByAddress(setup);
00209                         if (sym)
00210                             sig->setName(sym);
00211                         sig->setForced(true);
00212                         proc->setSignature(sig);
00213                         entrypoints.push_back(setup);
00214                     }
00215                     if (teardown) {
00216                         Type *ty = NamedType::getNamedType("ModuleTearDownProc");
00217                         assert(ty->isFunc());
00218                         UserProc *proc = (UserProc*)prog->setNewProc(teardown);
00219                         assert(proc);
00220                         Signature *sig = ty->asFunc()->getSignature()->clone();
00221                         const char *sym = pBF->SymbolByAddress(teardown);
00222                         if (sym)
00223                             sig->setName(sym);
00224                         sig->setForced(true);
00225                         proc->setSignature(sig);                        
00226                         entrypoints.push_back(teardown);
00227                     }
00228                 }
00229             }
00230         }
00231         
00232         if (!strcmp(fname + strlen(fname) - 3, ".ko")) {
00233             a = pBF->GetAddressByName("init_module");
00234             if (a != NO_ADDRESS)
00235                 entrypoints.push_back(a);
00236             a = pBF->GetAddressByName("cleanup_module");
00237             if (a != NO_ADDRESS)
00238                 entrypoints.push_back(a);
00239         }
00240     }
00241     return entrypoints;
00242 }
00243 
00244 void FrontEnd::decode(Prog* prog, bool decodeMain, const char *pname) {
00245     if (pname)
00246         prog->setName(pname);
00247 
00248     if (!decodeMain)
00249         return;
00250     
00251     Boomerang::get()->alert_start_decode(pBF->getLimitTextLow(), pBF->getLimitTextHigh() - pBF->getLimitTextLow());
00252 
00253     bool gotMain;
00254     ADDRESS a = getMainEntryPoint(gotMain);
00255     if (VERBOSE)
00256         LOG << "start: " << a << " gotmain: " << (gotMain ? "true" : "false") << "\n";
00257     if (a == NO_ADDRESS) {
00258         std::vector<ADDRESS> entrypoints = getEntryPoints();
00259         for (std::vector<ADDRESS>::iterator it = entrypoints.begin(); it != entrypoints.end(); it++)
00260             decode(prog, *it);
00261         return;
00262     }
00263 
00264     decode(prog, a);
00265     prog->setEntryPoint(a);
00266 
00267     if (gotMain) {
00268         static const char *mainName[] = { "main", "WinMain", "DriverEntry" };
00269         const char *name = pBF->SymbolByAddress(a);
00270         if (name == NULL)
00271             name = mainName[0];
00272         for (size_t i = 0; i < sizeof(mainName)/sizeof(char*); i++) {
00273             if (!strcmp(name, mainName[i])) {
00274                 Proc *proc = prog->findProc(a);
00275                 if (proc == NULL) {
00276                     if (VERBOSE)
00277                         LOG << "no proc found for address " << a << "\n";
00278                     return;
00279                 }
00280                 FuncType *fty = dynamic_cast<FuncType*>(Type::getNamedType(name));
00281                 if (fty == NULL)
00282                     LOG << "unable to find signature for known entrypoint " << name << "\n";
00283                 else {
00284                     proc->setSignature(fty->getSignature()->clone());
00285                     proc->getSignature()->setName(name);
00286                     
00287                     proc->getSignature()->setForced(true);          
00288                 }
00289                 break;
00290             }
00291         }
00292     }
00293     return;
00294 }
00295 
00296 
00297 void FrontEnd::decode(Prog *prog, ADDRESS a) {
00298     if (a != NO_ADDRESS) {
00299         prog->setNewProc(a);
00300         if (VERBOSE)
00301             LOG << "starting decode at address " << a << "\n";
00302         UserProc* p = (UserProc*)prog->findProc(a);
00303         if (p == NULL) {
00304             if (VERBOSE)
00305                 LOG << "no proc found at address " << a << "\n";
00306             return;
00307         }
00308         if (p->isLib()) {
00309             LOG << "NOT decoding library proc at address 0x" << a << "\n";
00310             return;
00311         }
00312         std::ofstream os;
00313         processProc(a, p, os);
00314         p->setDecoded();
00315 
00316     } else {                        
00317         bool change = true;
00318         while (change) {
00319             change = false;
00320             PROGMAP::const_iterator it;
00321             for (Proc *pProc = prog->getFirstProc(it); pProc != NULL; pProc = prog->getNextProc(it)) {
00322                 if (pProc->isLib()) continue;
00323                 UserProc *p = (UserProc*)pProc;
00324                 if (p->isDecoded()) continue;
00325 
00326                 
00327                 change = true;
00328                 std::ofstream os;
00329                 int res = processProc(p->getNativeAddress(), p, os);
00330                 if (res == 1)
00331                     p->setDecoded();
00332                 else
00333                     break;
00334                 
00335                 if (Boomerang::get()->noDecodeChildren)
00336                     break;
00337             }
00338             if (Boomerang::get()->noDecodeChildren)
00339                 break;
00340         }
00341     }
00342     prog->wellForm();
00343 }
00344 
00345 
00346 void FrontEnd::decodeOnly(Prog *prog, ADDRESS a) {
00347     UserProc* p = (UserProc*)prog->setNewProc(a);
00348     assert(!p->isLib());
00349     std::ofstream os;
00350     if (processProc(p->getNativeAddress(), p, os))
00351         p->setDecoded();
00352     prog->wellForm();
00353 }
00354 
00355 
00356 void FrontEnd::decodeFragment(UserProc* proc, ADDRESS a) {
00357     if (Boomerang::get()->traceDecoder)
00358         LOG << "decoding fragment at 0x" << a << "\n";
00359     std::ofstream os;
00360     processProc(a, proc, os, true);
00361 }
00362 
00363 DecodeResult& FrontEnd::decodeInstruction(ADDRESS pc) {
00364     if (pBF->GetSectionInfoByAddr(pc) == NULL) {
00365         LOG << "ERROR: attempted to decode outside any known segment " << pc << "\n";
00366         static DecodeResult invalid;
00367         invalid.reset();
00368         invalid.valid = false;
00369         return invalid;
00370     }
00371     return decoder->decodeInstruction(pc, pBF->getTextDelta());
00372 }
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 void FrontEnd::readLibrarySignatures(const char *sPath, callconv cc) {
00382     std::ifstream ifs;
00383 
00384     ifs.open(sPath);
00385 
00386     if (!ifs.good()) {
00387         std::cerr << "can't open `" << sPath << "'\n";
00388         exit(1);
00389     }
00390 
00391     AnsiCParser *p = new AnsiCParser(ifs, false);
00392     
00393     platform plat = getFrontEndId();
00394     p->yyparse(plat, cc);
00395 
00396     for (std::list<Signature*>::iterator it = p->signatures.begin(); it != p->signatures.end(); it++) {
00397 #if 0
00398         std::cerr << "readLibrarySignatures from " << sPath << ": " << (*it)->getName() << "\n";
00399 #endif
00400         librarySignatures[(*it)->getName()] = *it;
00401         (*it)->setSigFile(sPath);
00402     }
00403 
00404     delete p;
00405     ifs.close();
00406 }
00407 
00408 Signature *FrontEnd::getDefaultSignature(const char *name)
00409 {
00410     Signature *signature = NULL;
00411     
00412     if (isWin32())
00413         signature = Signature::instantiate(PLAT_PENTIUM, CONV_PASCAL, name);
00414     else {
00415         signature = Signature::instantiate(getFrontEndId(), CONV_C, name);
00416     } 
00417     return signature;
00418 }
00419 
00420 
00421 Signature *FrontEnd::getLibSignature(const char *name) {
00422     Signature *signature;
00423     
00424     std::map<std::string, Signature*>::iterator it;
00425     it = librarySignatures.find(name);
00426     if (it == librarySignatures.end()) {
00427         LOG << "Unknown library function " << name << "\n";
00428         signature = getDefaultSignature(name);
00429     }
00430     else {
00431         
00432         signature = (*it).second;
00433         signature->setUnknown(false);
00434     }
00435     return signature;
00436 }
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 bool FrontEnd::processProc(ADDRESS uAddr, UserProc* pProc, std::ofstream &os, bool frag ,
00451         bool spec ) {
00452     PBB pBB;                    
00453 
00454     
00455     Boomerang::get()->alert_new(pProc);
00456 
00457     
00458     
00459     
00460     std::list<CallStatement*> callList;
00461 
00462     
00463     
00464     bool sequentialDecode = true;
00465 
00466     Cfg* pCfg = pProc->getCFG();
00467 
00468     
00469     if (spec && (pCfg == 0))
00470         return false;
00471     assert(pCfg);
00472 
00473     
00474     targetQueue.initial(uAddr);
00475 
00476     
00477     
00478 
00479     
00480     int nTotalBytes = 0;
00481     ADDRESS startAddr = uAddr;
00482     ADDRESS lastAddr = uAddr;
00483 
00484     while ((uAddr = targetQueue.nextAddress(pCfg)) != NO_ADDRESS) {
00485         
00486         std::list<RTL*>* BB_rtls = new std::list<RTL*>();
00487 
00488         
00489         
00490         DecodeResult inst;
00491         while (sequentialDecode) {
00492 
00493             
00494             if (Boomerang::get()->traceDecoder)
00495                 LOG << "*" << uAddr << "\t";
00496 
00497             
00498             inst = decodeInstruction(uAddr);
00499 
00500             
00501             if (spec && !inst.valid)
00502                 return false;
00503 
00504             
00505             
00506             if (BB_rtls == NULL)
00507                 BB_rtls = new std::list<RTL*>();
00508 
00509             RTL* pRtl = inst.rtl;
00510             if (inst.valid == false) {
00511                 
00512                 Boomerang::get()->alert_baddecode(uAddr);
00513 
00514                 
00515                 
00516                 if (VERBOSE) {
00517                     LOG << "Warning: invalid instruction at " << uAddr << ": ";
00518                     
00519                     for (int ii=0; ii < 4; ii++)
00520                         LOG << (unsigned)(pBF->readNative1(uAddr + ii) & 0xFF) << " ";
00521                     LOG << "\n";
00522                 }
00523                 
00524                 BB_rtls->push_back(new RTL(uAddr));  
00525                 pBB = pCfg->newBB(BB_rtls, INVALID, 0);
00526                 sequentialDecode = false; BB_rtls = NULL; continue;
00527             }
00528 
00529             
00530             Boomerang::get()->alert_decode(uAddr, inst.numBytes);
00531             nTotalBytes += inst.numBytes;           
00532     
00533             
00534             
00535             
00536             std::map<ADDRESS, RTL*>::iterator ff = previouslyDecoded.find(uAddr);
00537             if (ff != previouslyDecoded.end())
00538                 pRtl = ff->second;
00539 
00540             if (pRtl == NULL) {
00541                 
00542                 
00543                 if (inst.numBytes > 0)
00544                     uAddr += inst.numBytes;
00545                 continue;
00546             }
00547 
00548             
00549             if (Boomerang::get()->printRtl) {
00550                 std::ostringstream st;
00551                 pRtl->print(st);
00552                 LOG << st.str().c_str();
00553             }
00554     
00555             ADDRESS uDest;
00556 
00557             
00558             
00559             std::list<Statement*> sl = pRtl->getList();
00560             
00561             
00562             
00563             
00564             
00565             
00566             
00567             
00568             std::list<Statement*>::iterator ss;
00569 #if 1
00570             for (ss = sl.begin(); ss != sl.end(); ss++) { 
00571 #else
00572             
00573             
00574             int counter = sl.size();
00575             for (ss = sl.begin(); counter > 0; ss++, counter--) {
00576 #endif
00577                 Statement* s = *ss;
00578                 s->setProc(pProc);      
00579                 if (refHints.find(pRtl->getAddress()) != refHints.end()) {
00580                     const char *nam = refHints[pRtl->getAddress()].c_str();
00581                     ADDRESS gu = prog->getGlobalAddr((char*)nam);
00582                     if (gu != NO_ADDRESS) {
00583                         s->searchAndReplace(new Const((int)gu), new Unary(opAddrOf, Location::global(nam, pProc)));
00584                     }
00585                 }
00586                 s->simplify();
00587                 GotoStatement* stmt_jump = static_cast<GotoStatement*>(s);
00588 
00589                 
00590                 
00591                 ADDRESS dest;
00592                 Proc* proc;
00593                 if (s->getKind() == STMT_GOTO) {
00594                     dest = stmt_jump->getFixedDest();
00595                     if (dest != NO_ADDRESS) {
00596                         proc = prog->findProc(dest);
00597                         if (proc == NULL) {
00598                             if (pBF->IsDynamicLinkedProc(dest))
00599                                 proc = prog->setNewProc(dest);
00600                         }
00601                         if (proc != NULL && proc != (Proc*)-1) {
00602                             s = new CallStatement();
00603                             CallStatement *call = static_cast<CallStatement*>(s);
00604                             call->setDest(dest);
00605                             call->setDestProc(proc);
00606                             call->setReturnAfterCall(true);
00607                             
00608                             std::list<Statement*>::iterator ss1 = ss;
00609                             ss1++;
00610                             assert(ss1 == sl.end());
00611                             pRtl->replaceLastStmt(s);
00612                             *ss = s;
00613                         }
00614                     }
00615                 }
00616 
00617                 switch (s->getKind())
00618                 {
00619 
00620                 case STMT_GOTO: {
00621                     uDest = stmt_jump->getFixedDest();
00622     
00623                     
00624                     if (uDest != NO_ADDRESS) {
00625 
00626                         BB_rtls->push_back(pRtl);
00627                         sequentialDecode = false;
00628 
00629                         pBB = pCfg->newBB(BB_rtls,ONEWAY,1);
00630                         BB_rtls = NULL;     
00631 
00632                         
00633                         if (pBB == 0) {
00634                             break;
00635                         }
00636 
00637                         
00638                         
00639                         if (uDest < pBF->getLimitTextHigh()) {
00640                             targetQueue.visit(pCfg, uDest, pBB);
00641                             pCfg->addOutEdge(pBB, uDest, true);
00642                         }
00643                         else {
00644                             LOG << "Error: Instruction at " << uAddr << " branches beyond end of section, to "
00645                                 << uDest << "\n";
00646                         }
00647                     }
00648                     break;
00649                 }
00650 
00651                 case STMT_CASE: {
00652                     Exp* pDest = stmt_jump->getDest();
00653                     if (pDest == NULL) {                
00654                         
00655                         BB_rtls->push_back(pRtl);
00656                         pBB = pCfg->newBB(BB_rtls, NWAY, 0);    
00657                         pBB->processSwitch(pProc);      
00658                         sequentialDecode = false;       
00659                         BB_rtls = NULL;                 
00660                         break;                          
00661                     }
00662                     
00663                     if (pDest && pDest->getOper() == opMemOf &&
00664                             pDest->getSubExp1()->getOper() == opIntConst && 
00665                             pBF->IsDynamicLinkedProcPointer(((Const*)pDest->getSubExp1())->getAddr())) {
00666                         if (VERBOSE)
00667                             LOG << "jump to a library function: " << stmt_jump << ", replacing with a call/ret.\n";
00668                         
00669                         
00670                         std::string func = pBF->GetDynamicProcName(
00671                             ((Const*)stmt_jump->getDest()->getSubExp1())->getAddr());
00672                         CallStatement *call = new CallStatement;
00673                         call->setDest(stmt_jump->getDest()->clone());
00674                         LibProc *lp = pProc->getProg()->getLibraryProc(func.c_str());
00675                         if (lp == NULL)
00676                             LOG << "getLibraryProc returned NULL, aborting\n";
00677                         assert(lp);
00678                         call->setDestProc(lp);
00679                         std::list<Statement*>* stmt_list = new std::list<Statement*>;
00680                         stmt_list->push_back(call);
00681                         BB_rtls->push_back(new RTL(pRtl->getAddress(), stmt_list));
00682                         pBB = pCfg->newBB(BB_rtls, CALL, 1);
00683                         appendSyntheticReturn(pBB, pProc, pRtl);
00684                         sequentialDecode = false;
00685                         BB_rtls = NULL;
00686                         if (pRtl->getAddress() == pProc->getNativeAddress()) {
00687                             
00688                             
00689                             func = std::string("__imp_") + func;
00690                             pProc->setName(func.c_str());
00691                             
00692                             Boomerang::get()->alert_update_signature(pProc);
00693                         }
00694                         callList.push_back(call);
00695                         ss = sl.end(); ss--;    
00696                         break;
00697                     }
00698                     BB_rtls->push_back(pRtl);
00699                     
00700                     pBB = pCfg->newBB(BB_rtls, COMPJUMP, 0);
00701                     LOG << "COMPUTED JUMP at " << uAddr << ", pDest = " << pDest << "\n";
00702                     if (Boomerang::get()->noDecompile) {
00703                         
00704                         if (pDest->isMemOf() && pDest->getSubExp1()->getOper() == opPlus &&
00705                                 pDest->getSubExp1()->getSubExp2()->isIntConst()) {
00706                             
00707                             ADDRESS jmptbl = ((Const*)pDest->getSubExp1()->getSubExp2())->getInt();
00708                             unsigned int i;
00709                             for (i = 0; ; i++) {
00710                                 ADDRESS uDest = pBF->readNative4(jmptbl + i * 4);
00711                                 if (pBF->getLimitTextLow() <= uDest && uDest < pBF->getLimitTextHigh()) {
00712                                     LOG << "  guessed uDest " << uDest << "\n";
00713                                     targetQueue.visit(pCfg, uDest, pBB);
00714                                     pCfg->addOutEdge(pBB, uDest, true);
00715                                 } else
00716                                     break;
00717                             }
00718                             pBB->updateType(NWAY, i);
00719                         }
00720                     }
00721                     sequentialDecode = false;
00722                     BB_rtls = NULL;     
00723                     break;
00724                 }
00725 
00726 
00727                 case STMT_BRANCH: {
00728                     uDest = stmt_jump->getFixedDest();
00729                     BB_rtls->push_back(pRtl);
00730                     pBB = pCfg->newBB(BB_rtls, TWOWAY, 2);
00731 
00732                     
00733                     if (pBB == 0)
00734                         sequentialDecode = false;
00735                     else {
00736 
00737                         
00738                         if (uDest < pBF->getLimitTextHigh()) {
00739                             targetQueue.visit(pCfg, uDest, pBB);
00740                             pCfg->addOutEdge(pBB, uDest, true);
00741                         }
00742                         else {
00743                             LOG << "Error: Instruction at " << uAddr << " branches beyond end of section, to "
00744                                 << uDest << "\n";
00745                         }
00746 
00747                         
00748                         pCfg->addOutEdge(pBB, uAddr + inst.numBytes); 
00749                     }
00750 
00751                     
00752                     BB_rtls = NULL;
00753                     break;
00754                 }
00755 
00756                 case STMT_CALL: {
00757                     CallStatement* call = static_cast<CallStatement*>(s);
00758                     
00759                     
00760                     if (call->getDest()->getOper() == opMemOf &&
00761                             call->getDest()->getSubExp1()->getOper() == opIntConst &&
00762                             pBF->IsDynamicLinkedProcPointer(((Const*)call->getDest()->getSubExp1())->getAddr())) {
00763                         
00764                         const char *nam = pBF->GetDynamicProcName( ((Const*)call->getDest()->getSubExp1())->getAddr());
00765                         Proc *p = pProc->getProg()->getLibraryProc(nam);
00766                         call->setDestProc(p);
00767                         call->setIsComputed(false);
00768                     }
00769 
00770                     
00771                     
00772                     if( call && call->getFixedDest() != NO_ADDRESS ) {
00773                         
00774                         ADDRESS callAddr=call->getFixedDest();
00775                         
00776                         if (callAddr < pBF->getLimitTextHigh()) {
00777                             
00778                             DecodeResult decoded=decodeInstruction(callAddr);
00779                             if (decoded.valid) { 
00780                                 
00781                                 RTL *rtl = decoded.rtl;
00782                                 Statement* first_statement = *rtl->getList().begin();
00783                                 if (first_statement) {
00784                                     first_statement->setProc(pProc);
00785                                     first_statement->simplify();
00786                                     GotoStatement* stmt_jump = static_cast<GotoStatement*>(first_statement);
00787                                     
00788                                     
00789                                     if ( first_statement->getKind() == STMT_CASE &&
00790                                         stmt_jump->getDest()->getOper() == opMemOf &&
00791                                         stmt_jump->getDest()->getSubExp1()->getOper() == opIntConst &&
00792                                         pBF->IsDynamicLinkedProcPointer(((Const*)stmt_jump->getDest()->getSubExp1())->
00793                                             getAddr())) 
00794                                     {
00795                                         
00796                                         ADDRESS a = ((Const*)stmt_jump->getDest()->getSubExp1())->getAddr();
00797                                         const char *nam = pBF->GetDynamicProcName(a);
00798                                         
00799                                         Proc *p = pProc->getProg()->getLibraryProc(nam);
00800                                         if (call->getDestProc()) {
00801                                             
00802                                             prog->removeProc(call->getDestProc()->getName());
00803                                         }
00804                                         call->setDestProc(p);
00805                                         call->setIsComputed(false);
00806                                         call->setDest(Location::memOf(new Const(a)));
00807                                     }
00808                                 }
00809                             }
00810                         }
00811                     }
00812 
00813                     
00814                     if (call->isComputed()) {
00815                         BB_rtls->push_back(pRtl);
00816                         pBB = pCfg->newBB(BB_rtls, COMPCALL, 1);
00817 
00818                         
00819                         
00820                         if (pBB == 0)
00821                             sequentialDecode = false;
00822                         else
00823                             pCfg->addOutEdge(pBB, uAddr + inst.numBytes);
00824                         
00825                         
00826                         callList.push_back(call);
00827                     }
00828                     else {      
00829                         
00830                         ADDRESS uNewAddr = call->getFixedDest();
00831 
00832                         
00833                         
00834                         if (uNewAddr == uAddr + inst.numBytes)
00835                             break;
00836 
00837                         
00838                         
00839                         if (helperFunc(uNewAddr, uAddr, BB_rtls)) {
00840                             
00841                             pRtl = NULL;        
00842                             break;
00843                         }
00844 
00845                         BB_rtls->push_back(pRtl);
00846 
00847                         
00848                         
00849                         callList.push_back(call);
00850 
00851                         
00852                         if (uNewAddr && uNewAddr != NO_ADDRESS && pProc->getProg()->findProc(uNewAddr) == NULL) {
00853                             callList.push_back(call);
00854                             
00855                             if (Boomerang::get()->traceDecoder)
00856                                 LOG << "p" << uNewAddr << "\t";
00857                         }
00858 
00859                         
00860                         
00861                         const char* name = pBF->SymbolByAddress(uNewAddr);
00862                         if (name == NULL && call->getDest()->isMemOf() && 
00863                                             call->getDest()->getSubExp1()->isIntConst()) {
00864                             ADDRESS a = ((Const*)call->getDest()->getSubExp1())->getInt();
00865                             if (pBF->IsDynamicLinkedProcPointer(a))
00866                                 name = pBF->GetDynamicProcName(a);
00867                         }   
00868                         if (name && noReturnCallDest(name)) {
00869                             
00870                             
00871                             
00872                             pBB = pCfg->newBB(BB_rtls, CALL, 1);
00873                             appendSyntheticReturn(pBB, pProc, pRtl);
00874 
00875                             
00876                             sequentialDecode = false;
00877                         }
00878                         else {
00879                             
00880                             pBB = pCfg->newBB(BB_rtls, CALL, 1);
00881 
00882                             if (call->isReturnAfterCall()) {
00883                                 
00884                                 std::list<RTL*>* rtls = new std::list<RTL*>();
00885                                 
00886                                 std::list<Statement*>* sl = new std::list<Statement*>;
00887                                 sl->push_back(new ReturnStatement());
00888                                 rtls->push_back(new RTL(pRtl->getAddress()+1, sl));
00889         
00890                                 BasicBlock* returnBB = pCfg->newBB(rtls, RET, 0);
00891                                 
00892                                 pCfg->addOutEdge(pBB, returnBB);
00893                                 
00894                                 pCfg->setLabel(returnBB);
00895                                 pBB->setJumpReqd();
00896                                 
00897                                 
00898                                 sequentialDecode = false;
00899                             }
00900                             else {
00901                                 
00902                                 
00903                                 if (pBB != NULL)
00904                                     pCfg->addOutEdge(pBB, uAddr+inst.numBytes);
00905                             }
00906                         }
00907                     }
00908 
00909                     extraProcessCall(call, BB_rtls);
00910 
00911                     
00912                     BB_rtls = NULL;
00913                     break;  
00914                 }
00915 
00916                 case STMT_RET: {
00917                     
00918                     sequentialDecode = false;
00919 
00920                     pBB = createReturnBlock(pProc, BB_rtls, pRtl);
00921 
00922                     
00923                     
00924                     BB_rtls = NULL;     
00925                 }
00926                 break;
00927 
00928                 case STMT_BOOLASSIGN:
00929                     
00930                     
00931                 case STMT_JUNCTION:
00932                     
00933                 case STMT_ASSIGN:
00934                 case STMT_PHIASSIGN:
00935                 case STMT_IMPASSIGN:
00936                 case STMT_IMPREF:
00937                     
00938                     break;
00939         
00940                 } 
00941             }
00942             if (BB_rtls && pRtl)
00943                 
00944                 BB_rtls->push_back(pRtl);
00945 
00946             if (inst.reDecode)
00947                 
00948                 continue;
00949             uAddr += inst.numBytes;
00950             if (uAddr > lastAddr)
00951                 lastAddr = uAddr;
00952 
00953             
00954             
00955             
00956             
00957             
00958             
00959             if (sequentialDecode && pCfg->existsBB(uAddr)) {
00960                 
00961                 if (BB_rtls) {
00962                     PBB pBB = pCfg->newBB(BB_rtls, FALL, 1);
00963                     
00964                     if (pBB) {
00965                         pCfg->addOutEdge(pBB, uAddr);
00966                         BB_rtls = NULL;         
00967                     }
00968                 }
00969                 
00970                 if (!pCfg->isIncomplete(uAddr))
00971                     sequentialDecode = false;
00972             }
00973         }   
00974 
00975         
00976 
00977 
00978         
00979         sequentialDecode = true;
00980 
00981     }   
00982 
00983     
00984     
00985     
00986 
00987     
00988     std::list<CallStatement*>::iterator it;
00989     for (it = callList.begin(); it != callList.end(); it++) {
00990         ADDRESS dest = (*it)->getFixedDest();
00991         
00992         
00993         if (pBF->IsDynamicLinkedProc(dest) || !spec || (dest < pBF->getLimitTextHigh())) {
00994             pCfg->addCall(*it);
00995             
00996             Proc *np = (*it)->getDestProc();
00997             if (np == NULL && dest != NO_ADDRESS) {
00998                 
00999                 np = pProc->getProg()->setNewProc(dest);
01000             }
01001             if (np != NULL) {
01002                 np->setFirstCaller(pProc);
01003                 pProc->addCallee(np);
01004             }           
01005         }
01006     }
01007 
01008     Boomerang::get()->alert_decode(pProc, startAddr, lastAddr, nTotalBytes);
01009 
01010     if (VERBOSE)
01011         LOG << "finished processing proc " << pProc->getName() << " at address " << pProc->getNativeAddress() << "\n";
01012 
01013     return true;
01014 }
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 int FrontEnd::getInst(int addr)
01024 {
01025     return (int)(*(unsigned char*)addr);
01026 }
01027 
01028 
01029 
01030 
01031 
01032 
01033 
01034 
01035 
01036 
01037 
01038 
01039 
01040 
01041 
01042 void TargetQueue::visit(Cfg* pCfg, ADDRESS uNewAddr, PBB& pNewBB) {
01043     
01044     bool bParsed = pCfg->label(uNewAddr, pNewBB);
01045     
01046     
01047     if (!bParsed) {
01048         targets.push(uNewAddr);
01049         if (Boomerang::get()->traceDecoder)
01050             LOG << ">" << uNewAddr << "\t";
01051     }
01052 }
01053 
01054 
01055 
01056 
01057 
01058 
01059 
01060 
01061 void TargetQueue::initial(ADDRESS uAddr) {
01062     targets.push(uAddr);
01063 }
01064 
01065 
01066 
01067 
01068 
01069 
01070 
01071 
01072 
01073 ADDRESS TargetQueue::nextAddress(Cfg* cfg) {
01074     while (!targets.empty())
01075     {
01076         ADDRESS address = targets.front();
01077         targets.pop();
01078         if (Boomerang::get()->traceDecoder)
01079             LOG << "<" << address << "\t";
01080 
01081         
01082         if (!cfg->existsBB(address) || cfg->isIncomplete(address))
01083             return address;
01084     }
01085     return NO_ADDRESS;
01086 }
01087 
01088 void TargetQueue::dump() {
01089     std::queue<ADDRESS> copy(targets);
01090     while (!copy.empty()) {
01091         ADDRESS a = copy.front();
01092         copy.pop();
01093         std::cerr << std::hex << a << ", ";
01094     }
01095     std::cerr << std::dec << "\n";
01096 }
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 
01107 
01108 RTL* decodeRtl(ADDRESS address, int delta, NJMCDecoder* decoder) {
01109     DecodeResult inst = 
01110         decoder->decodeInstruction(address, delta);
01111 
01112     RTL*    rtl = inst.rtl;
01113 
01114     return rtl;
01115 }
01116 
01117 
01118 
01119 
01120 
01121 
01122 
01123 Prog* FrontEnd::getProg() {
01124     return prog;
01125 }
01126 
01127 
01128 
01129 
01130 
01131 
01132 
01133 
01134 
01135 
01136 PBB FrontEnd::createReturnBlock(UserProc* pProc, std::list<RTL*>* BB_rtls, RTL* pRtl) {
01137     Cfg* pCfg = pProc->getCFG();
01138     PBB pBB;
01139     
01140     
01141     if (BB_rtls == NULL) BB_rtls = new std::list<RTL*>;     
01142     BB_rtls->push_back(pRtl);
01143     ADDRESS retAddr = pProc->getTheReturnAddr();
01144     
01145     if (retAddr == NO_ADDRESS) {
01146         
01147         pBB = pCfg->newBB(BB_rtls, RET, 0);
01148         Statement* s = pRtl->getList().back();      
01149         pProc->setTheReturnAddr((ReturnStatement*)s, pRtl->getAddress());
01150     } else {
01151         
01152         
01153         
01154         
01155         
01156         
01157         PBB retBB = pProc->getCFG()->findRetNode();
01158         assert(retBB);
01159         if (retBB->getFirstStmt()->isReturn()) {
01160             
01161             pRtl->deleteLastStmt();
01162         } else
01163             pRtl->clear();
01164         pRtl->appendStmt(new GotoStatement(retAddr));
01165         try {
01166             pBB = pCfg->newBB(BB_rtls, ONEWAY, 1);
01167             
01168             pCfg->addOutEdge(pBB, retAddr, true);
01169             
01170             
01171             targetQueue.visit(pCfg, retAddr, pBB);
01172         } catch(Cfg::BBAlreadyExistsError &) {
01173             if (VERBOSE)
01174                 LOG << "not visiting " << retAddr << " due to exception\n";
01175         }
01176     }
01177     return pBB;
01178 }
01179 
01180 
01181 
01182 void FrontEnd::appendSyntheticReturn(PBB pCallBB, UserProc* pProc, RTL* pRtl) {
01183     ReturnStatement *ret = new ReturnStatement();
01184     std::list<RTL*> *ret_rtls = new std::list<RTL*>();
01185     std::list<Statement*>* stmt_list = new std::list<Statement*>;
01186     stmt_list->push_back(ret);
01187     PBB pret = createReturnBlock(pProc, ret_rtls, new RTL(pRtl->getAddress()+1, stmt_list));
01188     pret->addInEdge(pCallBB);
01189     pCallBB->setOutEdge(0, pret);
01190 }