prog.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1998-2001, The University of Queensland
00003  * Copyright (C) 2001, Sun Microsystems, Inc
00004  * Copyright (C) 2002-2003, Trent Waddington
00005  *
00006  * See the file "LICENSE.TERMS" for information on usage and
00007  * redistribution of this file, and for a DISCLAIMER OF ALL
00008  * WARRANTIES.
00009  *
00010  */
00011 
00012 /*==============================================================================
00013  * FILE:        prog.cpp
00014  * OVERVIEW:    Implementation of the program class. Holds information of
00015  *              interest to the whole program.
00016  *============================================================================*/
00017 
00018 /*
00019  * $Revision: 1.169 $   // 1.126.2.14
00020  *
00021  * 18 Apr 02 - Mike: Mods for boomerang
00022  * 26 Apr 02 - Mike: common.hs read relative to BOOMDIR
00023  * 20 Jul 04 - Mike: Got rid of BOOMDIR
00024  * 03 Mar 06 - tamlin: prevent arrays from crossing section boundaries
00025  */
00026 
00027 /*==============================================================================
00028  * Dependencies.
00029  *============================================================================*/
00030 
00031 #include <assert.h>
00032 #if defined(_MSC_VER) && _MSC_VER <= 1200 
00033 #pragma warning(disable:4786)
00034 // ? How does the following do any good?
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>                 // For Windows mkdir()
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"                   // For lockFileWrite etc
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     // Default constructor
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     // Constructor taking a name. Technically, the allocation of the space for the name could fail, but this is unlikely
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) {     // Assign a name to this program
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 // well form the entire program
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 // last fixes after decoding everything
00144 // was in analysis.cpp
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         // Subgraph for the proc name
00171         of << "\nsubgraph cluster_" << p->getName() << " {\n" << "     color=gray;\n    label=" << p->getName() <<
00172             ";\n";
00173         // Generate dotty CFG for this proc
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                 // Check for an initial value
00220                 Exp *e = NULL;
00221                 e = (*it1)->getInitialValue(this);
00222 //              if (e) {
00223                     code->AddGlobal((*it1)->getName(), (*it1)->getType(), e);
00224                     global = true;
00225 //              }
00226             }
00227             if (global) code->print(os);        // Avoid blank line if no globals
00228         }
00229     }
00230 
00231     // First declare prototypes for all but the first proc
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);                 // May be the wrong signature if up has ellipsis
00244         if (cluster == NULL || cluster == m_rootCluster)
00245             code->print(os);
00246     }
00247     if (proto && cluster == NULL || cluster == m_rootCluster)
00248         os << "\n";             // Separate prototype(s) from first proc
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     // Ugh - should probably return a whole std::string
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         // Check for an initial value
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 // Print this program, mainly for debugging
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         // decoded userproc.. print it
00455         p->print(out);
00456     }
00457 }
00458 
00459 // clear the current project
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  * FUNCTION:    Prog::setNewProc
00477  * NOTE:        Formally Frontend::newProc
00478  * OVERVIEW:    Call this function when a procedure is discovered (usually by
00479  *                decoding a call instruction). That way, it is given a name
00480  *                that can be displayed in the dot file, etc. If we assign it
00481  *                a number now, then it will retain this number always
00482  * PARAMETERS:  uAddr - Native address of the procedure entry point
00483  * RETURNS:     Pointer to the Proc object, or 0 if this is a deleted (not to
00484  *                be decoded) address
00485  *============================================================================*/
00486 Proc* Prog::setNewProc(ADDRESS uAddr) {
00487     // this test fails when decoding sparc, why?  Please investigate - trent
00488     // Likely because it is in the Procedure Linkage Table (.plt), which for Sparc is in the data section
00489     //assert(uAddr >= limitTextLow && uAddr < limitTextHigh);
00490     // Check if we already have this proc
00491     Proc* pProc = findProc(uAddr);
00492     if (pProc == (Proc*)-1)         // Already decoded and deleted?
00493         return 0;                   // Yes, exit with 0
00494     if (pProc)
00495         // Yes, we are done
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         // No name. Give it a numbered name
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;  // bits
00566 
00567     switch(d) {
00568         case 11:
00569             return makeUDT(index, ModBase);
00570         case 13:
00571             // TODO: signature
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: // int
00595                 case 13: // long
00596                     return new IntegerType(sz, 1);
00597                 case 7: // unsigned int
00598                 case 14: // ulong
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;  // edx
00620         case 4:
00621             return 25;  // ecx
00622         case 8:
00623             return 29;  // ebp
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);  // ebp
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  * FUNCTION:    Prog::newProc
00660  * OVERVIEW:    Creates a new Proc object, adds it to the list of procs in this Prog object, and adds the address to
00661  *                  the list
00662  * PARAMETERS:  name: Name for the proc
00663  *              uNative: Native address of the entry point of the proc
00664  *              bLib: If true, this will be a libProc; else a UserProc
00665  * RETURNS:     A pointer to the new Proc object
00666  *============================================================================*/
00667 Proc* Prog::newProc (const char* name, ADDRESS uNative, bool bLib /*= false*/) {
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         // use debugging information
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             // get a calling convention
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                 // TODO: use it
00692             } else {
00693                 // assume we're stdc calling convention, remove r28, r24 returns
00694                 pProc->setSignature(Signature::instantiate(PLAT_PENTIUM, CONV_C, sname.c_str()));
00695             }
00696 
00697             // get a return type
00698             Type *rtype = typeFromDebugInfo(retType, sym->ModBase);
00699             if (!rtype->isVoid()) {
00700                 pProc->getSignature()->addReturn(rtype, Location::regOf(24));
00701             }
00702 
00703             // find params and locals
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);       // Append this to list of procs
00716     m_procLabels[uNative] = pProc;
00717     // alert the watchers of a new proc
00718     Boomerang::get()->alert_new(pProc);
00719     return pProc;
00720 }
00721 
00722 /*==============================================================================
00723  * FUNCTION:       Prog::remProc
00724  * OVERVIEW:       Removes the UserProc from this Prog object's list, and deletes as much as possible of the Proc
00725  * PARAMETERS:     proc: pointer to the UserProc object to be removed
00726  * RETURNS:        <nothing>
00727  *============================================================================*/
00728 void Prog::remProc(UserProc* uProc) {
00729     // Delete the cfg etc.
00730     uProc->deleteCFG();
00731 
00732     // Replace the entry in the procedure map with -1 as a warning not to decode that address ever again
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     // Delete the UserProc object as well
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  * FUNCTION:    Prog::getNumProcs
00758  * OVERVIEW:    Return the number of real (non deleted) procedures
00759  * PARAMETERS:  None
00760  * RETURNS:     The number of procedures
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  * FUNCTION:    Prog::getProc
00776  * OVERVIEW:    Return a pointer to the indexed Proc object
00777  * PARAMETERS:  Index of the proc
00778  * RETURNS:     Pointer to the Proc object, or 0 if index invalid
00779  *============================================================================*/
00780 Proc* Prog::getProc(int idx) const {
00781     // Return the indexed procedure. If this is used often, we should use a vector instead of a list
00782     // If index is invalid, result will be 0
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  * FUNCTION:    Prog::findProc
00794  * OVERVIEW:    Return a pointer to the associated Proc object, or NULL if none
00795  * NOTE:        Could return -1 for a deleted Proc
00796  * PARAMETERS:  Native address of the procedure entry point
00797  * RETURNS:     Pointer to the Proc object, or 0 if none, or -1 if deleted
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 // get a library procedure by name; create if does not exist
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     // FIXME: inefficient
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;       // Size in bytes
00932             int sz = pBF->GetSizeByName(nam);
00933             if (sz && baseSize)
00934                 // Note: since ty is a pointer and has not been cloned, this will also set the type for knownType
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);        // An "unbounded" array
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         // Check if it might be a string
00985         char* str = getStringConstant(u);
00986         if (str)
00987             // return char* and hope it is dealt with properly
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     // FIXME: inefficient
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 // get a string constant at a given address if appropriate
01032 // if knownString, it is already known to be a char*
01033 char *Prog::getStringConstant(ADDRESS uaddr, bool knownString /* = false */) {
01034     const SectionInfo* si = pBF->GetSectionInfoByAddr(uaddr);
01035     // Too many compilers put constants, including string constants, into read/write sections
01036     //if (si && si->bReadOnly)
01037     if (si && !si->isAddressBss(uaddr)) {
01038         // At this stage, only support ascii, null terminated, non unicode strings.
01039         // At least 4 of the first 6 chars should be printable ascii
01040         char* p = (char*)(uaddr + si->uHostAddr - si->uNativeAddr);
01041         if (knownString)
01042             // No need to guess... this is hopefully a known string
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         // Just a hack while type propagations are not yet ready
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  * FUNCTION:    Prog::findContainingProc
01077  * OVERVIEW:    Return a pointer to the Proc object containing uAddr, or 0 if none
01078  * NOTE:        Could return -1 for a deleted Proc
01079  * PARAMETERS:  Native address to search for
01080  * RETURNS:     Pointer to the Proc object, or 0 if none, or -1 if deleted
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  * FUNCTION:    Prog::isProcLabel
01099  * OVERVIEW:    Return true if this is a real procedure
01100  * PARAMETERS:  Native address of the procedure entry point
01101  * RETURNS:     True if a real (non deleted) proc
01102  *============================================================================*/
01103 bool Prog::isProcLabel (ADDRESS addr) {
01104     if (m_procLabels[addr] == 0)
01105         return false;
01106     return true;
01107 }
01108 
01109 /*==============================================================================
01110  * FUNCTION:    Prog::getNameNoPath
01111  * OVERVIEW:    Get the name for the progam, without any path at the front
01112  * PARAMETERS:  None
01113  * RETURNS:     A string with the name
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  * FUNCTION:    Prog::getFirstProc
01136  * OVERVIEW:    Return a pointer to the first Proc object for this program
01137  * NOTE:        The it parameter must be passed to getNextProc
01138  * PARAMETERS:  it: An uninitialised PROGMAP::const_iterator
01139  * RETURNS:     A pointer to the first Proc object; could be 0 if none
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  * FUNCTION:    Prog::getNextProc
01152  * OVERVIEW:    Return a pointer to the next Proc object for this program
01153  * NOTE:        The it parameter must be from a previous call to getFirstProc or getNextProc
01154  * PARAMETERS:  it: A PROGMAP::const_iterator as above
01155  * RETURNS:     A pointer to the next Proc object; could be 0 if no more
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  * FUNCTION:    Prog::getFirstUserProc
01168  * OVERVIEW:    Return a pointer to the first UserProc object for this program
01169  * NOTE:        The it parameter must be passed to getNextUserProc
01170  * PARAMETERS:  it: An uninitialised std::list<Proc*>::iterator
01171  * RETURNS:     A pointer to the first UserProc object; could be 0 if none
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  * FUNCTION:    Prog::getNextUserProc
01184  * OVERVIEW:    Return a pointer to the next UserProc object for this program
01185  * NOTE:        The it parameter must be from a previous call to
01186  *                getFirstUserProc or getNextUserProc
01187  * PARAMETERS:  it: A std::list<Proc*>::iterator
01188  * RETURNS:     A pointer to the next UserProc object; could be 0 if no more
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  * FUNCTION:    getCodeInfo
01201  * OVERVIEW:    Lookup the given native address in the code section, returning a host pointer corresponding to the same
01202  *               address
01203  * PARAMETERS:  uNative: Native address of the candidate string or constant
01204  *              last: will be set to one past end of the code section (host)
01205  *              delta: will be set to the difference between the host and native addresses
01206  * RETURNS:     Host pointer if in range; NULL if not
01207  *              Also sets 2 reference parameters (see above)
01208  *============================================================================*/
01209 const void* Prog::getCodeInfo(ADDRESS uAddr, const char*& last, int& delta) {
01210     delta=0;
01211     last=0;
01212 #ifdef _WIN32
01213     // this is broken obviously
01214     return NULL;
01215 #else
01216     int n = pBF->GetNumSections();
01217     int i;
01218     // Search all code and read-only sections
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;           // Try the next section
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())                // -sf procs marked as __nodecode are treated as library procs (?)
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;   // Probably not needed
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     // Start decompiling each entry point
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     // Just in case there are any Procs not in the call graph. 
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     // Type analysis, if requested
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             // A final pass to remove returns not used by any caller
01315             if (VERBOSE)
01316                 LOG << "prog: global removing unused returns\n";
01317             // Repeat until no change. Note 100% sure if needed.
01318             while(removeUnusedReturns());
01319         }
01320 
01321         // print XML after removing returns
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     // Now it is OK to transform out of SSA form
01333     fromSSAform();
01334 
01335     // Note: removeUnusedLocals() is now in UserProc::generateCode()
01336 
01337     removeUnusedGlobals();
01338 }
01339 
01340 void Prog::removeUnusedGlobals() {
01341     if (VERBOSE)
01342         LOG << "removing unused globals\n";
01343 
01344     // seach for used globals
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         // Search each statement in u, excepting implicit assignments (their uses don't count, since they don't really
01351         // exist in the program representation)
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;          // Ignore the uses in ImplicitAssigns
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     // make a map to find a global by its name (could be a global var too)
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     // rebuild the globals vector
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 // This is the global removing of unused and redundant returns. The initial idea is simple enough: remove some returns
01388 // according to the formula returns(p) = modifieds(p) isect union(live at c) for all c calling p.
01389 // However, removing returns reduces the uses, leading to three effects:
01390 // 1) The statement that defines the return, if only used by that return, becomes unused
01391 // 2) if the return is implicitly defined, then the parameters may be reduced, which affects all callers
01392 // 3) if the return is defined at a call, the location may no longer be live at the call. If not, you need to check
01393 //   the child, and do the union again (hence needing a list of callers) to find out if this change also affects that
01394 //   child.
01395 // Return true if any change
01396 bool Prog::removeUnusedReturns() {
01397     // For each UserProc. Each proc may process many others, so this may duplicate some work. Really need a worklist of
01398     // procedures not yet processed.
01399     // Define a workset for the procedures who have to have their returns checked
01400     // This will be all user procs, except those undecoded (-sf says just trust the given signature)
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;       // e.g. use -sf file to just prototype the proc
01408         removeRetSet.insert(proc);
01409     }
01410     // The workset is processed in arbitrary order. May be able to do better, but note that sometimes changes propagate
01411     // down the call tree (no caller uses potential returns for child), and sometimes up the call tree (removal of
01412     // returns and/or dead code removes parameters, which affects all callers).
01413     std::set<UserProc*>::iterator it;
01414     while (removeRetSet.size()) {
01415         it = removeRetSet.begin();      // Pick the first element of the set
01416         change |= (*it)->removeRedundantReturns(removeRetSet);
01417         // Note: removing the currently processed item here should prevent unnecessary reprocessing of self recursive
01418         // procedures
01419         removeRetSet.erase(it);         // Remove the current element (may no longer be the first)
01420     }
01421     return change;
01422 }
01423 
01424 // Have to transform out of SSA form after the above final pass
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     // FIXME: This needs to be done bottom of the call-tree first, with repeat until no change for cycles
01450     // in the call graph
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         // FIXME: this just does local TA again. Need to meet types for all parameter/arguments, and return/results!
01471         // This will require a repeat until no change loop
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) // seen lib proc
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     /* Print procs */
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; // don't forget the rest
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                 // NODECODE isn't really the right modifier; perhaps we should have a LIB modifier,
01639                 // to specifically specify that this function obeys library calling conventions
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     // Do-nothing d'tor
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         // This global is in the BSS, so it can't be initialised
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             // TODO: typecast?
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             // Make a global string
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             // "null" terminated
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                 // Note: must respect endianness
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     After every undoable operation:
01928         
01929                                          ? ||
01930         prog->takeMemo();                1 |.1|
01931 
01932         always deletes any memos before the cursor, adds new memo leaving cursor pointing to new memo
01933 
01934 
01935     For first undo:
01936 
01937                                          ? |.4321|
01938         prog->restoreMemo(inc);          4 |5.4321|
01939 
01940         takes a memo of previous state, always leaves cursor pointing at current state
01941 
01942     For second undo:
01943                                          4 |5.4321|
01944         prog->restoreMemo(inc);          3 |54.321|
01945 
01946     To redo:
01947 
01948                                          3  |54.321|
01949         prog->restoreMemo(dec);          4  |5.4321|
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     // relocations have been applied to the constant, so if there is a 
02053     // relocation for this lc then we should be able to replace the constant
02054     // with a symbol.
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                 // check for accesses into the middle of symbols
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 

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