static void emergencyDump(int quit)
{
  extern sqInt preSnapshot(void);
  extern sqInt postSnapshot(void);
  extern void writeImageFile(sqInt);
  char savedName[MAXPATHLEN];
  char baseName[MAXPATHLEN];
  char *term;
  int  dataSize, i;
  strncpy(savedName, imageName, MAXPATHLEN);
  strncpy(baseName, imageName, MAXPATHLEN);
  if ((term= strrchr(baseName, '.')))
    *term= '\0';
  for (i= 0; ++i;)
    {
      struct stat sb;
      sprintf(imageName, "%s-emergency-dump-%d.image", baseName, i);
      if (stat(imageName, &sb))
	break;
    }
  dataSize= preSnapshot();
  writeImageFile(dataSize);

  fprintf(stderr, "\n");
  printCallStack();
  fprintf(stderr, "\nTo recover valuable content from this image:\n");
  fprintf(stderr, "    squeak %s\n", imageName);
  fprintf(stderr, "and then evaluate\n");
  fprintf(stderr, "    Smalltalk processStartUpList: true\n");
  fprintf(stderr, "in a workspace.  DESTROY the dumped image after recovering content!");

  if (quit) abort();
  strncpy(imageName, savedName, sizeof(imageName));
}
static void sigsegv(int ignore)
{
  /* error("Segmentation fault"); */
  static int printingStack= 0;

  printf("\nSegmentation fault\n\n");
  if (!printingStack)
    {
      printingStack= 1;
      printCallStack();
    }
  abort();
}
Ejemplo n.º 3
0
//
// debugging convenience
//
void printCallStack() {
  printCallStack(true, true, stdout);
}
Ejemplo n.º 4
0
static void printCallStackOnError() {
  printCallStack(false, false, stderr);
}
Ejemplo n.º 5
0
void HandlePrefsMenu(int cmd) {
  switch(cmd) {
  case ID_ABOUT: 
    MessageBox(stWindow,VM_VERSION_TEXT,
	       TEXT("About ") TEXT(VM_NAME) TEXT(" on Win32"), MB_OK);
    break;
  case ID_DEFERUPDATES:
    fDeferredUpdate = !fDeferredUpdate;
    SetDeferredUpdate();
    break;
  case ID_SHOWCONSOLE:
    fShowConsole = !fShowConsole;
    SetShowConsole();
    break;
  case ID_DYNAMICCONSOLE:
    fDynamicConsole = !fDynamicConsole;
    SetDynamicConsole();
    break;
  case ID_REDUCECPUUSAGE:
    fReduceCPUUsage = !fReduceCPUUsage;
    SetReduceCPUUsage();
    break;
  case ID_3BUTTONMOUSE:
    f3ButtonMouse = !f3ButtonMouse;
    Set3ButtonMouse();
    break;
  case ID_DEFAULTPRINTER:
    SetTheDefaultPrinter();
    break;
  case ID_REDUCEBACKGROUNDCPU:
    fReduceCPUInBackground = !fReduceCPUInBackground;
    SetReduceCPUInBackground();
    break;
  case ID_1BUTTONMOUSE:
    f1ButtonMouse = !f1ButtonMouse;
    Set1ButtonMouse();
    break;
  case ID_DIRECTSOUND:
    fUseDirectSound = !fUseDirectSound;
    SetUseDirectSound();
    break;
  case ID_FILEACCESS:
    _ioSetFileAccess(!ioHasFileAccess());
    SetAllowFileAccess();
    break;
  case ID_IMAGEWRITE:
    _ioSetImageWrite(!ioCanWriteImage());
    SetAllowImageWrite();
    break;
  case ID_SHOWALLOCATIONS:
    fShowAllocations = !fShowAllocations;
    SetShowAllocations();
    break;
#ifndef NO_NETWORK
  case ID_SOCKETACCESS:
    _ioSetSocketAccess(!ioHasSocketAccess());
    SetAllowSocketAccess();
    break;
  case ID_DBGPRINTSOCKET:
    win32DebugPrintSocketState();
   break;
#endif
  case ID_DBGPRINTSTACK:
    printCallStack();
    break;
  case ID_PRINTALLSTACKS:
    printf("Printing all processes:\n");
    printAllStacks();
    break;
#if STACKVM
  case ID_DUMPPRIMLOG: { extern void dumpPrimTraceLog(void);
    printf("Printing recent primitives:\n");
    dumpPrimTraceLog();
    break;
  }
#endif
  case ID_PRIORITYBOOST:
    fPriorityBoost = !fPriorityBoost;
    SetPriorityBoost();
    break;
  case ID_USEOPENGL:
    fUseOpenGL = !fUseOpenGL;
    SetB3DXUsesOpenGL();
    break;
  case ID_CASEFILES:
    printf("case files %d\n", caseSensitiveFileMode);
    caseSensitiveFileMode = !caseSensitiveFileMode;
    SetCaseSensitiveFileMode();
    printf("case files %d\n", caseSensitiveFileMode);
    break;
  }
}
Ejemplo n.º 6
0
ProcStatus ProcDecompiler::tryDecompileRecursive(UserProc *proc)
{
    /* Cycle detection logic:
     * *********************
     * cycleGrp is an initially null pointer to a set of procedures, representing the procedures
     * involved in the current recursion group, if any. These procedures have to be analysed
     * together as a group, after individual pre-group analysis. child is a set of procedures,
     * cleared at the top of decompile(), representing the cycles associated with the current
     * procedure and all of its children. If this is empty, the current procedure is not involved in
     * recursion, and can be decompiled up to and including removing unused statements. callStack is
     * an initially empty list of procedures, representing the call stack from the current entry
     * point to the current procedure, inclusive. If (after all children have been processed:
     * important!) the first element in callStack and also cycleGrp is the current procedure, we
     * have the maximal set of distinct cycles, so we can do the recursion group analysis and return
     * an empty set. At the end of the recursion group analysis, the whole group is complete, ready
     * for the global analyses.
     *
     *   cycleSet decompile(ProcList callStack)        // call stack initially empty
     *     child = new ProcSet
     *     push this proc to the call stack
     *     for each child c called by this proc
     *       if c has already been visited but not finished
     *         // have new cycle
     *         if c is in callStack
     *           // this is a completely new cycle
     *           insert every proc from c to the end of callStack into child
     *         else
     *           // this is a new branch of an existing cycle
     *           child = c->cycleGrp
     *           find first element f of callStack that is in cycleGrp
     *           insert every proc after f to the end of callStack into child
     *           for each element e of child
     *         insert e->cycleGrp into child
     *         e->cycleGrp = child
     *       else
     *         // no new cycle
     *         tmp = c->decompile(callStack)
     *         child = union(child, tmp)
     *         set return statement in call to that of c
     *
     *     if (child empty)
     *       earlyDecompile()
     *       child = middleDecompile()
     *       removeUnusedStatments()            // Not involved in recursion
     *     else
     *       // Is involved in recursion
     *       find first element f in callStack that is also in cycleGrp
     *       if (f == this) // The big test: have we got the complete strongly connected component?
     *         recursionGroupAnalysis() // Yes, we have
     *         child = new ProcSet      // Don't add these processed cycles to the parent
     *     remove last element (= this) from callStack
     *     return child
     */

    Project *project = proc->getProg()->getProject();

    LOG_MSG("%1 procedure '%2'", (proc->getStatus() >= PROC_VISITED) ? "Re-visiting" : "Visiting",
            proc->getName());
    project->alertDiscovered(proc);

    // Prevent infinite loops when there are cycles in the call graph (should never happen now)
    if (proc->getStatus() >= PROC_FINAL) {
        LOG_WARN("Proc %1 already has status PROC_FINAL", proc->getName());
        return PROC_FINAL; // Already decompiled
    }

    if (proc->getStatus() < PROC_DECODED) {
        // Can happen e.g. if a callee is visible only after analysing a switch statement
        // Actually decoding for the first time, not REdecoding
        if (!proc->getProg()->reDecode(proc)) {
            return PROC_UNDECODED;
        }
    }

    if (proc->getStatus() < PROC_VISITED) {
        proc->setStatus(PROC_VISITED); // We have at least visited this proc "on the way down"
    }

    m_callStack.push_back(proc);

    if (project->getSettings()->verboseOutput) {
        printCallStack();
    }

    if (project->getSettings()->decodeChildren) {
        // Recurse to callees first, to perform a depth first search
        for (BasicBlock *bb : *proc->getCFG()) {
            if (bb->getType() != BBType::Call) {
                continue;
            }

            // The call Statement will be in the last RTL in this BB
            CallStatement *call = static_cast<CallStatement *>(bb->getRTLs()->back()->getHlStmt());

            if (!call->isCall()) {
                LOG_WARN("BB at address %1 is a CALL but last stmt is not a call: %2",
                         bb->getLowAddr(), call);
                continue;
            }

            assert(call->isCall());
            UserProc *callee = dynamic_cast<UserProc *>(call->getDestProc());

            if (callee == nullptr) { // not an user proc, or missing dest
                continue;
            }

            if (callee->getStatus() == PROC_FINAL) {
                // Already decompiled, but the return statement still needs to be set for this call
                call->setCalleeReturn(callee->getRetStmt());
                continue;
            }

            // check if the callee has already been visited but not done (apart from global
            // analyses). This means that we have found a new cycle or a part of an existing cycle
            if ((callee->getStatus() >= PROC_VISITED) && (callee->getStatus() <= PROC_EARLYDONE)) {
                // if callee is in callStack
                ProcList::iterator calleeIt = std::find(m_callStack.begin(), m_callStack.end(),
                                                        callee);

                if (calleeIt != m_callStack.end()) {
                    // This is a completely new cycle
                    std::shared_ptr<ProcSet> newRecursionGroup(new ProcSet());
                    newRecursionGroup->insert(calleeIt, m_callStack.end());
                    createRecursionGoup(newRecursionGroup);
                }
                else if (callee->getRecursionGroup()) {
                    // This is a new branch of an existing cycle that was visited previously
                    std::shared_ptr<ProcSet> recursionGroup = callee->getRecursionGroup();

                    // Find first element func of callStack that is in callee->recursionGroup
                    ProcList::iterator _pi = std::find_if(
                        m_callStack.begin(), m_callStack.end(), [callee](UserProc *func) {
                            return callee->getRecursionGroup()->find(func) !=
                                   callee->getRecursionGroup()->end();
                        });

                    // Insert every proc after func to the end of path into child
                    assert(_pi != m_callStack.end());
                    for (auto it = std::next(_pi); it != m_callStack.end(); ++it) {
                        addToRecursionGroup(*it, recursionGroup);
                    }
                }

                proc->setStatus(PROC_INCYCLE);
            }
            else {
                // No new cycle
                LOG_VERBOSE("Preparing to decompile callee '%1' of '%2'", callee->getName(),
                            proc->getName());

                callee->promoteSignature();
                tryDecompileRecursive(callee);
                // Child has at least done middleDecompile(), possibly more
                call->setCalleeReturn(callee->getRetStmt());

                if (proc->getStatus() != PROC_INCYCLE &&
                    m_recursionGroups.find(proc) != m_recursionGroups.end()) {
                    proc->setStatus(PROC_INCYCLE);
                    proc->setRecursionGroup(m_recursionGroups.find(proc)->second);
                }
            }
        }
    }

    // if no child involved in recursion
    if (proc->getStatus() != PROC_INCYCLE) {
        project->alertDecompiling(proc);
        LOG_MSG("Decompiling procedure '%1'", proc->getName());

        earlyDecompile(proc);
        middleDecompile(proc);

        if (project->getSettings()->verboseOutput) {
            printCallStack();
        }
    }

    if (proc->getStatus() != PROC_INCYCLE) {
        lateDecompile(proc); // Do the whole works
        proc->setStatus(PROC_FINAL);
        project->alertEndDecompile(proc);
    }
    else if (m_recursionGroups.find(proc) != m_recursionGroups.end()) {
        // This proc's callees, and hence this proc, is/are involved in recursion.
        // Find first element f in path that is also in our recursion group
        ProcList::iterator f = std::find_if(
            m_callStack.begin(), m_callStack.end(), [proc](UserProc *func) {
                return proc->getRecursionGroup()->find(func) != proc->getRecursionGroup()->end();
            });

        // The big test: have we found the whole strongly connected component (in the call graph)?
        if (*f == proc) {
            // Yes, process these procs as a group
            recursionGroupAnalysis(proc->getRecursionGroup());
            proc->setStatus(PROC_FINAL);
            project->alertEndDecompile(proc);
        }
    }

    // Remove last element (= this) from path
    assert(!m_callStack.empty());
    assert(m_callStack.back() == proc);
    m_callStack.pop_back();

    LOG_MSG("Finished decompile of '%1'", proc->getName());

    if (project->getSettings()->verboseOutput) {
        printCallStack();
    }

    return proc->getStatus();
}