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