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
00030
00031 #include <assert.h>
00032 #if defined(_MSC_VER) && _MSC_VER <= 1200
00033 #pragma warning(disable:4786)
00034
00035 #define for if(0){}else for
00036 #endif
00037 #if defined(_MSC_VER) && _MSC_VER >= 1400
00038 #pragma warning(disable:4996) // Warnings about e.g. _strdup deprecated in VS 2005
00039 #endif
00040
00041 #include <assert.h>
00042 #include <fstream>
00043 #include <sstream>
00044 #include <vector>
00045 #include <math.h>
00046 #ifdef _WIN32
00047 #include <direct.h>
00048 #endif
00049
00050 #include "type.h"
00051 #include "cluster.h"
00052 #include "types.h"
00053 #include "statement.h"
00054 #include "exp.h"
00055 #include "cfg.h"
00056 #include "proc.h"
00057 #include "util.h"
00058 #include "register.h"
00059 #include "rtl.h"
00060 #include "BinaryFile.h"
00061 #include "frontend.h"
00062 #include "prog.h"
00063 #include "signature.h"
00064 #include "boomerang.h"
00065 #include "ansi-c-parser.h"
00066 #include "config.h"
00067 #include "managed.h"
00068 #include "log.h"
00069
00070 #ifdef _WIN32
00071 #undef NO_ADDRESS
00072 #include <windows.h>
00073 #ifndef __MINGW32__
00074 namespace dbghelp {
00075 #include <dbghelp.h>
00076 };
00077 #endif
00078 #undef NO_ADDRESS
00079 #define NO_ADDRESS ((ADDRESS)-1)
00080 #endif
00081
00082 #include <sys/stat.h>
00083 #include <sys/types.h>
00084
00085 Prog::Prog() :
00086 pBF(NULL),
00087 pFE(NULL),
00088 m_iNumberedProc(1),
00089 m_rootCluster(new Cluster("prog")) {
00090
00091 }
00092
00093 void Prog::setFrontEnd(FrontEnd *pFE) {
00094 pBF = pFE->getBinaryFile();
00095 this->pFE = pFE;
00096 if (pBF && pBF->getFilename()) {
00097 m_name = pBF->getFilename();
00098 m_rootCluster = new Cluster(getNameNoPathNoExt().c_str());
00099 }
00100 }
00101
00102 Prog::Prog(const char* name) :
00103 pBF(NULL),
00104 pFE(NULL),
00105 m_name(name),
00106 m_iNumberedProc(1),
00107 m_rootCluster(new Cluster(getNameNoPathNoExt().c_str())) {
00108
00109 m_path = m_name;
00110 }
00111
00112 Prog::~Prog() {
00113 if (pBF) delete pBF;
00114 if (pFE) delete pFE;
00115 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00116 if (*it)
00117 delete *it;
00118 }
00119 m_procs.clear();
00120 }
00121
00122 void Prog::setName (const char *name) {
00123 m_name = name;
00124 m_rootCluster->setName(name);
00125 }
00126
00127 char* Prog::getName() {
00128 return (char*) m_name.c_str();
00129 }
00130
00131
00132 bool Prog::wellForm() {
00133 bool wellformed = true;
00134
00135 for (std::list<Proc *>::iterator it = m_procs.begin(); it != m_procs.end(); it++)
00136 if (!(*it)->isLib()) {
00137 UserProc *u = (UserProc*)*it;
00138 wellformed &= u->getCFG()->wellFormCfg();
00139 }
00140 return wellformed;
00141 }
00142
00143
00144
00145 void Prog::finishDecode()
00146 {
00147 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00148 Proc *pProc = *it;
00149
00150 if (pProc->isLib()) continue;
00151 UserProc *p = (UserProc*)pProc;
00152 if (!p->isDecoded()) continue;
00153
00154 p->assignProcsToCalls();
00155 p->finalSimplify();
00156 }
00157
00158 }
00159
00160 void Prog::generateDotFile() {
00161 assert(Boomerang::get()->dotFile);
00162 std::ofstream of(Boomerang::get()->dotFile);
00163 of << "digraph Cfg {" << std::endl;
00164
00165 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00166 Proc *pProc = *it;
00167 if (pProc->isLib()) continue;
00168 UserProc *p = (UserProc*)pProc;
00169 if (!p->isDecoded()) continue;
00170
00171 of << "\nsubgraph cluster_" << p->getName() << " {\n" << " color=gray;\n label=" << p->getName() <<
00172 ";\n";
00173
00174 p->getCFG()->generateDotFile(of);
00175 }
00176 of << "}";
00177 of.close();
00178
00179 }
00180
00181 void Prog::generateCode(Cluster *cluster, UserProc *proc, bool intermixRTL) {
00182 std::string basedir = m_rootCluster->makeDirs();
00183 std::ofstream os;
00184 if (cluster) {
00185 cluster->openStream("c");
00186 cluster->closeStreams();
00187 }
00188 if (cluster == NULL || cluster == m_rootCluster) {
00189 os.open(m_rootCluster->getOutPath("c"));
00190 if (proc == NULL) {
00191 HLLCode *code = Boomerang::get()->getHLLCode();
00192 bool global = false;
00193 if (Boomerang::get()->noDecompile) {
00194 char *sections[] = { "rodata", "data", "data1", 0 };
00195 for (int j = 0; sections[j]; j++) {
00196 std::string str = ".";
00197 str += sections[j];
00198 PSectionInfo info = pBF->GetSectionInfoByName(str.c_str());
00199 str = "start_";
00200 str += sections[j];
00201 code->AddGlobal(str.c_str(), new IntegerType(32, -1), new Const(info ? info->uNativeAddr : (unsigned int)-1));
00202 str = sections[j];
00203 str += "_size";
00204 code->AddGlobal(str.c_str(), new IntegerType(32, -1), new Const(info ? info->uSectionSize : (unsigned int)-1));
00205 Exp *l = new Terminal(opNil);
00206 for (unsigned int i = 0; info && i < info->uSectionSize; i++) {
00207 int n = pBF->readNative1(info->uNativeAddr + info->uSectionSize - 1 - i);
00208 if (n < 0)
00209 n = 256 + n;
00210 l = new Binary(opList, new Const(n), l);
00211 }
00212 code->AddGlobal(sections[j], new ArrayType(new IntegerType(8, -1), info ? info->uSectionSize : 0), l);
00213 }
00214 code->AddGlobal("source_endianness", new IntegerType(), new Const(getFrontEndId() != PLAT_PENTIUM));
00215 os << "#include \"boomerang.h\"\n\n";
00216 global = true;
00217 }
00218 for (std::set<Global*>::iterator it1 = globals.begin(); it1 != globals.end(); it1++) {
00219
00220 Exp *e = NULL;
00221 e = (*it1)->getInitialValue(this);
00222
00223 code->AddGlobal((*it1)->getName(), (*it1)->getType(), e);
00224 global = true;
00225
00226 }
00227 if (global) code->print(os);
00228 }
00229 }
00230
00231
00232 std::list<Proc*>::iterator it = m_procs.begin();
00233 bool first = true, proto = false;
00234 for (it = m_procs.begin(); it != m_procs.end(); it++) {
00235 if ((*it)->isLib()) continue;
00236 if (first) {
00237 first = false;
00238 continue;
00239 }
00240 proto = true;
00241 UserProc* up = (UserProc*)*it;
00242 HLLCode *code = Boomerang::get()->getHLLCode(up);
00243 code->AddPrototype(up);
00244 if (cluster == NULL || cluster == m_rootCluster)
00245 code->print(os);
00246 }
00247 if (proto && cluster == NULL || cluster == m_rootCluster)
00248 os << "\n";
00249
00250 for (it = m_procs.begin(); it != m_procs.end(); it++) {
00251 Proc *pProc = *it;
00252 if (pProc->isLib()) continue;
00253 UserProc *up = (UserProc*)pProc;
00254 if (!up->isDecoded()) continue;
00255 if (proc != NULL && up != proc)
00256 continue;
00257 up->getCFG()->compressCfg();
00258 HLLCode *code = Boomerang::get()->getHLLCode(up);
00259 up->generateCode(code);
00260 if (up->getCluster() == m_rootCluster) {
00261 if (cluster == NULL || cluster == m_rootCluster)
00262 code->print(os);
00263 } else {
00264 if (cluster == NULL || cluster == up->getCluster()) {
00265 up->getCluster()->openStream("c");
00266 code->print(up->getCluster()->getStream());
00267 }
00268 }
00269 }
00270 os.close();
00271 m_rootCluster->closeStreams();
00272 }
00273
00274 void Prog::generateRTL(Cluster *cluster, UserProc *proc) {
00275 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00276 Proc *pProc = *it;
00277 if (pProc->isLib()) continue;
00278 UserProc *p = (UserProc*)pProc;
00279 if (!p->isDecoded()) continue;
00280 if (proc != NULL && p != proc)
00281 continue;
00282 if (cluster != NULL && p->getCluster() != cluster)
00283 continue;
00284
00285 p->getCluster()->openStream("rtl");
00286 p->print(p->getCluster()->getStream());
00287 }
00288 m_rootCluster->closeStreams();
00289 }
00290
00291 Statement *Prog::getStmtAtLex(Cluster *cluster, unsigned int begin, unsigned int end)
00292 {
00293 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00294 Proc *pProc = *it;
00295 if (pProc->isLib()) continue;
00296 UserProc *p = (UserProc*)pProc;
00297 if (!p->isDecoded()) continue;
00298 if (cluster != NULL && p->getCluster() != cluster)
00299 continue;
00300
00301 if (p->getCluster() == cluster) {
00302 Statement *s = p->getStmtAtLex(begin, end);
00303 if (s)
00304 return s;
00305 }
00306 }
00307 return NULL;
00308 }
00309
00310
00311 const char *Cluster::makeDirs()
00312 {
00313 std::string path;
00314 if (parent)
00315 path = parent->makeDirs();
00316 else
00317 path = Boomerang::get()->getOutputPath();
00318 if (getNumChildren() > 0 || parent == NULL) {
00319 path = path + "/" + name;
00320 #ifdef _WIN32
00321 mkdir(path.c_str());
00322 #else
00323 mkdir(path.c_str(), 0777);
00324 #endif
00325 }
00326 return strdup(path.c_str());
00327 }
00328
00329 void Cluster::removeChild(Cluster *n)
00330 {
00331 std::vector<Cluster*>::iterator it;
00332 for (it = children.begin(); it != children.end(); it++)
00333 if (*it == n)
00334 break;
00335 assert(it != children.end());
00336 children.erase(it);
00337 }
00338
00339 void Cluster::addChild(Cluster *n)
00340 {
00341 if (n->parent)
00342 n->parent->removeChild(n);
00343 children.push_back(n);
00344 n->parent = this;
00345 }
00346
00347 Cluster *Cluster::find(const char *nam)
00348 {
00349 if (name == nam)
00350 return this;
00351 for (unsigned i = 0; i < children.size(); i++) {
00352 Cluster *c = children[i]->find(nam);
00353 if (c)
00354 return c;
00355 }
00356 return NULL;
00357 }
00358
00359 const char *Cluster::getOutPath(const char *ext)
00360 {
00361 std::string basedir = makeDirs();
00362
00363 return strdup((basedir + "/" + name + "." + ext).c_str());
00364 }
00365
00366 void Cluster::openStream(const char *ext)
00367 {
00368 if (out.is_open())
00369 return;
00370 out.open(getOutPath(ext));
00371 stream_ext = ext;
00372 if (!strcmp(ext, "xml")) {
00373 out << "<?xml version=\"1.0\"?>\n";
00374 if (parent != NULL)
00375 out << "<procs>\n";
00376 }
00377 }
00378
00379 void Cluster::openStreams(const char *ext)
00380 {
00381 openStream(ext);
00382 for (unsigned i = 0; i < children.size(); i++)
00383 children[i]->openStreams(ext);
00384 }
00385
00386 void Cluster::closeStreams()
00387 {
00388 if (out.is_open()) {
00389 out.close();
00390 }
00391 for (unsigned i = 0; i < children.size(); i++)
00392 children[i]->closeStreams();
00393 }
00394
00395 bool Prog::clusterUsed(Cluster *c)
00396 {
00397 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++)
00398 if ((*it)->getCluster() == c)
00399 return true;
00400 return false;
00401 }
00402
00403 Cluster *Prog::getDefaultCluster(const char *name)
00404 {
00405 const char *cfname = NULL;
00406 if (pBF) cfname = pBF->getFilenameSymbolFor(name);
00407 if (cfname == NULL)
00408 return m_rootCluster;
00409 if (strcmp(cfname + strlen(cfname) - 2, ".c"))
00410 return m_rootCluster;
00411 LOG << "got filename " << cfname << " for " << name << "\n";
00412 char *fname = strdup(cfname);
00413 fname[strlen(fname) - 2] = 0;
00414 Cluster *c = findCluster(fname);
00415 if (c == NULL) {
00416 c = new Cluster(fname);
00417 m_rootCluster->addChild(c);
00418 }
00419 return c;
00420 }
00421
00422 void Prog::generateCode(std::ostream &os) {
00423 HLLCode *code = Boomerang::get()->getHLLCode();
00424 for (std::set<Global*>::iterator it1 = globals.begin(); it1 != globals.end(); it1++) {
00425
00426 Exp *e = NULL;
00427 e = (*it1)->getInitialValue(this);
00428 if (e)
00429 code->AddGlobal((*it1)->getName(), (*it1)->getType(), e);
00430 }
00431 code->print(os);
00432 delete code;
00433 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00434 Proc *pProc = *it;
00435 if (pProc->isLib()) continue;
00436 UserProc *p = (UserProc*)pProc;
00437 if (!p->isDecoded()) continue;
00438 p->getCFG()->compressCfg();
00439 code = Boomerang::get()->getHLLCode(p);
00440 p->generateCode(code);
00441 code->print(os);
00442 delete code;
00443 }
00444 }
00445
00446
00447 void Prog::print(std::ostream &out) {
00448 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00449 Proc *pProc = *it;
00450 if (pProc->isLib()) continue;
00451 UserProc *p = (UserProc*)pProc;
00452 if (!p->isDecoded()) continue;
00453
00454
00455 p->print(out);
00456 }
00457 }
00458
00459
00460 void Prog::clear() {
00461 m_name = std::string("");
00462 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++)
00463 if (*it)
00464 delete *it;
00465 m_procs.clear();
00466 m_procLabels.clear();
00467 if (pBF)
00468 delete pBF;
00469 pBF = NULL;
00470 if (pFE)
00471 delete pFE;
00472 pFE = NULL;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 Proc* Prog::setNewProc(ADDRESS uAddr) {
00487
00488
00489
00490
00491 Proc* pProc = findProc(uAddr);
00492 if (pProc == (Proc*)-1)
00493 return 0;
00494 if (pProc)
00495
00496 return pProc;
00497 ADDRESS other = pBF->IsJumpToAnotherAddr(uAddr);
00498 if (other != NO_ADDRESS)
00499 uAddr = other;
00500 const char* pName = pBF->SymbolByAddress(uAddr);
00501 bool bLib = pBF->IsDynamicLinkedProc(uAddr) | pBF->IsStaticLinkedLibProc(uAddr);
00502 if (pName == NULL) {
00503
00504 std::ostringstream ost;
00505 ost << "proc" << m_iNumberedProc++;
00506 pName = strdup(ost.str().c_str());
00507 if (VERBOSE)
00508 LOG << "assigning name " << pName << " to addr " << uAddr << "\n";
00509 }
00510 pProc = newProc(pName, uAddr, bLib);
00511 return pProc;
00512 }
00513
00514 #if defined(_WIN32) && !defined(__MINGW32__)
00515
00516 Type *typeFromDebugInfo(int index, DWORD64 ModBase);
00517
00518 Type *makeUDT(int index, DWORD64 ModBase)
00519 {
00520 HANDLE hProcess = GetCurrentProcess();
00521 int got;
00522 WCHAR *name;
00523 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_SYMNAME, &name);
00524 assert(got);
00525 if (got) {
00526 char nameA[1024];
00527 WideCharToMultiByte(CP_ACP,0,name,-1,nameA,sizeof(nameA),0,NULL);
00528 Type *ty = Type::getNamedType(nameA);
00529 if (ty)
00530 return new NamedType(nameA);
00531 CompoundType *cty = new CompoundType();
00532 DWORD count = 0;
00533 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_CHILDRENCOUNT, &count);
00534 int FindChildrenSize = sizeof(dbghelp::TI_FINDCHILDREN_PARAMS) + count*sizeof(ULONG);
00535 dbghelp::TI_FINDCHILDREN_PARAMS* pFC = (dbghelp::TI_FINDCHILDREN_PARAMS*)malloc( FindChildrenSize );
00536 memset( pFC, 0, FindChildrenSize );
00537 pFC->Count = count;
00538 got = SymGetTypeInfo( hProcess, ModBase, index, dbghelp::TI_FINDCHILDREN, pFC );
00539 for (unsigned int i = 0; i < count; i++) {
00540 char fieldName[1024];
00541 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, pFC->ChildId[i], dbghelp::TI_GET_SYMNAME, &name);
00542 WideCharToMultiByte(CP_ACP,0,name,-1,fieldName,sizeof(fieldName),0,NULL);
00543 DWORD mytype;
00544 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, pFC->ChildId[i], dbghelp::TI_GET_TYPE, &mytype);
00545 cty->addType(typeFromDebugInfo(mytype, ModBase), fieldName);
00546 }
00547 Type::addNamedType(nameA, cty);
00548 ty = Type::getNamedType(nameA);
00549 assert(ty);
00550 return new NamedType(nameA);
00551 }
00552 return NULL;
00553 }
00554
00555 Type *typeFromDebugInfo(int index, DWORD64 ModBase)
00556 {
00557 HANDLE hProcess = GetCurrentProcess();
00558
00559 int got;
00560 DWORD d;
00561 ULONG64 lsz = 0;
00562 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_SYMTAG, &d);
00563 assert(got);
00564 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_LENGTH, &lsz);
00565 int sz = (int)lsz * 8;
00566
00567 switch(d) {
00568 case 11:
00569 return makeUDT(index, ModBase);
00570 case 13:
00571
00572 return new FuncType();
00573 case 14:
00574 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_TYPE, &d);
00575 assert(got);
00576 return new PointerType(typeFromDebugInfo(d, ModBase));
00577 case 15:
00578 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_TYPE, &d);
00579 assert(got);
00580 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_LENGTH, &lsz);
00581 assert(got);
00582 return new ArrayType(typeFromDebugInfo(d, ModBase), (unsigned)lsz);
00583 break;
00584 case 16:
00585 got = dbghelp::SymGetTypeInfo(hProcess, ModBase, index, dbghelp::TI_GET_BASETYPE, &d);
00586 assert(got);
00587 switch(d) {
00588 case 1:
00589 return new VoidType();
00590 case 2:
00591 return new CharType();
00592 case 3:
00593 return new CharType();
00594 case 6:
00595 case 13:
00596 return new IntegerType(sz, 1);
00597 case 7:
00598 case 14:
00599 return new IntegerType(sz, -1);
00600 case 8:
00601 return new FloatType(sz);
00602 case 10:
00603 return new BooleanType();
00604 default:
00605 std::cerr << "unhandled base type " << d << "\n";
00606 assert(false);
00607 }
00608 break;
00609 default:
00610 std::cerr << "unhandled symtag " << d << "\n";
00611 assert(false);
00612 }
00613 return NULL;
00614 }
00615
00616 int debugRegister(int r) {
00617 switch(r) {
00618 case 2:
00619 return 26;
00620 case 4:
00621 return 25;
00622 case 8:
00623 return 29;
00624 }
00625 assert(false);
00626 return -1;
00627 }
00628
00629 BOOL CALLBACK addSymbol(
00630 dbghelp::PSYMBOL_INFO pSymInfo,
00631 ULONG SymbolSize,
00632 PVOID UserContext
00633 )
00634 {
00635 Proc *proc = (Proc*)UserContext;
00636 const char *name = proc->getName();
00637 if (pSymInfo->Flags & SYMFLAG_PARAMETER) {
00638 Type *ty = typeFromDebugInfo(pSymInfo->TypeIndex, pSymInfo->ModBase);
00639 if (pSymInfo->Flags & SYMFLAG_REGREL) {
00640 assert(pSymInfo->Register == 8);
00641 proc->getSignature()->addParameter(ty, pSymInfo->Name, Location::memOf(new Binary(opPlus, Location::regOf(28), new Const((int)pSymInfo->Address - 4))));
00642 } else if (pSymInfo->Flags & SYMFLAG_REGISTER) {
00643 proc->getSignature()->addParameter(ty, pSymInfo->Name, Location::regOf(debugRegister(pSymInfo->Register)));
00644 }
00645 } else if ((pSymInfo->Flags & SYMFLAG_LOCAL) && !proc->isLib()) {
00646 UserProc *u = (UserProc*)proc;
00647 assert(pSymInfo->Flags & SYMFLAG_REGREL);
00648 assert(pSymInfo->Register == 8);
00649 Exp *memref = Location::memOf(new Binary(opMinus, Location::regOf(28), new Const(-((int)pSymInfo->Address - 4))));
00650 Type *ty = typeFromDebugInfo(pSymInfo->TypeIndex, pSymInfo->ModBase);
00651 u->addLocal(ty, pSymInfo->Name, memref);
00652 }
00653 return TRUE;
00654 }
00655
00656 #endif
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 Proc* Prog::newProc (const char* name, ADDRESS uNative, bool bLib ) {
00668 Proc* pProc;
00669 std::string sname(name);
00670 if (bLib)
00671 pProc = new LibProc(this, sname, uNative);
00672 else
00673 pProc = new UserProc(this, sname, uNative);
00674
00675 #if defined(_WIN32) && !defined(__MINGW32__)
00676 if (isWin32()) {
00677
00678 HANDLE hProcess = GetCurrentProcess();
00679 dbghelp::SYMBOL_INFO *sym = (dbghelp::SYMBOL_INFO *)malloc(sizeof(dbghelp::SYMBOL_INFO) + 1000);
00680 sym->SizeOfStruct = sizeof(*sym);
00681 sym->MaxNameLen = 1000;
00682 sym->Name[0] = 0;
00683 BOOL got = dbghelp::SymFromAddr(hProcess, uNative, 0, sym);
00684 DWORD retType;
00685 if (got && *sym->Name && dbghelp::SymGetTypeInfo(hProcess, sym->ModBase, sym->TypeIndex, dbghelp::TI_GET_TYPE, &retType)) {
00686 DWORD d;
00687
00688 got = dbghelp::SymGetTypeInfo(hProcess, sym->ModBase, sym->TypeIndex, dbghelp::TI_GET_CALLING_CONVENTION, &d);
00689 if (got) {
00690 std::cout << "calling convention: " << d << "\n";
00691
00692 } else {
00693
00694 pProc->setSignature(Signature::instantiate(PLAT_PENTIUM, CONV_C, sname.c_str()));
00695 }
00696
00697
00698 Type *rtype = typeFromDebugInfo(retType, sym->ModBase);
00699 if (!rtype->isVoid()) {
00700 pProc->getSignature()->addReturn(rtype, Location::regOf(24));
00701 }
00702
00703
00704 dbghelp::IMAGEHLP_STACK_FRAME stack;
00705 stack.InstructionOffset = uNative;
00706 dbghelp::SymSetContext(hProcess, &stack, 0);
00707 dbghelp::SymEnumSymbols(hProcess, 0, NULL, addSymbol, pProc);
00708
00709 LOG << "final signature: ";
00710 pProc->getSignature()->printToLog();
00711 LOG << "\n";
00712 }
00713 }
00714 #endif
00715 m_procs.push_back(pProc);
00716 m_procLabels[uNative] = pProc;
00717
00718 Boomerang::get()->alert_new(pProc);
00719 return pProc;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728 void Prog::remProc(UserProc* uProc) {
00729
00730 uProc->deleteCFG();
00731
00732
00733 m_procLabels[uProc->getNativeAddress()] = (Proc*)-1;
00734
00735 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00736 if (*it == uProc) {
00737 m_procs.erase(it);
00738 break;
00739 }
00740 }
00741
00742
00743 delete uProc;
00744 }
00745
00746 void Prog::removeProc(const char *name)
00747 {
00748 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++)
00749 if (std::string(name) == (*it)->getName()) {
00750 Boomerang::get()->alert_remove(*it);
00751 m_procs.erase(it);
00752 break;
00753 }
00754 }
00755
00756
00757
00758
00759
00760
00761
00762 int Prog::getNumProcs() {
00763 return m_procs.size();
00764 }
00765
00766 int Prog::getNumUserProcs() {
00767 int n = 0;
00768 for (std::list<Proc*>::const_iterator it = m_procs.begin(); it != m_procs.end(); it++)
00769 if (!(*it)->isLib())
00770 n++;
00771 return n;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780 Proc* Prog::getProc(int idx) const {
00781
00782
00783 if ((idx < 0) || (idx >= (int)m_procs.size())) return 0;
00784 std::list<Proc*>::const_iterator it;
00785 it = m_procs.begin();
00786 for (int i=0; i < idx; i++)
00787 it++;
00788 return (*it);
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 Proc* Prog::findProc(ADDRESS uAddr) const {
00800 PROGMAP::const_iterator it;
00801 it = m_procLabels.find(uAddr);
00802 if (it == m_procLabels.end())
00803 return NULL;
00804 else
00805 return (*it).second;
00806 }
00807
00808 Proc* Prog::findProc(const char *name) const {
00809 std::list<Proc *>::const_iterator it;
00810 for (it = m_procs.begin(); it != m_procs.end(); it++)
00811 if (!strcmp((*it)->getName(), name))
00812 return *it;
00813 return NULL;
00814 }
00815
00816
00817 LibProc *Prog::getLibraryProc(const char *nam) {
00818 Proc *p = findProc(nam);
00819 if (p && p->isLib())
00820 return (LibProc*)p;
00821 return (LibProc*)newProc(nam, NO_ADDRESS, true);
00822 }
00823
00824 Signature* Prog::getLibSignature(const char *nam) {
00825 return pFE->getLibSignature(nam);
00826 }
00827
00828 void Prog::rereadLibSignatures()
00829 {
00830 pFE->readLibraryCatalog();
00831 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
00832 if ((*it)->isLib()) {
00833 (*it)->setSignature(getLibSignature((*it)->getName()));
00834 std::set<CallStatement*> &callers = (*it)->getCallers();
00835 for (std::set<CallStatement*>::iterator it1 = callers.begin(); it1 != callers.end(); it1++)
00836 (*it1)->setSigArguments();
00837 Boomerang::get()->alert_update_signature(*it);
00838 }
00839 }
00840 }
00841
00842 platform Prog::getFrontEndId() {
00843 return pFE->getFrontEndId();
00844 }
00845
00846 Signature *Prog::getDefaultSignature(const char *name)
00847 {
00848 return pFE->getDefaultSignature(name);
00849 }
00850
00851 std::vector<Exp*> &Prog::getDefaultParams()
00852 {
00853 return pFE->getDefaultParams();
00854 }
00855
00856 std::vector<Exp*> &Prog::getDefaultReturns()
00857 {
00858 return pFE->getDefaultReturns();
00859 }
00860
00861 bool Prog::isWin32() {
00862 return pFE->isWin32();
00863 }
00864
00865 const char *Prog::getGlobalName(ADDRESS uaddr)
00866 {
00867
00868 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++) {
00869 if ((*it)->getAddress() == uaddr)
00870 return (*it)->getName();
00871 else if ((*it)->getAddress() < uaddr &&
00872 (*it)->getAddress() + (*it)->getType()->getSize() / 8 > uaddr)
00873 return (*it)->getName();
00874 }
00875 if (pBF)
00876 return pBF->SymbolByAddress(uaddr);
00877 return NULL;
00878 }
00879
00880 void Prog::dumpGlobals() {
00881 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++) {
00882 (*it)->print(std::cerr, this);
00883 std::cerr << "\n";
00884 }
00885 }
00886
00887 ADDRESS Prog::getGlobalAddr(char *nam)
00888 {
00889 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++) {
00890 if (!strcmp((*it)->getName(), nam))
00891 return (*it)->getAddress();
00892 }
00893 return pBF->GetAddressByName(nam);
00894 }
00895
00896 Global* Prog::getGlobal(char *nam) {
00897 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++) {
00898 if (!strcmp((*it)->getName(), nam))
00899 return *it;
00900 }
00901 return NULL;
00902 }
00903
00904 bool Prog::globalUsed(ADDRESS uaddr, Type* knownType) {
00905 Global* global;
00906
00907 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++) {
00908 if ((*it)->getAddress() == uaddr) {
00909 if (knownType) (*it)->meetType(knownType);
00910 return true;
00911 }
00912 else if ((*it)->getAddress() < uaddr && (*it)->getAddress() + (*it)->getType()->getSize() / 8 > uaddr) {
00913 if (knownType) (*it)->meetType(knownType);
00914 return true;
00915 }
00916 }
00917
00918 if (pBF->GetSectionInfoByAddr(uaddr) == NULL) {
00919 if (VERBOSE)
00920 LOG << "refusing to create a global at address that is in no known section of the binary: " << uaddr << "\n";
00921 return false;
00922 }
00923
00924 const char *nam = newGlobalName(uaddr);
00925 Type *ty;
00926 if (knownType) {
00927 ty = knownType;
00928 if (ty->resolvesToArray() && ty->asArray()->isUnbounded()) {
00929 Type* baseType = ty->asArray()->getBaseType();
00930 int baseSize = 0;
00931 if (baseType) baseSize = baseType->getSize() / 8;
00932 int sz = pBF->GetSizeByName(nam);
00933 if (sz && baseSize)
00934
00935 ty->asArray()->setLength(sz / baseSize);
00936 }
00937 }
00938 else
00939 ty = guessGlobalType(nam, uaddr);
00940
00941 global = new Global(ty, uaddr, nam);
00942 globals.insert(global);
00943
00944 if (VERBOSE) {
00945 LOG << "globalUsed: name " << nam << ", address " << uaddr;
00946 if (knownType)
00947 LOG << ", known type " << ty->getCtype() << "\n";
00948 else
00949 LOG << ", guessed type " << ty->getCtype() << "\n";
00950 }
00951 return true;
00952 }
00953
00954 std::map<ADDRESS, std::string> &Prog::getSymbols()
00955 {
00956 return pBF->getSymbols();
00957 }
00958
00959 ArrayType* Prog::makeArrayType(ADDRESS u, Type* t) {
00960 const char* nam = newGlobalName(u);
00961 int sz = pBF->GetSizeByName(nam);
00962 if (sz == 0)
00963 return new ArrayType(t);
00964 int n = t->getSize()/8;
00965 if (n == 0) n = 1;
00966 return new ArrayType(t, sz/n);
00967 }
00968
00969 Type *Prog::guessGlobalType(const char *nam, ADDRESS u) {
00970 #if defined(_WIN32) && !defined(__MINGW32__)
00971 HANDLE hProcess = GetCurrentProcess();
00972 dbghelp::SYMBOL_INFO *sym = (dbghelp::SYMBOL_INFO *)malloc(sizeof(dbghelp::SYMBOL_INFO) + 1000);
00973 sym->SizeOfStruct = sizeof(*sym);
00974 sym->MaxNameLen = 1000;
00975 sym->Name[0] = 0;
00976 BOOL got = dbghelp::SymFromAddr(hProcess, u, 0, sym);
00977 if (got && *sym->Name && sym->TypeIndex) {
00978 assert(!strcmp(nam, sym->Name));
00979 return typeFromDebugInfo(sym->TypeIndex, sym->ModBase);
00980 }
00981 #endif
00982 int sz = pBF->GetSizeByName(nam);
00983 if (sz == 0) {
00984
00985 char* str = getStringConstant(u);
00986 if (str)
00987
00988 return new PointerType(new CharType());
00989 }
00990 Type *ty;
00991 switch(sz) {
00992 case 1: case 2: case 4: case 8:
00993 ty = new IntegerType(sz*8);
00994 break;
00995 default:
00996 ty = new ArrayType(new CharType(), sz);
00997 }
00998 return ty;
00999 }
01000
01001 const char *Prog::newGlobalName(ADDRESS uaddr)
01002 {
01003 const char *nam = getGlobalName(uaddr);
01004 if (nam == NULL) {
01005 std::ostringstream os;
01006 os << "global" << globals.size();
01007 nam = strdup(os.str().c_str());
01008 if (VERBOSE)
01009 LOG << "naming new global: " << nam << " at address " << uaddr << "\n";
01010 }
01011 return nam;
01012 }
01013
01014 Type *Prog::getGlobalType(char* nam) {
01015 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++)
01016 if (!strcmp((*it)->getName(), nam))
01017 return (*it)->getType();
01018 return NULL;
01019 }
01020
01021 void Prog::setGlobalType(const char* nam, Type* ty) {
01022
01023 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++) {
01024 if (!strcmp((*it)->getName(), nam)) {
01025 (*it)->setType(ty);
01026 return;
01027 }
01028 }
01029 }
01030
01031
01032
01033 char *Prog::getStringConstant(ADDRESS uaddr, bool knownString ) {
01034 const SectionInfo* si = pBF->GetSectionInfoByAddr(uaddr);
01035
01036
01037 if (si && !si->isAddressBss(uaddr)) {
01038
01039
01040 char* p = (char*)(uaddr + si->uHostAddr - si->uNativeAddr);
01041 if (knownString)
01042
01043 return p;
01044 int printable = 0;
01045 char last = 0;
01046 for (int i=0; i < 6; i++) {
01047 char c = p[i];
01048 if (c == 0) break;
01049 if (c >= ' ' && c < '\x7F') printable++;
01050 last = c;
01051 }
01052 if (printable >= 4)
01053 return p;
01054
01055 if (last == '\n' && printable >= 2)
01056 return p;
01057 }
01058 return NULL;
01059 }
01060
01061 double Prog::getFloatConstant(ADDRESS uaddr, bool &ok, int bits) {
01062 ok = true;
01063 SectionInfo* si = pBF->GetSectionInfoByAddr(uaddr);
01064 if (si && si->bReadOnly)
01065 if (bits == 64) {
01066 return pBF->readNativeFloat8(uaddr);
01067 } else {
01068 assert(bits == 32);
01069 return pBF->readNativeFloat4(uaddr);
01070 }
01071 ok = false;
01072 return 0.0;
01073 }
01074
01075
01076
01077
01078
01079
01080
01081
01082 Proc* Prog::findContainingProc(ADDRESS uAddr) const {
01083 for (std::list<Proc*>::const_iterator it = m_procs.begin();
01084 it != m_procs.end(); it++) {
01085 Proc *p = (*it);
01086 if (p->getNativeAddress() == uAddr)
01087 return p;
01088 if (p->isLib()) continue;
01089
01090 UserProc *u = (UserProc *)p;
01091 if (u->containsAddr(uAddr))
01092 return p;
01093 }
01094 return NULL;
01095 }
01096
01097
01098
01099
01100
01101
01102
01103 bool Prog::isProcLabel (ADDRESS addr) {
01104 if (m_procLabels[addr] == 0)
01105 return false;
01106 return true;
01107 }
01108
01109
01110
01111
01112
01113
01114
01115 std::string Prog::getNameNoPath() const {
01116 unsigned n = m_name.rfind("/");
01117 if (n == std::string::npos) {
01118 n = m_name.rfind("\\");
01119 if (n == std::string::npos)
01120 return m_name;
01121 }
01122
01123 return m_name.substr(n+1);
01124 }
01125
01126 std::string Prog::getNameNoPathNoExt() const {
01127 std::string nopath = getNameNoPath();
01128 unsigned n = nopath.rfind(".");
01129 if (n == std::string::npos)
01130 return nopath;
01131 return nopath.substr(0, n);
01132 }
01133
01134
01135
01136
01137
01138
01139
01140
01141 Proc* Prog::getFirstProc(PROGMAP::const_iterator& it) {
01142 it = m_procLabels.begin();
01143 while (it != m_procLabels.end() && (it->second == (Proc*) -1))
01144 it++;
01145 if (it == m_procLabels.end())
01146 return 0;
01147 return it->second;
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157 Proc* Prog::getNextProc(PROGMAP::const_iterator& it) {
01158 it++;
01159 while (it != m_procLabels.end() && (it->second == (Proc*) -1))
01160 it++;
01161 if (it == m_procLabels.end())
01162 return 0;
01163 return it->second;
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173 UserProc* Prog::getFirstUserProc(std::list<Proc*>::iterator& it) {
01174 it = m_procs.begin();
01175 while (it != m_procs.end() && (*it)->isLib())
01176 it++;
01177 if (it == m_procs.end())
01178 return 0;
01179 return (UserProc*)*it;
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 UserProc* Prog::getNextUserProc(std::list<Proc*>::iterator& it) {
01191 it++;
01192 while (it != m_procs.end() && (*it)->isLib())
01193 it++;
01194 if (it == m_procs.end())
01195 return 0;
01196 return (UserProc*)*it;
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 const void* Prog::getCodeInfo(ADDRESS uAddr, const char*& last, int& delta) {
01210 delta=0;
01211 last=0;
01212 #ifdef _WIN32
01213
01214 return NULL;
01215 #else
01216 int n = pBF->GetNumSections();
01217 int i;
01218
01219 for (i=0; i < n; i++) {
01220 SectionInfo* pSect = pBF->GetSectionInfo(i);
01221 if ((!pSect->bCode) && (!pSect->bReadOnly))
01222 continue;
01223 if ((uAddr < pSect->uNativeAddr) || (uAddr >= pSect->uNativeAddr + pSect->uSectionSize))
01224 continue;
01225 delta = pSect->uHostAddr - pSect->uNativeAddr;
01226 last = (const char*) (pSect->uHostAddr + pSect->uSectionSize);
01227 const char* p = (const char *) (uAddr + delta);
01228 return p;
01229 }
01230 return NULL;
01231 #endif
01232 }
01233
01234 void Prog::decodeEntryPoint(ADDRESS a) {
01235 Proc* p = (UserProc*)findProc(a);
01236 if (p == NULL || (!p->isLib() && !((UserProc*)p)->isDecoded())) {
01237 if (a < pBF->getLimitTextLow() || a >= pBF->getLimitTextHigh()) {
01238 std::cerr << "attempt to decode entrypoint at address outside text area, addr=" << a << "\n";
01239 if (VERBOSE)
01240 LOG << "attempt to decode entrypoint at address outside text area, addr=" << a << "\n";
01241 return;
01242 }
01243 pFE->decode(this, a);
01244 finishDecode();
01245 }
01246 if (p == NULL)
01247 p = findProc(a);
01248 assert(p);
01249 if (!p->isLib())
01250 entryProcs.push_back((UserProc*)p);
01251 }
01252
01253 void Prog::setEntryPoint(ADDRESS a) {
01254 Proc* p = (UserProc*)findProc(a);
01255 if (p != NULL && !p->isLib())
01256 entryProcs.push_back((UserProc*)p);
01257 }
01258
01259 void Prog::decodeEverythingUndecoded() {
01260 std::list<Proc*>::iterator pp;
01261 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01262 UserProc *up = (UserProc*) *pp;
01263 if (up == NULL) continue;
01264 if (up->isLib()) continue;
01265 if (up->isDecoded()) continue;
01266 pFE->decode(this, up->getNativeAddress());
01267 }
01268 finishDecode();
01269 }
01270
01271 void Prog::decompile() {
01272 assert(m_procs.size());
01273
01274 if (VERBOSE)
01275 LOG << (int)m_procs.size() << " procedures\n";
01276
01277
01278 std::list<UserProc*>::iterator ee;
01279 for (ee = entryProcs.begin(); ee != entryProcs.end(); ++ee) {
01280 std::cerr << "decompiling entry point " << (*ee)->getName() << "\n";
01281 if (VERBOSE)
01282 LOG << "decompiling entry point " << (*ee)->getName() << "\n";
01283 int indent = 0;
01284 (*ee)->decompile(new ProcList, indent);
01285 }
01286
01287
01288 std::list<Proc*>::iterator pp;
01289 if (Boomerang::get()->decodeMain && !Boomerang::get()->noDecodeChildren) {
01290 bool foundone = true;
01291 while (foundone) {
01292 foundone = false;
01293 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01294 UserProc* proc = (UserProc*)(*pp);
01295 if (proc->isLib()) continue;
01296 if (proc->isDecompiled()) continue;
01297 int indent = 0;
01298 proc->decompile(new ProcList, indent);
01299 foundone = true;
01300 }
01301 }
01302 }
01303
01304
01305 if (Boomerang::get()->conTypeAnalysis && Boomerang::get()->dfaTypeAnalysis) {
01306 std::cerr << "can't use two types of type analysis at once!\n";
01307 Boomerang::get()->conTypeAnalysis = false;
01308 }
01309 globalTypeAnalysis();
01310
01311
01312 if (!Boomerang::get()->noDecompile) {
01313 if (!Boomerang::get()->noRemoveReturns) {
01314
01315 if (VERBOSE)
01316 LOG << "prog: global removing unused returns\n";
01317
01318 while(removeUnusedReturns());
01319 }
01320
01321
01322 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01323 UserProc* proc = (UserProc*)(*pp);
01324 if (proc->isLib()) continue;
01325 proc->printXML();
01326 }
01327 }
01328
01329 if (VERBOSE)
01330 LOG << "transforming from SSA\n";
01331
01332
01333 fromSSAform();
01334
01335
01336
01337 removeUnusedGlobals();
01338 }
01339
01340 void Prog::removeUnusedGlobals() {
01341 if (VERBOSE)
01342 LOG << "removing unused globals\n";
01343
01344
01345 std::list<Exp*> usedGlobals;
01346 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++) {
01347 if ((*it)->isLib()) continue;
01348 UserProc *u = (UserProc*)(*it);
01349 Exp* search = new Location(opGlobal, new Terminal(opWild), u);
01350
01351
01352 StatementList stmts;
01353 StatementList::iterator ss;
01354 u->getStatements(stmts);
01355 for (ss = stmts.begin(); ss != stmts.end(); ++ss) {
01356 Statement* s = *ss;
01357 if (s->isImplicit()) continue;
01358 bool found = s->searchAll(search, usedGlobals);
01359 if (found && DEBUG_UNUSED)
01360 LOG << " a global is used by stmt " << s->getNumber() << "\n";
01361 }
01362 }
01363
01364
01365 std::map<std::string, Global*> namedGlobals;
01366 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++)
01367 namedGlobals[(*it)->getName()] = (*it);
01368
01369
01370 char* name;
01371 Global* usedGlobal;
01372
01373 globals.clear();
01374 for (std::list<Exp*>::iterator it = usedGlobals.begin(); it != usedGlobals.end(); it++) {
01375 if (DEBUG_UNUSED)
01376 LOG << " " << *it << " is used\n";
01377 name = ((Const*)(*it)->getSubExp1())->getStr();
01378 usedGlobal=namedGlobals[name];
01379 if(usedGlobal) {
01380 globals.insert(usedGlobal);
01381 } else {
01382 LOG << "warning: an expression refers to a nonexistent global\n";
01383 }
01384 }
01385 }
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 bool Prog::removeUnusedReturns() {
01397
01398
01399
01400
01401 std::set<UserProc*> removeRetSet;
01402 std::list<Proc*>::iterator pp;
01403 bool change=false;
01404 for (pp = m_procs.begin(); pp != m_procs.end(); ++pp) {
01405 UserProc* proc = (UserProc*)(*pp);
01406 if (proc->isLib()) continue;
01407 if (!proc->isDecoded()) continue;
01408 removeRetSet.insert(proc);
01409 }
01410
01411
01412
01413 std::set<UserProc*>::iterator it;
01414 while (removeRetSet.size()) {
01415 it = removeRetSet.begin();
01416 change |= (*it)->removeRedundantReturns(removeRetSet);
01417
01418
01419 removeRetSet.erase(it);
01420 }
01421 return change;
01422 }
01423
01424
01425 void Prog::fromSSAform() {
01426 std::list<Proc*>::iterator pp;
01427 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01428 UserProc* proc = (UserProc*)(*pp);
01429 if (proc->isLib()) continue;
01430 if (Boomerang::get()->vFlag) {
01431 LOG << "===== before transformation from SSA form for " << proc->getName() << " =====\n";
01432 proc->printToLog();
01433 LOG << "===== end before transformation from SSA for " << proc->getName() << " =====\n\n";
01434 if (Boomerang::get()->dotFile)
01435 proc->printDFG();
01436 }
01437 proc->fromSSAform();
01438 if (Boomerang::get()->vFlag) {
01439 LOG << "===== after transformation from SSA form for " << proc->getName() << " =====\n";
01440 proc->printToLog();
01441 LOG << "===== end after transformation from SSA for " << proc->getName() << " =====\n\n";
01442 }
01443 }
01444 }
01445
01446 void Prog::conTypeAnalysis() {
01447 if (VERBOSE || DEBUG_TA)
01448 LOG << "=== start constraint-based type analysis ===\n";
01449
01450
01451 std::list<Proc*>::iterator pp;
01452 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01453 UserProc* proc = (UserProc*)(*pp);
01454 if (proc->isLib()) continue;
01455 if (!proc->isDecoded()) continue;
01456 proc->conTypeAnalysis();
01457 }
01458 if (VERBOSE || DEBUG_TA)
01459 LOG << "=== end type analysis ===\n";
01460 }
01461
01462 void Prog::globalTypeAnalysis() {
01463 if (VERBOSE || DEBUG_TA)
01464 LOG << "### start global data-flow-based type analysis ###\n";
01465 std::list<Proc*>::iterator pp;
01466 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01467 UserProc* proc = (UserProc*)(*pp);
01468 if (proc->isLib()) continue;
01469 if (!proc->isDecoded()) continue;
01470
01471
01472 std::cout << "global type analysis for " << proc->getName() << "\n";
01473 proc->typeAnalysis();
01474 }
01475 if (VERBOSE || DEBUG_TA)
01476 LOG << "### end type analysis ###\n";
01477 }
01478
01479 void Prog::rangeAnalysis()
01480 {
01481 std::list<Proc*>::iterator pp;
01482 for (pp = m_procs.begin(); pp != m_procs.end(); pp++) {
01483 UserProc* proc = (UserProc*)(*pp);
01484 if (proc->isLib()) continue;
01485 if (!proc->isDecoded()) continue;
01486 proc->rangeAnalysis();
01487 proc->logSuspectMemoryDefs();
01488 }
01489 }
01490
01491 void Prog::printCallGraph() {
01492 std::string fname1 = Boomerang::get()->getOutputPath() + "callgraph.out";
01493 std::string fname2 = Boomerang::get()->getOutputPath() + "callgraph.dot";
01494 int fd1 = lockFileWrite(fname1.c_str());
01495 int fd2 = lockFileWrite(fname2.c_str());
01496 std::ofstream f1(fname1.c_str());
01497 std::ofstream f2(fname2.c_str());
01498 std::set<Proc*> seen;
01499 std::map<Proc*, int> spaces;
01500 std::map<Proc*, Proc*> parent;
01501 std::list<Proc*> procList;
01502 std::list<UserProc*>::iterator pp;
01503 f2 << "digraph callgraph {\n";
01504 for (pp = entryProcs.begin(); pp != entryProcs.end(); ++pp)
01505 procList.push_back(*pp);
01506 spaces[procList.front()] = 0;
01507 while (procList.size()) {
01508 Proc *p = procList.front();
01509 procList.erase(procList.begin());
01510 if ((unsigned)p == NO_ADDRESS)
01511 continue;
01512 if (seen.find(p) == seen.end()) {
01513 seen.insert(p);
01514 int n = spaces[p];
01515 for (int i = 0; i < n; i++)
01516 f1 << " ";
01517 f1 << p->getName() << " @ " << std::hex << p->getNativeAddress();
01518 if (parent.find(p) != parent.end())
01519 f1 << " [parent=" << parent[p]->getName() << "]";
01520 f1 << std::endl;
01521 if (!p->isLib()) {
01522 n++;
01523 UserProc *u = (UserProc*)p;
01524 std::list<Proc*> &calleeList = u->getCallees();
01525 for (std::list<Proc*>::reverse_iterator it1 = calleeList.rbegin(); it1 != calleeList.rend(); it1++) {
01526 procList.push_front(*it1);
01527 spaces[*it1] = n;
01528 parent[*it1] = p;
01529 f2 << p->getName() << " -> " << (*it1)->getName() << ";\n";
01530 }
01531 }
01532 }
01533 }
01534 f2 << "}\n";
01535 f1.close();
01536 f2.close();
01537 unlockFile(fd1);
01538 unlockFile(fd2);
01539 }
01540
01541 void printProcsRecursive(Proc* proc, int indent, std::ofstream &f,std::set<Proc*> &seen)
01542 {
01543 bool fisttime=false;
01544 if (seen.find(proc) == seen.end()) {
01545 seen.insert(proc);
01546 fisttime=true;
01547 }
01548 for (int i = 0; i < indent; i++)
01549 f << " ";
01550
01551 if(!proc->isLib() && fisttime)
01552 {
01553 f << "0x" << std::hex << proc->getNativeAddress();
01554 f << " __nodecode __incomplete void " << proc->getName() << "();\n";
01555
01556 UserProc *u = (UserProc*)proc;
01557 std::list<Proc*> &calleeList = u->getCallees();
01558 for (std::list<Proc*>::iterator it1 = calleeList.begin(); it1 != calleeList.end(); it1++) {
01559 printProcsRecursive(*it1,indent+1,f,seen);
01560 }
01561 for (int i = 0; i < indent; i++)
01562 f << " ";
01563 f << "// End of " << proc->getName() << "\n";
01564 } else {
01565 f << "// " << proc->getName() << "();\n";
01566 }
01567 }
01568
01569 void Prog::printSymbolsToFile() {
01570 std::cerr << "entering Prog::printSymbolsToFile\n";
01571 std::string fname = Boomerang::get()->getOutputPath() + "symbols.h";
01572 int fd = lockFileWrite(fname.c_str());
01573 std::ofstream f(fname.c_str());
01574
01575
01576 f << "/* Functions: */\n";
01577 std::set<Proc*> seen;
01578 std::list<UserProc*>::iterator pp;
01579 for (pp = entryProcs.begin(); pp != entryProcs.end(); ++pp)
01580 printProcsRecursive(*pp, 0, f, seen);
01581
01582 f << "/* Leftovers: */\n";
01583 std::list<Proc*>::iterator it;
01584 for (it = m_procs.begin(); it != m_procs.end(); it++)
01585 if (!(*it)->isLib() && seen.find(*it) == seen.end()) {
01586 printProcsRecursive(*it,0,f,seen);
01587 }
01588
01589 f.close();
01590 unlockFile(fd);
01591 std::cerr << "leaving Prog::printSymbolsToFile\n";
01592 }
01593
01594 void Prog::printCallGraphXML() {
01595 if (!Boomerang::get()->dumpXML)
01596 return;
01597 std::list<Proc*>::iterator it;
01598 for (it = m_procs.begin(); it != m_procs.end(); it++)
01599 (*it)->clearVisited();
01600 std::string fname = Boomerang::get()->getOutputPath() + "callgraph.xml";
01601 int fd = lockFileWrite(fname.c_str());
01602 std::ofstream f(fname.c_str());
01603 f << "<prog name=\"" << getName() << "\">\n";
01604 f << " <callgraph>\n";
01605 std::list<UserProc*>::iterator pp;
01606 for (pp = entryProcs.begin(); pp != entryProcs.end(); ++pp)
01607 (*pp)->printCallGraphXML(f, 2);
01608 for (it = m_procs.begin(); it != m_procs.end(); it++) {
01609 if (!(*it)->isVisited() && !(*it)->isLib()) {
01610 (*it)->printCallGraphXML(f, 2);
01611 }
01612 }
01613 f << " </callgraph>\n";
01614 f << "</prog>\n";
01615 f.close();
01616 unlockFile(fd);
01617 }
01618
01619 void Prog::readSymbolFile(const char *fname) {
01620 std::ifstream ifs;
01621
01622 ifs.open(fname);
01623
01624 if (!ifs.good()) {
01625 LOG << "can't open `" << fname << "'\n";
01626 exit(1);
01627 }
01628
01629 AnsiCParser *par = new AnsiCParser(ifs, false);
01630 platform plat = getFrontEndId();
01631 callconv cc = CONV_C;
01632 if (isWin32()) cc = CONV_PASCAL;
01633 par->yyparse(plat, cc);
01634
01635 for (std::list<Symbol*>::iterator it = par->symbols.begin(); it != par->symbols.end(); it++) {
01636 if ((*it)->sig) {
01637 Proc* p = newProc((*it)->sig->getName(), (*it)->addr, pBF->IsDynamicLinkedProcPointer((*it)->addr) ||
01638
01639
01640 (*it)->mods->noDecode);
01641 if (!(*it)->mods->incomplete) {
01642 p->setSignature((*it)->sig->clone());
01643 p->getSignature()->setForced(true);
01644 }
01645 } else {
01646 const char *nam = (*it)->nam.c_str();
01647 if (strlen(nam) == 0) {
01648 nam = newGlobalName((*it)->addr);
01649 }
01650 Type *ty = (*it)->ty;
01651 if (ty == NULL) {
01652 ty = guessGlobalType(nam, (*it)->addr);
01653 }
01654 globals.insert(new Global(ty, (*it)->addr, nam));
01655 }
01656 }
01657
01658 for (std::list<SymbolRef*>::iterator it2 = par->refs.begin(); it2 != par->refs.end(); it2++) {
01659 pFE->addRefHint((*it2)->addr, (*it2)->nam.c_str());
01660 }
01661
01662 delete par;
01663 ifs.close();
01664 }
01665
01666 Global::~Global() {
01667
01668 }
01669
01670 Exp* Global::getInitialValue(Prog* prog) {
01671 Exp* e = NULL;
01672 PSectionInfo si = prog->getSectionInfoByAddr(uaddr);
01673 if (si && si->isAddressBss(uaddr))
01674
01675 return NULL;
01676 if (si == NULL)
01677 return NULL;
01678 e = prog->readNativeAs(uaddr, type);
01679 return e;
01680 }
01681
01682 void Global::print(std::ostream& os, Prog* prog) {
01683 Exp* init = getInitialValue(prog);
01684 os << type << " " << nam << " at " << std::hex << uaddr << std::dec << " initial value " <<
01685 (init ? init->prints() : "<none>");
01686 }
01687
01688 Exp *Prog::readNativeAs(ADDRESS uaddr, Type *type)
01689 {
01690 Exp *e = NULL;
01691 PSectionInfo si = getSectionInfoByAddr(uaddr);
01692 if (si == NULL)
01693 return NULL;
01694 if (type->resolvesToPointer()) {
01695 ADDRESS init = readNative4(uaddr);
01696 if (init == 0)
01697 return new Const(0);
01698 const char *nam = getGlobalName(init);
01699 if (nam != NULL)
01700
01701 return Location::global(nam, NULL);
01702 if (type->asPointer()->getPointsTo()->resolvesToChar()) {
01703 char *str = getStringConstant(init);
01704 if (str != NULL)
01705 return new Const(str);
01706 }
01707 }
01708 if (type->resolvesToCompound()) {
01709 CompoundType *c = type->asCompound();
01710 Exp *n = e = new Terminal(opNil);
01711 for (unsigned int i = 0; i < c->getNumTypes(); i++) {
01712 ADDRESS addr = uaddr + c->getOffsetTo(i) / 8;
01713 Type *t = c->getType(i);
01714 Exp *v = readNativeAs(addr, t);
01715 if (v == NULL) {
01716 LOG << "unable to read native address " << addr << " as type " << t->getCtype() << "\n";
01717 v = new Const(-1);
01718 }
01719 if (n->isNil()) {
01720 n = new Binary(opList, v, n);
01721 e = n;
01722 } else {
01723 assert(n->getSubExp2()->getOper() == opNil);
01724 n->setSubExp2(new Binary(opList, v, n->getSubExp2()));
01725 n = n->getSubExp2();
01726 }
01727 }
01728 return e;
01729 }
01730 if (type->resolvesToArray() && type->asArray()->getBaseType()->resolvesToChar()) {
01731 char* str = getStringConstant(uaddr, true);
01732 if (str) {
01733
01734 return new Const(str);
01735 }
01736 }
01737 if (type->resolvesToArray()) {
01738 int nelems = -1;
01739 const char *nam = getGlobalName(uaddr);
01740 int base_sz = type->asArray()->getBaseType()->getSize() / 8;
01741 if (nam != NULL)
01742 nelems = pBF->GetSizeByName(nam) / base_sz;
01743 Exp *n = e = new Terminal(opNil);
01744 for (int i = 0; nelems == -1 || i < nelems; i++) {
01745 Exp *v = readNativeAs(uaddr + i * base_sz, type->asArray()->getBaseType());
01746 if (v == NULL)
01747 break;
01748 if (n->isNil()) {
01749 n = new Binary(opList, v, n);
01750 e = n;
01751 } else {
01752 assert(n->getSubExp2()->getOper() == opNil);
01753 n->setSubExp2(new Binary(opList, v, n->getSubExp2()));
01754 n = n->getSubExp2();
01755 }
01756
01757 if (nelems == -1 && v->isConst() && ((Const*)v)->getInt() == 0)
01758 break;
01759 }
01760 }
01761 if (type->resolvesToInteger() || type->resolvesToSize()) {
01762 int size;
01763 if (type->resolvesToInteger())
01764 size = type->asInteger()->getSize();
01765 else
01766 size = type->asSize()->getSize();
01767 switch(size) {
01768 case 8:
01769 e = new Const(
01770 (int)*(char*)(uaddr + si->uHostAddr - si->uNativeAddr));
01771 break;
01772 case 16:
01773
01774 e = new Const(readNative2(uaddr));
01775 break;
01776 case 32:
01777 e = new Const(readNative4(uaddr));
01778 break;
01779 case 64:
01780 e = new Const(readNative8(uaddr));
01781 break;
01782 }
01783 }
01784 if (type->resolvesToFloat()) {
01785 switch(type->asFloat()->getSize()) {
01786 case 32:
01787 e = new Const(readNativeFloat4(uaddr));
01788 break;
01789 case 64:
01790 e = new Const(readNativeFloat8(uaddr));
01791 break;
01792 }
01793 }
01794 return e;
01795 }
01796
01797 void Global::meetType(Type* ty) {
01798 bool ch;
01799 type = type->meetWith(ty, ch);
01800 }
01801
01802 void Prog::reDecode(UserProc* proc) {
01803 std::ofstream os;
01804 pFE->processProc(proc->getNativeAddress(), proc, os);
01805 }
01806
01807
01808
01809
01810 #ifdef USING_MEMO
01811 class ClusterMemo : public Memo {
01812 public:
01813 ClusterMemo(int mId) : Memo(mId) { }
01814
01815 std::string name;
01816 std::vector<Cluster*> children;
01817 Cluster *parent;
01818 };
01819
01820 Memo *Cluster::makeMemo(int mId)
01821 {
01822 ClusterMemo *m = new ClusterMemo(mId);
01823 m->name = name;
01824 m->children = children;
01825 m->parent = parent;
01826 return m;
01827 }
01828
01829 void Cluster::readMemo(Memo *mm, bool dec)
01830 {
01831 ClusterMemo *m = dynamic_cast<ClusterMemo*>(mm);
01832
01833 name = m->name;
01834 children = m->children;
01835 parent = m->parent;
01836
01837 for (std::vector<Cluster*>::iterator it = children.begin(); it != children.end(); it++)
01838 (*it)->restoreMemo(m->mId, dec);
01839 }
01840
01841 class GlobalMemo : public Memo {
01842 public:
01843 GlobalMemo(int mId) : Memo(mId) { }
01844
01845 Type *type;
01846 ADDRESS uaddr;
01847 std::string nam;
01848 };
01849
01850 Memo *Global::makeMemo(int mId)
01851 {
01852 GlobalMemo *m = new GlobalMemo(mId);
01853 m->type = type;
01854 m->uaddr = uaddr;
01855 m->nam = nam;
01856
01857 type->takeMemo(mId);
01858 return m;
01859 }
01860
01861 void Global::readMemo(Memo *mm, bool dec)
01862 {
01863 GlobalMemo *m = dynamic_cast<GlobalMemo*>(mm);
01864
01865 type = m->type;
01866 uaddr = m->uaddr;
01867 nam = m->nam;
01868
01869 type->restoreMemo(m->mId, dec);
01870 }
01871
01872 class ProgMemo : public Memo {
01873 public:
01874 ProgMemo(int m) : Memo(m) { }
01875
01876 std::string m_name, m_path;
01877 std::list<Proc*> m_procs;
01878 PROGMAP m_procLabels;
01879 std::set<Global*> globals;
01880 DataIntervalMap globalMap;
01881 int m_iNumberedProc;
01882 Cluster *m_rootCluster;
01883 };
01884
01885 Memo *Prog::makeMemo(int mId)
01886 {
01887 ProgMemo *m = new ProgMemo(mId);
01888 m->m_name = m_name;
01889 m->m_path = m_path;
01890 m->m_procs = m_procs;
01891 m->m_procLabels = m_procLabels;
01892 m->globals = globals;
01893 m->globalMap = globalMap;
01894 m->m_iNumberedProc = m_iNumberedProc;
01895 m->m_rootCluster = m_rootCluster;
01896
01897 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++)
01898 (*it)->takeMemo(m->mId);
01899 m_rootCluster->takeMemo(m->mId);
01900 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++)
01901 (*it)->takeMemo(m->mId);
01902
01903 return m;
01904 }
01905
01906 void Prog::readMemo(Memo *mm, bool dec)
01907 {
01908 ProgMemo *m = dynamic_cast<ProgMemo*>(mm);
01909 m_name = m->m_name;
01910 m_path = m->m_path;
01911 m_procs = m->m_procs;
01912 m_procLabels = m->m_procLabels;
01913 globals = m->globals;
01914 globalMap = m->globalMap;
01915 m_iNumberedProc = m->m_iNumberedProc;
01916 m_rootCluster = m->m_rootCluster;
01917
01918 for (std::list<Proc*>::iterator it = m_procs.begin(); it != m_procs.end(); it++)
01919 (*it)->restoreMemo(m->mId, dec);
01920 m_rootCluster->restoreMemo(m->mId, dec);
01921 for (std::set<Global*>::iterator it = globals.begin(); it != globals.end(); it++)
01922 (*it)->restoreMemo(m->mId, dec);
01923 }
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953 void Memoisable::takeMemo(int mId)
01954 {
01955 if (cur_memo != memos.end() && (*cur_memo)->mId == mId && mId != -1)
01956 return;
01957
01958 if (cur_memo != memos.begin()) {
01959 std::list<Memo*>::iterator it = memos.begin();
01960 while (it != cur_memo)
01961 it = memos.erase(it);
01962 }
01963
01964 if (mId == -1) {
01965 if (cur_memo == memos.end())
01966 mId = 1;
01967 else
01968 mId = memos.front()->mId + 1;
01969 }
01970
01971 Memo *m = makeMemo(mId);
01972
01973 memos.push_front(m);
01974 cur_memo = memos.begin();
01975 }
01976
01977 void Memoisable::restoreMemo(int mId, bool dec)
01978 {
01979 if (memos.begin() == memos.end())
01980 return;
01981
01982 if ((*cur_memo)->mId == mId && mId != -1)
01983 return;
01984
01985 if (dec) {
01986 if (cur_memo == memos.begin())
01987 return;
01988 cur_memo--;
01989 } else {
01990 cur_memo++;
01991 if (cur_memo == memos.end()) {
01992 cur_memo--;
01993 return;
01994 }
01995 }
01996
01997 Memo *m = *cur_memo;
01998 if (m->mId != mId && mId != -1)
01999 return;
02000
02001 readMemo(m, dec);
02002 }
02003
02004
02005 bool Memoisable::canRestore(bool dec)
02006 {
02007 if (memos.begin() == memos.end())
02008 return false;
02009
02010 if (dec) {
02011 if (cur_memo == memos.begin())
02012 return false;
02013 } else {
02014 cur_memo++;
02015 if (cur_memo == memos.end()) {
02016 cur_memo--;
02017 return false;
02018 }
02019 cur_memo--;
02020 }
02021 return true;
02022 }
02023
02024 void Memoisable::takeMemo()
02025 {
02026 takeMemo(-1);
02027 }
02028
02029 void Memoisable::restoreMemo(bool dec)
02030 {
02031 restoreMemo(-1, dec);
02032 }
02033
02034 #endif // #ifdef USING_MEMO
02035
02036 void Prog::decodeFragment(UserProc* proc, ADDRESS a)
02037 {
02038 if (a >= pBF->getLimitTextLow() && a < pBF->getLimitTextHigh())
02039 pFE->decodeFragment(proc, a);
02040 else {
02041 std::cerr << "attempt to decode fragment outside text area, addr=" << a << "\n";
02042 if (VERBOSE)
02043 LOG << "attempt to decode fragment outside text area, addr=" << a << "\n";
02044 }
02045 }
02046
02047 Exp *Prog::addReloc(Exp *e, ADDRESS lc)
02048 {
02049 assert(e->isConst());
02050 Const *c = (Const*)e;
02051
02052
02053
02054
02055
02056 if (pBF->IsRelocationAt(lc)) {
02057 std::map<ADDRESS, std::string> &symbols = pBF->getSymbols();
02058 if (symbols.find(c->getInt()) != symbols.end()) {
02059 const char *n = symbols[c->getInt()].c_str();
02060 ADDRESS a = c->getInt();
02061 unsigned int sz = pBF->GetSizeByName(n);
02062 if (getGlobal((char*)n) == NULL) {
02063 Global *global = new Global(new SizeType(sz*8), a, n);
02064 globals.insert(global);
02065 }
02066 e = new Unary(opAddrOf, Location::global(n, NULL));
02067 } else {
02068 char *str = getStringConstant(c->getInt());
02069 if (str)
02070 e = new Const(str);
02071 else {
02072
02073 for (std::map<ADDRESS, std::string>::iterator it = symbols.begin(); it != symbols.end(); it++) {
02074 if ((*it).first < (ADDRESS)c->getInt() && (*it).first + pBF->GetSizeByName((*it).second.c_str()) >
02075 (ADDRESS)c->getInt()) {
02076 int off = c->getInt() - (*it).first;
02077 e = new Binary(opPlus,
02078 new Unary(opAddrOf, Location::global((*it).second.c_str(), NULL)),
02079 new Const(off));
02080 break;
02081 }
02082 }
02083 }
02084 }
02085 }
02086 return e;
02087 }
02088