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 }