Blame dyninst-10.1.0/dyninstAPI/src/dynProcess.C

Packit ce96f2
/*
Packit ce96f2
 * See the dyninst/COPYRIGHT file for copyright information.
Packit ce96f2
 * 
Packit ce96f2
 * We provide the Paradyn Tools (below described as "Paradyn")
Packit ce96f2
 * on an AS IS basis, and do not warrant its validity or performance.
Packit ce96f2
 * We reserve the right to update, modify, or discontinue this
Packit ce96f2
 * software at any time.  We shall have no obligation to supply such
Packit ce96f2
 * updates or modifications or any other form of support to you.
Packit ce96f2
 * 
Packit ce96f2
 * By your use of Paradyn, you understand and agree that we (or any
Packit ce96f2
 * other person or entity with proprietary rights in Paradyn) are
Packit ce96f2
 * under no obligation to provide either maintenance services,
Packit ce96f2
 * update services, notices of latent defects, or correction of
Packit ce96f2
 * defects for Paradyn.
Packit ce96f2
 * 
Packit ce96f2
 * This library is free software; you can redistribute it and/or
Packit ce96f2
 * modify it under the terms of the GNU Lesser General Public
Packit ce96f2
 * License as published by the Free Software Foundation; either
Packit ce96f2
 * version 2.1 of the License, or (at your option) any later version.
Packit ce96f2
 * 
Packit ce96f2
 * This library is distributed in the hope that it will be useful,
Packit ce96f2
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ce96f2
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ce96f2
 * Lesser General Public License for more details.
Packit ce96f2
 * 
Packit ce96f2
 * You should have received a copy of the GNU Lesser General Public
Packit ce96f2
 * License along with this library; if not, write to the Free Software
Packit ce96f2
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Packit ce96f2
 */
Packit ce96f2
Packit ce96f2
#include "dynProcess.h"
Packit ce96f2
#include "dynThread.h"
Packit ce96f2
#include "pcEventHandler.h"
Packit ce96f2
#include "pcEventMuxer.h"
Packit ce96f2
#include "function.h"
Packit ce96f2
#include "os.h"
Packit ce96f2
#include "debug.h"
Packit ce96f2
#include "instPoint.h"
Packit ce96f2
#include "BPatch.h"
Packit ce96f2
#include "mapped_module.h"
Packit ce96f2
#include "baseTramp.h"
Packit ce96f2
#include "registerSpace.h"
Packit ce96f2
#include "mapped_object.h"
Packit ce96f2
#include "image.h"
Packit ce96f2
Packit ce96f2
#include "common/src/pathName.h"
Packit ce96f2
Packit ce96f2
#include "PCErrors.h"
Packit ce96f2
#include "MemoryEmulator/memEmulator.h"
Packit ce96f2
#include <boost/tuple/tuple.hpp>
Packit ce96f2
Packit ce96f2
#include "symtabAPI/h/SymtabReader.h"
Packit ce96f2
#include "patchAPI/h/PatchMgr.h"
Packit ce96f2
#include "patchAPI/h/Point.h"
Packit ce96f2
Packit ce96f2
Packit ce96f2
#include <sstream>
Packit ce96f2
Packit ce96f2
using namespace Dyninst::ProcControlAPI;
Packit ce96f2
using std::map;
Packit ce96f2
using std::vector;
Packit ce96f2
using std::string;
Packit ce96f2
using std::stringstream;
Packit ce96f2
Packit ce96f2
Dyninst::SymtabAPI::SymtabReaderFactory *PCProcess::symReaderFactory_;
Packit ce96f2
Packit ce96f2
PCProcess *PCProcess::createProcess(const string file, pdvector<string> &argv,
Packit ce96f2
                                    BPatch_hybridMode analysisMode,
Packit ce96f2
                                    pdvector<string> &envp,
Packit ce96f2
                                    const string dir, int stdin_fd, int stdout_fd,
Packit ce96f2
                                    int stderr_fd)
Packit ce96f2
{
Packit ce96f2
    // Debugging information
Packit ce96f2
    startup_cerr << "Creating process " << file << " in directory " << dir << endl;
Packit ce96f2
Packit ce96f2
    startup_cerr << "Arguments: (" << argv.size() << ")" << endl;
Packit ce96f2
    for (unsigned a = 0; a < argv.size(); a++)
Packit ce96f2
        startup_cerr << "   " << a << ": " << argv[a] << endl;
Packit ce96f2
Packit ce96f2
    startup_cerr << "Environment: (" << envp.size() << ")" << endl;
Packit ce96f2
    for (unsigned e = 0; e < envp.size(); e++)
Packit ce96f2
        startup_cerr << "   " << e << ": " << envp[e] << endl;
Packit ce96f2
Packit ce96f2
    startup_printf("%s[%d]: stdin: %d, stdout: %d, stderr: %d\n", FILE__, __LINE__,
Packit ce96f2
            stdin_fd, stdout_fd, stderr_fd);
Packit ce96f2
Packit ce96f2
    initSymtabReader();
Packit ce96f2
Packit ce96f2
    // Create a full path to the executable
Packit ce96f2
    string path = createExecPath(file, dir);
Packit ce96f2
Packit ce96f2
    std::map<int, int> fdMap;
Packit ce96f2
    redirectFds(stdin_fd, stdout_fd, stderr_fd, fdMap);
Packit ce96f2
Packit ce96f2
    if( !setEnvPreload(envp, path) ) {
Packit ce96f2
        startup_cerr << "Failed to set environment var to preload RT library" << endl;
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Create the ProcControl process
Packit ce96f2
    Process::ptr tmpPcProc = Process::createProcess(path, argv, envp, fdMap);
Packit ce96f2
Packit ce96f2
    if( !tmpPcProc ) {
Packit ce96f2
       cerr << "Failed to create process " << path << endl;
Packit ce96f2
       const char *lastErrMsg = getLastErrorMsg();
Packit ce96f2
        startup_printf("%s[%d]: failed to create process for %s: %s\n", __FILE__,
Packit ce96f2
                __LINE__, file.c_str(), lastErrMsg);
Packit ce96f2
        string msg = string("Failed to create process for ") + file +
Packit ce96f2
           string(": ") + lastErrMsg;
Packit ce96f2
        showErrorCallback(68, msg.c_str());
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    startup_cerr << "Created process " << tmpPcProc->getPid() << endl;
Packit ce96f2
Packit ce96f2
    PCProcess *ret = new PCProcess(tmpPcProc, file, analysisMode);
Packit ce96f2
    assert(ret);
Packit ce96f2
    tmpPcProc->setData(ret);
Packit ce96f2
Packit ce96f2
    if( !ret->bootstrapProcess() ) {
Packit ce96f2
        startup_cerr << "Failed to bootstrap process " << ret->getPid()
Packit ce96f2
                     << ": terminating..." << endl;
Packit ce96f2
        ret->terminateProcess();
Packit ce96f2
Packit ce96f2
        delete ret;
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return ret;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCProcess *PCProcess::attachProcess(const string &progpath, int pid,
Packit ce96f2
                                    BPatch_hybridMode analysisMode)
Packit ce96f2
{
Packit ce96f2
    initSymtabReader();
Packit ce96f2
Packit ce96f2
    startup_cerr << "Attaching to process " << pid << endl;
Packit ce96f2
    Process::ptr tmpPcProc = Process::attachProcess(pid, progpath);
Packit ce96f2
Packit ce96f2
    if( !tmpPcProc ) {
Packit ce96f2
        const char *lastErrMsg = getLastErrorMsg();
Packit ce96f2
        startup_printf("%s[%d]: Failed to attach process %d: %s\n",
Packit ce96f2
                __FILE__, __LINE__, pid, lastErrMsg);
Packit ce96f2
        stringstream msg;
Packit ce96f2
        msg << "Failed to attach to process " << pid << ": " << lastErrMsg;
Packit ce96f2
        showErrorCallback(26, msg.str());
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
    startup_cerr << "Attached to process " << tmpPcProc->getPid() << endl;
Packit ce96f2
        
Packit ce96f2
    PCProcess *ret = new PCProcess(tmpPcProc, analysisMode);
Packit ce96f2
    assert(ret);
Packit ce96f2
Packit ce96f2
    tmpPcProc->setData(ret);
Packit ce96f2
Packit ce96f2
    ret->runningWhenAttached_ = tmpPcProc->allThreadsRunningWhenAttached();
Packit ce96f2
    ret->file_ = tmpPcProc->libraries().getExecutable()->getAbsoluteName();
Packit ce96f2
Packit ce96f2
    if( !ret->bootstrapProcess() ) {
Packit ce96f2
        startup_cerr << "Failed to bootstrap process " << pid 
Packit ce96f2
                     << ": terminating..." << endl;
Packit ce96f2
        ret->terminateProcess();
Packit ce96f2
Packit ce96f2
        delete ret;
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return ret;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCProcess *PCProcess::setupForkedProcess(PCProcess *parent, Process::ptr pcProc) {
Packit ce96f2
    startup_printf("%s[%d]: setting up forked process %d\n",
Packit ce96f2
            FILE__, __LINE__, pcProc->getPid());
Packit ce96f2
Packit ce96f2
    PCProcess *ret = new PCProcess(parent, pcProc);
Packit ce96f2
    assert(ret);
Packit ce96f2
Packit ce96f2
    pcProc->setData(ret);
Packit ce96f2
Packit ce96f2
    ret->copyAddressSpace(parent);
Packit ce96f2
Packit ce96f2
    // This requires the AddressSpace be copied from the parent
Packit ce96f2
    if (parent->tracedSyscalls_)
Packit ce96f2
      ret->tracedSyscalls_ = new syscallNotification(parent->tracedSyscalls_, ret);
Packit ce96f2
    else
Packit ce96f2
      ret->tracedSyscalls_ = NULL;
Packit ce96f2
Packit ce96f2
    // Check if RT library exists in child
Packit ce96f2
    if( ret->runtime_lib.size() == 0 ) {
Packit ce96f2
        // Set the RT library name
Packit ce96f2
        if( !ret->getDyninstRTLibName() ) {
Packit ce96f2
            startup_printf("%s[%d]: failed to get Dyninst RT lib name\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            delete ret;
Packit ce96f2
            return NULL;
Packit ce96f2
        }
Packit ce96f2
        startup_printf("%s[%d]: Got Dyninst RT libname: %s\n", FILE__, __LINE__,
Packit ce96f2
                       ret->dyninstRT_name.c_str());
Packit ce96f2
Packit ce96f2
        for(unsigned i = 0; i < ret->mapped_objects.size(); ++i) {
Packit ce96f2
            const fileDescriptor &desc = ret->mapped_objects[i]->getFileDesc();
Packit ce96f2
            fileDescriptor tmpDesc(ret->dyninstRT_name,
Packit ce96f2
                    desc.code(), desc.data(), true);
Packit ce96f2
            if( desc == tmpDesc ) {
Packit ce96f2
                ret->runtime_lib.insert(ret->mapped_objects[i]);
Packit ce96f2
                break;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // TODO hybrid mode stuff
Packit ce96f2
Packit ce96f2
    // Copy signal handlers
Packit ce96f2
    pdvector<codeRange *> sigHandlers;
Packit ce96f2
    parent->signalHandlerLocations_.elements(sigHandlers);
Packit ce96f2
    for(unsigned i = 0; i < sigHandlers.size(); ++i) {
Packit ce96f2
        signal_handler_location *oldSig = dynamic_cast<signal_handler_location *>(sigHandlers[i]);
Packit ce96f2
        assert(oldSig);
Packit ce96f2
        signal_handler_location *newSig = new signal_handler_location(*oldSig);
Packit ce96f2
        ret->signalHandlerLocations_.insert(newSig);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // If required
Packit ce96f2
    if( !ret->copyDanglingMemory(parent) ) {
Packit ce96f2
        startup_printf("%s[%d]: failed to copy dangling memory from parent %d to child %d\n",
Packit ce96f2
                FILE__, __LINE__, parent->getPid(), ret->getPid());
Packit ce96f2
        ret->terminateProcess();
Packit ce96f2
Packit ce96f2
        delete ret;
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    ret->setInEventHandling(true);
Packit ce96f2
Packit ce96f2
    if( !ret->bootstrapProcess() ) {
Packit ce96f2
        startup_cerr << "Failed to bootstrap process " << ret->getPid()
Packit ce96f2
                     << ": terminating..." << endl;
Packit ce96f2
        ret->terminateProcess();
Packit ce96f2
Packit ce96f2
        delete ret;
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    ret->setDesiredProcessState(parent->getDesiredProcessState());
Packit ce96f2
Packit ce96f2
    return ret;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCProcess *PCProcess::setupExecedProcess(PCProcess *oldProc, std::string execPath) {
Packit ce96f2
    BPatch::bpatch->registerExecCleanup(oldProc, NULL);
Packit ce96f2
Packit ce96f2
    PCProcess *newProc = new PCProcess(oldProc->pcProc_, execPath, oldProc->analysisMode_);
Packit ce96f2
Packit ce96f2
    oldProc->pcProc_->setData(newProc);
Packit ce96f2
    newProc->setExecing(true);
Packit ce96f2
Packit ce96f2
    if( !newProc->bootstrapProcess() ) {
Packit ce96f2
        proccontrol_printf("%s[%d]: failed to bootstrap execed process %d\n",
Packit ce96f2
                FILE__, __LINE__, newProc->getPid());
Packit ce96f2
        delete newProc;
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    delete oldProc;
Packit ce96f2
    oldProc = NULL;
Packit ce96f2
Packit ce96f2
    newProc->setInEventHandling(true);
Packit ce96f2
    //newProc->incPendingEvents();
Packit ce96f2
Packit ce96f2
    BPatch::bpatch->registerExecExit(newProc);
Packit ce96f2
Packit ce96f2
    newProc->setExecing(false);
Packit ce96f2
    newProc->setDesiredProcessState(ps_running);
Packit ce96f2
Packit ce96f2
    return newProc;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCProcess::~PCProcess() {
Packit ce96f2
        proccontrol_printf("%s[%d]: destructing PCProcess %d\n",
Packit ce96f2
                FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    if( tracedSyscalls_ ) delete tracedSyscalls_;
Packit ce96f2
    tracedSyscalls_ = NULL;
Packit ce96f2
Packit ce96f2
    if( irpcTramp_ ) delete irpcTramp_;
Packit ce96f2
    irpcTramp_ = NULL;
Packit ce96f2
Packit ce96f2
    signalHandlerLocations_.clear();
Packit ce96f2
Packit ce96f2
    trapMapping.clearTrapMappings();
Packit ce96f2
Packit ce96f2
    if(pcProc_ && pcProc_->getData() == this) pcProc_->setData(NULL);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::initSymtabReader()
Packit ce96f2
{
Packit ce96f2
   //Set SymbolReaderFactory in Stackwalker before create/attach
Packit ce96f2
   if (!symReaderFactory_) {
Packit ce96f2
      symReaderFactory_ = new Dyninst::SymtabAPI::SymtabReaderFactory();
Packit ce96f2
      Dyninst::Stackwalker::Walker::setSymbolReader(symReaderFactory_);
Packit ce96f2
   }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
/***************************************************************************
Packit ce96f2
 **** Runtime library initialization code (Dyninst)                     ****
Packit ce96f2
 ***************************************************************************/
Packit ce96f2
Packit ce96f2
/*
Packit ce96f2
 *
Packit ce96f2
 * Gratuitously large comment. This diagrams the startup flow of
Packit ce96f2
 * messages between the mutator and mutatee. Entry points
Packit ce96f2
 * for create and attach process are both given.
Packit ce96f2
 *     Mutator           Signal              Mutatee
Packit ce96f2
 * Create:
Packit ce96f2
 *     Fork/Exec
Packit ce96f2
 *                     <-- Trap              Halted in exec (handled by ProcControlAPI)
Packit ce96f2
 *     Install trap in main
Packit ce96f2
 *                     <-- Trap              Halted in main
Packit ce96f2
 *  Attach: (also paused, not in main)
Packit ce96f2
 *     Install call to dlopen/
Packit ce96f2
 *     LoadLibrary
Packit ce96f2
 *                     <-- Trap              In library load
Packit ce96f2
 *     Set parameters in library
Packit ce96f2
 *                     <-- Trap              Finished loading
Packit ce96f2
 *     Restore code and leave paused
Packit ce96f2
 *     Finalize library
Packit ce96f2
 *       If finalizing fails, init via iRPC
Packit ce96f2
 */
Packit ce96f2
Packit ce96f2
/*
Packit ce96f2
 * In all cases, the process is left paused at the entry of main
Packit ce96f2
 * (create) or where it was (attach). No permanent instrumentation
Packit ce96f2
 * is inserted.
Packit ce96f2
 */
Packit ce96f2
Packit ce96f2
bool PCProcess::hasReachedBootstrapState(bootstrapState_t state) const {
Packit ce96f2
    return state <= bootstrapState_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::setBootstrapState(bootstrapState_t newState) {
Packit ce96f2
    bootstrapState_ = newState;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::bootstrapProcess() {
Packit ce96f2
    assert( pcProc_->allThreadsStopped() );
Packit ce96f2
Packit ce96f2
    startup_printf("%s[%d]: attempting to bootstrap process %d\n", 
Packit ce96f2
            FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    if( !wasCreatedViaFork() ) {
Packit ce96f2
        // Initialize the inferior heaps
Packit ce96f2
        initializeHeap();
Packit ce96f2
Packit ce96f2
        for(unsigned i = 0; i < mapped_objects.size(); ++i) {
Packit ce96f2
            addInferiorHeap(mapped_objects[i]);
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        // Create the mapped_objects for the executable and shared libraries
Packit ce96f2
        if( !createInitialMappedObjects() ) {
Packit ce96f2
            startup_printf("%s[%d]: bootstrap failed while creating mapped objects\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Create the initial threads
Packit ce96f2
    createInitialThreads();
Packit ce96f2
Packit ce96f2
    // Initialize StackwalkerAPI
Packit ce96f2
    if ( !createStackwalker() )
Packit ce96f2
    {
Packit ce96f2
      startup_printf("Bootstrap failed while initializing Stackwalker\n");
Packit ce96f2
      return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Insert a breakpoint at the entry point of main (and possibly __libc_start_main)
Packit ce96f2
    if( !hasPassedMain() ) {
Packit ce96f2
      startup_printf("%s[%d]: inserting breakpoint at main\n", FILE__, __LINE__);
Packit ce96f2
        if( !insertBreakpointAtMain() ) {
Packit ce96f2
            startup_printf("%s[%d]: bootstrap failed while setting a breakpoint at main\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
	startup_printf("%s[%d]: continuing process to breakpoint\n", FILE__, __LINE__);
Packit ce96f2
        if( !continueProcess() ) {
Packit ce96f2
            startup_printf("%s[%d]: bootstrap failed while continuing the process\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        while( !hasReachedBootstrapState(bs_readyToLoadRTLib) ) {
Packit ce96f2
	  startup_printf("%s[%d]: waiting for main() loop\n", FILE__, __LINE__);
Packit ce96f2
            if( isStopped() ) {
Packit ce96f2
	      startup_printf("%s[%d]: We think the process is stopped, continuing\n", FILE__, __LINE__);
Packit ce96f2
                if( !continueProcess() ) {
Packit ce96f2
                    startup_printf("%s[%d]: bootstrap failed while continuing the process\n",
Packit ce96f2
                            FILE__, __LINE__);
Packit ce96f2
                    return false;
Packit ce96f2
                }
Packit ce96f2
            }
Packit ce96f2
Packit ce96f2
            if( isTerminated() ) {
Packit ce96f2
                bperr("The process exited during startup.  This is likely due to one "
Packit ce96f2
                      "of two reasons:\n"
Packit ce96f2
                      "A). The application is mis-built and unable to load.  Try "
Packit ce96f2
                      "running the application outside of Dyninst and see if it "
Packit ce96f2
                      "loads properly.\n"
Packit ce96f2
                      "B). libdyninstAPI_RT is mis-built.  Try loading the library "
Packit ce96f2
                      "into another application and see if it reports any errors.  "
Packit ce96f2
                      "Ubuntu users - You may need to rebuild the RT library "
Packit ce96f2
                      "with the DISABLE_STACK_PROT line enabled in "
Packit ce96f2
                      "core/make.config.local");
Packit ce96f2
                startup_printf("%s[%d]: program exited early, never reached "
Packit ce96f2
                               "initialized state\n", FILE__, __LINE__);
Packit ce96f2
                startup_printf("Error is likely due to the application or RT "
Packit ce96f2
                               "library having missing symbols or dependencies\n");
Packit ce96f2
                return false;
Packit ce96f2
            }
Packit ce96f2
Packit ce96f2
            startup_printf("%s[%d]: bootstrap waiting for process to initialize\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            if( PCEventMuxer::wait(true) == PCEventMuxer::Error) {
Packit ce96f2
                startup_printf("%s[%d]: bootstrap failed to wait for events\n",
Packit ce96f2
                        FILE__, __LINE__);
Packit ce96f2
                return false;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }else{
Packit ce96f2
        bootstrapState_ = bs_readyToLoadRTLib;
Packit ce96f2
    }
Packit ce96f2
    startup_printf("%s[%d]: process initialized, loading the RT library\n",
Packit ce96f2
            FILE__, __LINE__);
Packit ce96f2
Packit ce96f2
    // Load the RT library
Packit ce96f2
    if( !loadRTLib() ) {
Packit ce96f2
        bperr("Dyninst was unable to load the dyninst runtime library "
Packit ce96f2
              "into the application.  This may be caused by statically "
Packit ce96f2
              "linked executables, or by having dyninst linked against a "
Packit ce96f2
              "different version of libelf than it was built with.");
Packit ce96f2
        startup_printf("%s[%d]: bootstrap failed to load RT library\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
Packit ce96f2
    pdvector<int_variable *> obsCostVec;
Packit ce96f2
    if( !findVarsByAll("DYNINSTobsCostLow", obsCostVec) ) {
Packit ce96f2
        startup_printf("%s[%d]: failed to find DYNINSTobsCostLow\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    costAddr_ = obsCostVec[0]->getAddress();
Packit ce96f2
    assert(costAddr_);
Packit ce96f2
Packit ce96f2
    if( !wasCreatedViaFork() ) {
Packit ce96f2
        // Install system call tracing
Packit ce96f2
        startup_printf("%s[%d]: installing default Dyninst instrumentation into process %d\n", 
Packit ce96f2
            FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
        tracedSyscalls_ = new syscallNotification(this);
Packit ce96f2
Packit ce96f2
        // TODO 
Packit ce96f2
        // pre-fork and pre-exit should depend on whether a callback is defined
Packit ce96f2
        // 
Packit ce96f2
        // This will require checking whether BPatch holds a defined callback and also
Packit ce96f2
        // adding a way for BPatch enable this instrumentation in all processes when
Packit ce96f2
        // a callback is registered
Packit ce96f2
Packit ce96f2
        if (!tracedSyscalls_->installPreFork()) {
Packit ce96f2
            startup_printf("%s[%d]: failed pre-fork notification setup\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        if (!tracedSyscalls_->installPostFork()) {
Packit ce96f2
            startup_printf("%s[%d]: failed post-fork notification setup\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        if (!tracedSyscalls_->installPreExec()) {
Packit ce96f2
            startup_printf("%s[%d]: failed pre-exec notification setup\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        if (!tracedSyscalls_->installPostExec()) {
Packit ce96f2
            startup_printf("%s[%d]: failed post-exec notification setup\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        if (!tracedSyscalls_->installPreExit()) {
Packit ce96f2
            startup_printf("%s[%d]: failed pre-exit notification setup\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        if (!tracedSyscalls_->installPreLwpExit()) {
Packit ce96f2
            startup_printf("%s[%d]: failed pre-lwp-exit notification setup\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        // Initialize the MT stuff
Packit ce96f2
        if (multithread_capable()) {
Packit ce96f2
            if( !instrumentMTFuncs() ) {
Packit ce96f2
                startup_printf("%s[%d]: Failed to instrument MT funcs\n",
Packit ce96f2
                        FILE__, __LINE__);
Packit ce96f2
                return false;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // use heuristics to set hybrid analysis mode
Packit ce96f2
    if (BPatch_heuristicMode == analysisMode_) {
Packit ce96f2
        if (getAOut()->parse_img()->codeObject()->defensiveMode()) {
Packit ce96f2
            analysisMode_ = BPatch_defensiveMode;
Packit ce96f2
        } else {
Packit ce96f2
            analysisMode_ = BPatch_normalMode;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    bootstrapState_ = bs_initialized;
Packit ce96f2
    startup_printf("%s[%d]: finished bootstrapping process %d\n", FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::createStackwalker()
Packit ce96f2
{
Packit ce96f2
  using namespace Stackwalker;
Packit ce96f2
  ProcDebug *procDebug = NULL;
Packit ce96f2
  StackwalkSymLookup *symLookup = NULL;
Packit ce96f2
Packit ce96f2
  // Create ProcessState
Packit ce96f2
  if (NULL == (procDebug = ProcDebug::newProcDebug(pcProc_)))
Packit ce96f2
  {
Packit ce96f2
    startup_printf("Could not create Stackwalker process state\n");
Packit ce96f2
    return false;
Packit ce96f2
  }
Packit ce96f2
Packit ce96f2
  // Create SymbolLookup
Packit ce96f2
  symLookup = new StackwalkSymLookup(this);
Packit ce96f2
Packit ce96f2
  // Create Walker without default steppers
Packit ce96f2
  if (NULL == (stackwalker_ = Walker::newWalker(procDebug,
Packit ce96f2
                                                NULL,
Packit ce96f2
                                                symLookup,
Packit ce96f2
                                                false)))
Packit ce96f2
  {
Packit ce96f2
    startup_printf("Could not create Stackwalker\n");
Packit ce96f2
    return false;
Packit ce96f2
  }
Packit ce96f2
Packit ce96f2
  return createStackwalkerSteppers();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::createInitialThreads() {
Packit ce96f2
    ThreadPool &pcThreads = pcProc_->threads();
Packit ce96f2
    initialThread_ = PCThread::createPCThread(this, pcThreads.getInitialThread());
Packit ce96f2
    addThread(initialThread_);
Packit ce96f2
Packit ce96f2
    for(ThreadPool::iterator i = pcThreads.begin(); i != pcThreads.end(); ++i) {
Packit ce96f2
        if( *i == pcThreads.getInitialThread() ) continue;
Packit ce96f2
Packit ce96f2
        // Wait to create threads until they have user thread information available
Packit ce96f2
        if( !(*i)->haveUserThreadInfo() ) continue;
Packit ce96f2
Packit ce96f2
        PCThread *newThr = PCThread::createPCThread(this, *i);
Packit ce96f2
        addThread(newThr);
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::createInitialMappedObjects() {
Packit ce96f2
    if( file_.empty() ) {
Packit ce96f2
        startup_printf("%s[%d]: failed to determine executable for process %d\n",
Packit ce96f2
                FILE__, __LINE__, getPid());
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    startup_printf("Processing initial shared objects\n");
Packit ce96f2
    startup_printf("----\n");
Packit ce96f2
Packit ce96f2
    initPatchAPI();
Packit ce96f2
Packit ce96f2
    // Do the a.out first...
Packit ce96f2
    mapped_object *aout = mapped_object::createMappedObject(pcProc_->libraries().getExecutable(), this, analysisMode_);
Packit ce96f2
    addASharedObject(aout);
Packit ce96f2
Packit ce96f2
    // Set the RT library name
Packit ce96f2
    if( !getDyninstRTLibName() ) {
Packit ce96f2
      bperr("Dyninst was unable to find the dyninst runtime library.");
Packit ce96f2
        startup_printf("%s[%d]: failed to get Dyninst RT lib name\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Find main
Packit ce96f2
    startup_printf("%s[%d]:  leave setAOut/setting main\n", FILE__, __LINE__);
Packit ce96f2
    setMainFunction();
Packit ce96f2
Packit ce96f2
    // Create mapped objects for any loaded shared libraries
Packit ce96f2
    const LibraryPool &libraries = pcProc_->libraries();
Packit ce96f2
    for(LibraryPool::const_iterator i = libraries.begin(); i != libraries.end(); ++i) {
Packit ce96f2
       // Some platforms don't use the data load address field
Packit ce96f2
       if ((*i) == libraries.getExecutable()) continue;
Packit ce96f2
Packit ce96f2
       startup_cerr << "Library: " << (*i)->getAbsoluteName() 
Packit ce96f2
            << hex << " / " << (*i)->getLoadAddress() 
Packit ce96f2
            << ", " << ((*i)->isSharedLib() ? "<lib>" : "<aout>") << dec << endl;
Packit ce96f2
Packit ce96f2
       mapped_object *newObj = mapped_object::createMappedObject(*i, 
Packit ce96f2
                                                                 this, analysisMode_);
Packit ce96f2
       if( newObj == NULL ) {
Packit ce96f2
           startup_printf("%s[%d]: failed to create mapped object for library %s\n",
Packit ce96f2
                   FILE__, __LINE__, (*i)->getAbsoluteName().c_str());
Packit ce96f2
           return false;
Packit ce96f2
       }
Packit ce96f2
Packit ce96f2
       const fileDescriptor &desc = newObj->getFileDesc();
Packit ce96f2
       fileDescriptor tmpDesc(dyninstRT_name, desc.code(), desc.data(), true);
Packit ce96f2
       if( desc == tmpDesc ) {
Packit ce96f2
          startup_printf("%s[%d]: RT library already loaded, manual loading not necessary\n",
Packit ce96f2
                         FILE__, __LINE__);
Packit ce96f2
          runtime_lib.insert(newObj);
Packit ce96f2
       }
Packit ce96f2
Packit ce96f2
       if (analysisMode_ == BPatch_defensiveMode) {
Packit ce96f2
           std::string lib_name = newObj->fileName();
Packit ce96f2
           if (lib_name == "dyninstAPI_RT.dll" ||
Packit ce96f2
               lib_name == "ntdll.dll" ||
Packit ce96f2
               lib_name == "kernel32.dll" ||
Packit ce96f2
               lib_name == "user32.dll" ||
Packit ce96f2
               lib_name == "KERNELBASE.dll" ||
Packit ce96f2
               lib_name == "msvcrt.dll" ||
Packit ce96f2
               lib_name == "msvcr80.dll" ||
Packit ce96f2
               lib_name == "msvcr100d.dll" ||
Packit ce96f2
               lib_name == "msvcp100d.dll" ||
Packit ce96f2
               lib_name == "MSVCR100.dll") {
Packit ce96f2
                   startup_cerr << "Running library " << lib_name
Packit ce96f2
                       << " in normal mode because it is trusted.\n";
Packit ce96f2
                   newObj->enableDefensiveMode(false);
Packit ce96f2
           }
Packit ce96f2
       }
Packit ce96f2
Packit ce96f2
       addASharedObject(newObj);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
Packit ce96f2
    startup_printf("----\n");
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// creates an image, creates new resources for a new shared object
Packit ce96f2
// adds it to the collection of mapped_objects
Packit ce96f2
void PCProcess::addASharedObject(mapped_object *newObj) {
Packit ce96f2
    assert(newObj);
Packit ce96f2
Packit ce96f2
    addMappedObject(newObj);
Packit ce96f2
Packit ce96f2
    findSignalHandler(newObj);
Packit ce96f2
Packit ce96f2
    startup_printf("%s[%d]: adding shared object %s, addr range 0x%lx to 0x%lx\n",
Packit ce96f2
            FILE__, __LINE__,
Packit ce96f2
            newObj->fileName().c_str(),
Packit ce96f2
            newObj->getBaseAddress(),
Packit ce96f2
            newObj->getBaseAddress() + newObj->get_size());
Packit ce96f2
    parsing_printf("Adding shared object %s, addr range 0x%x to 0x%x\n",
Packit ce96f2
            newObj->fileName().c_str(),
Packit ce96f2
            newObj->getBaseAddress(),
Packit ce96f2
            newObj->getBaseAddress() + newObj->get_size());
Packit ce96f2
Packit ce96f2
    if( heapInitialized_ ) {
Packit ce96f2
        addInferiorHeap(newObj);
Packit ce96f2
    }else{
Packit ce96f2
        startup_printf("%s[%d]: skipping check for new inferior heaps, heap uninitialized\n",
Packit ce96f2
                                       FILE__, __LINE__);
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::removeASharedObject(mapped_object *obj) {
Packit ce96f2
    // Remove from mapped_objects list
Packit ce96f2
    for (unsigned j = 0; j < mapped_objects.size(); j++) {
Packit ce96f2
        if (obj == mapped_objects[j]) {
Packit ce96f2
            mapped_objects[j] = mapped_objects.back();
Packit ce96f2
            mapped_objects.pop_back();
Packit ce96f2
            deletedObjects_.push_back(obj);
Packit ce96f2
            break;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    if (runtime_lib.end() != runtime_lib.find(obj)) {
Packit ce96f2
        runtime_lib.erase( runtime_lib.find(obj) );
Packit ce96f2
    }
Packit ce96f2
    proccontrol_printf("Removing shared object %s, addr range 0x%x to 0x%x\n",
Packit ce96f2
                  obj->fileName().c_str(),
Packit ce96f2
                  obj->getBaseAddress(),
Packit ce96f2
                  obj->get_size());
Packit ce96f2
Packit ce96f2
    // TODO Signal handler...
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::setAOut(fileDescriptor &desc) {
Packit ce96f2
    startup_printf("%s[%d]:  enter setAOut\n", FILE__, __LINE__);
Packit ce96f2
Packit ce96f2
    assert(mapped_objects.size() == 0);
Packit ce96f2
Packit ce96f2
    mapped_object *aout = mapped_object::createMappedObject
Packit ce96f2
                          (desc, this, getHybridMode());
Packit ce96f2
    if (!aout) {
Packit ce96f2
        startup_printf("%s[%d]:  fail setAOut\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// We keep a vector of all signal handler locations
Packit ce96f2
void PCProcess::findSignalHandler(mapped_object *obj) {
Packit ce96f2
    startup_printf("%s[%d]: findSignalhandler(%p)\n", FILE__, __LINE__, obj);
Packit ce96f2
    assert(obj);
Packit ce96f2
Packit ce96f2
    int_symbol sigSym;
Packit ce96f2
    string signame(SIGNAL_HANDLER);
Packit ce96f2
Packit ce96f2
    startup_printf("%s[%d]: findSignalhandler(%p): gettingSymbolInfo\n", FILE__, __LINE__, obj);
Packit ce96f2
    if (obj->getSymbolInfo(signame, sigSym)) {
Packit ce96f2
        // Symbols often have a size of 0. This b0rks the codeRange code,
Packit ce96f2
        // so override to 1 if this is true...
Packit ce96f2
        unsigned size_to_use = sigSym.getSize();
Packit ce96f2
        if (!size_to_use) size_to_use = 1;
Packit ce96f2
Packit ce96f2
        startup_printf("%s[%d]: findSignalhandler(%p): addingSignalHandler(%p, %d)\n", FILE__, __LINE__, obj, (void *) sigSym.getAddr(), size_to_use);
Packit ce96f2
        addSignalHandler(sigSym.getAddr(), size_to_use);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    startup_printf("%s[%d]: leaving findSignalhandler(%p)\n", FILE__, __LINE__, obj);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// NUMBER_OF_MAIN_POSSIBILITIES is defined in image.h
Packit ce96f2
void PCProcess::setMainFunction() {
Packit ce96f2
    assert(!main_function_);
Packit ce96f2
Packit ce96f2
    for (unsigned i = 0; i < NUMBER_OF_MAIN_POSSIBILITIES; i++) {
Packit ce96f2
        main_function_ = findOnlyOneFunction(main_function_names[i]);
Packit ce96f2
        if (main_function_) {
Packit ce96f2
           break;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
 
Packit ce96f2
/*
Packit ce96f2
 * Given an image, add all static heaps inside it
Packit ce96f2
 * (DYNINSTstaticHeap...) to the buffer pool.
Packit ce96f2
 */
Packit ce96f2
void PCProcess::addInferiorHeap(mapped_object *obj) {
Packit ce96f2
    pdvector<heapDescriptor> infHeaps;
Packit ce96f2
    /* Get a list of inferior heaps in the new image */
Packit ce96f2
    if (obj->getInfHeapList(infHeaps)) {
Packit ce96f2
        /* Add the vector to the inferior heap structure */
Packit ce96f2
        for (u_int j=0; j < infHeaps.size(); j++) {
Packit ce96f2
            infmalloc_printf("%s[%d]: adding heap at 0x%lx to 0x%lx, name %s\n",
Packit ce96f2
                             FILE__, __LINE__,
Packit ce96f2
                             infHeaps[j].addr(),
Packit ce96f2
                             infHeaps[j].addr() + infHeaps[j].size(),
Packit ce96f2
                             infHeaps[j].name().c_str());
Packit ce96f2
Packit ce96f2
            // platform-specific check to ignore this heap
Packit ce96f2
            if( skipHeap(infHeaps[j]) ) continue;
Packit ce96f2
Packit ce96f2
            heapItem *h = new heapItem (infHeaps[j].addr(), infHeaps[j].size(),
Packit ce96f2
                                        infHeaps[j].type(), false);
Packit ce96f2
Packit ce96f2
            infmalloc_printf("%s[%d]: Adding heap from 0x%lx - 0x%lx (%d bytes, type %d) from mapped object %s\n",
Packit ce96f2
                             FILE__, __LINE__,
Packit ce96f2
                             infHeaps[j].addr(),
Packit ce96f2
                             infHeaps[j].addr() + infHeaps[j].size(),
Packit ce96f2
                             infHeaps[j].size(),
Packit ce96f2
                             infHeaps[j].type(),
Packit ce96f2
                             obj->fileName().c_str());
Packit ce96f2
Packit ce96f2
            addHeap(h);
Packit ce96f2
Packit ce96f2
            // set rtlib heaps (runtime_lib hasn't been set yet)
Packit ce96f2
            if ( ! obj->fullName().compare( dyninstRT_name ) ) {
Packit ce96f2
                dyninstRT_heaps_.push_back(h);
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
static const unsigned MAX_THREADS = 32; // Should match MAX_THREADS in RTcommon.c
Packit ce96f2
Packit ce96f2
bool PCProcess::loadRTLib() {
Packit ce96f2
    // Check if the RT library has already been loaded
Packit ce96f2
   if( runtime_lib.size() != 0 ) {
Packit ce96f2
      startup_printf("%s[%d]: RT library already loaded\n",
Packit ce96f2
                     FILE__, __LINE__);
Packit ce96f2
Packit ce96f2
      bootstrapState_ = bs_loadedRTLib;
Packit ce96f2
   }
Packit ce96f2
   else {
Packit ce96f2
     if (!pcProc_->addLibrary(dyninstRT_name)) {
Packit ce96f2
       startup_printf("%s[%d]: failed to start loading RT lib\n", FILE__,
Packit ce96f2
		      __LINE__);
Packit ce96f2
       return false;
Packit ce96f2
     }
Packit ce96f2
     bootstrapState_ = bs_loadedRTLib;
Packit ce96f2
     
Packit ce96f2
     // Process the library load (we hope)
Packit ce96f2
     PCEventMuxer::handle(this);
Packit ce96f2
     
Packit ce96f2
     if( runtime_lib.size() == 0 ) {
Packit ce96f2
       startup_printf("%s[%d]: failed to load RT lib\n", FILE__,
Packit ce96f2
		      __LINE__);
Packit ce96f2
       return false;
Packit ce96f2
     }
Packit ce96f2
     
Packit ce96f2
     bootstrapState_ = bs_loadedRTLib;
Packit ce96f2
   }
Packit ce96f2
   int loaded_ok = 0;
Packit ce96f2
   pdvector<int_variable *> vars;
Packit ce96f2
   if (!findVarsByAll("DYNINSThasInitialized", vars)) {
Packit ce96f2
        startup_printf("%s[%d]: no DYNINSThasInitialized variable\n", FILE__, __LINE__);
Packit ce96f2
		return false;
Packit ce96f2
   }
Packit ce96f2
   if (!readDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *)&loaded_ok, false)) {
Packit ce96f2
        startup_printf("%s[%d]: readDataWord failed\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
   }
Packit ce96f2
   if(!loaded_ok)
Packit ce96f2
   {
Packit ce96f2
	   startup_printf("%s[%d]: DYNINSTinit not called automatically\n", FILE__, __LINE__);
Packit ce96f2
   }
Packit ce96f2
   startup_printf("%s[%d]: DYNINSTinit succeeded\n", FILE__, __LINE__);
Packit ce96f2
   return setRTLibInitParams();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// Set up the parameters for DYNINSTinit in the RT lib
Packit ce96f2
bool PCProcess::setRTLibInitParams() {
Packit ce96f2
    startup_printf("%s[%d]: welcome to PCProcess::setRTLibInitParams\n",
Packit ce96f2
            FILE__, __LINE__);
Packit ce96f2
Packit ce96f2
    int pid = P_getpid();
Packit ce96f2
Packit ce96f2
Packit ce96f2
    // Now we write these variables into the following global vrbles
Packit ce96f2
    // in the dyninst library:
Packit ce96f2
    // libdyninstAPI_RT_init_localCause
Packit ce96f2
    // libdyninstAPI_RT_init_localPid
Packit ce96f2
Packit ce96f2
    pdvector<int_variable *> vars;
Packit ce96f2
Packit ce96f2
Packit ce96f2
    if (!findVarsByAll("libdyninstAPI_RT_init_localPid", vars)) {
Packit ce96f2
        if (!findVarsByAll("_libdyninstAPI_RT_init_localPid", vars)) {
Packit ce96f2
            startup_printf("%s[%d]: could not find necessary internal variable\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    assert(vars.size() >= 1);
Packit ce96f2
    if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *)&pid)) {
Packit ce96f2
        startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    vars.clear();
Packit ce96f2
Packit ce96f2
    if (!findVarsByAll("libdyninstAPI_RT_init_maxthreads", vars)) {
Packit ce96f2
        if (!findVarsByAll("_libdyninstAPI_RT_init_maxthreads", vars)) {
Packit ce96f2
            startup_printf("%s[%d]: could not find necessary internal variable\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    unsigned numThreads = MAX_THREADS;
Packit ce96f2
    if( !multithread_capable() ) numThreads = 1;
Packit ce96f2
Packit ce96f2
    assert(vars.size() >= 1);
Packit ce96f2
    if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *) &numThreads)) {
Packit ce96f2
        startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    vars.clear();
Packit ce96f2
Packit ce96f2
    if (!findVarsByAll("libdyninstAPI_RT_init_debug_flag", vars)) {
Packit ce96f2
        if (!findVarsByAll("_libdyninstAPI_RT_init_debug_flag", vars)) {
Packit ce96f2
            startup_printf("%s[%d]: could not find necessary internal variable\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    assert(vars.size() >= 1);
Packit ce96f2
    if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *) &dyn_debug_rtlib)) {
Packit ce96f2
        startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    vars.clear();
Packit ce96f2
    if (dyn_debug_rtlib) {
Packit ce96f2
        fprintf(stderr, "%s[%d]:  set var in RTlib for debug...\n", FILE__, __LINE__);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    int static_mode = 0;
Packit ce96f2
    if (!findVarsByAll("DYNINSTstaticMode", vars)) {
Packit ce96f2
        if (!findVarsByAll("DYNINSTstaticMode", vars)) {
Packit ce96f2
            startup_printf("%s[%d]: could not find necessary internal variable\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    assert(vars.size() >= 1);
Packit ce96f2
    if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *) &static_mode)) {
Packit ce96f2
        startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    vars.clear();
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Packit ce96f2
#if defined(os_vxworks)
Packit ce96f2
bool PCProcess::insertBreakpointAtMain() {
Packit ce96f2
    // We don't need any extra processing of the RTlib.
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
#else
Packit ce96f2
bool PCProcess::insertBreakpointAtMain() {
Packit ce96f2
    if( main_function_ == NULL ) {
Packit ce96f2
        startup_printf("%s[%d]: main function not yet found, cannot insert breakpoint\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    Address addr = main_function_->addr();
Packit ce96f2
Packit ce96f2
    // Create the breakpoint
Packit ce96f2
    mainBrkPt_ = Breakpoint::newBreakpoint();
Packit ce96f2
    if( !pcProc_->addBreakpoint(addr, mainBrkPt_) ) {
Packit ce96f2
        startup_printf("%s[%d]: failed to insert a breakpoint at main entry: 0x%x\n",
Packit ce96f2
                FILE__, __LINE__, addr);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    startup_printf("%s[%d]: added trap to entry of main, address 0x%x\n", 
Packit ce96f2
            FILE__, __LINE__, addr);
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
bool PCProcess::removeBreakpointAtMain() {
Packit ce96f2
    if( main_function_ == NULL || mainBrkPt_ == Breakpoint::ptr() ) {
Packit ce96f2
        startup_printf("%s[%d]: no breakpoint set at main function, not removing\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    Address addr = main_function_->addr();
Packit ce96f2
Packit ce96f2
    if( !pcProc_->rmBreakpoint(addr, mainBrkPt_) ) {
Packit ce96f2
        startup_printf("%s[%d]: failed to remove breakpoint at main entry: 0x%x\n",
Packit ce96f2
                FILE__, __LINE__, addr);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    mainBrkPt_ = Breakpoint::ptr();
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Breakpoint::ptr PCProcess::getBreakpointAtMain() const {
Packit ce96f2
    return mainBrkPt_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// End Runtime library initialization code
Packit ce96f2
Packit ce96f2
bool PCProcess::continueProcess() {
Packit ce96f2
    proccontrol_printf("%s[%d]: Continuing process %d\n", FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    if( !isAttached() || isTerminated() ) {
Packit ce96f2
        bpwarn("Warning: continue attempted on non-attached process\n");
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // If the process is in event handling, the process should not be continued, 
Packit ce96f2
    // the processState_t value will be used after event handling to determine the
Packit ce96f2
    // state of the process
Packit ce96f2
    if( isInEventHandling() ) {
Packit ce96f2
        proccontrol_printf("%s[%d]: process currently in event handling, not continuing\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
Packit ce96f2
            i != threadsByTid_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
        i->second->clearStackwalk();
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return pcProc_->continueProc();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::stopProcess() {
Packit ce96f2
    proccontrol_printf("%s[%d]: Stopping process %d\n", FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    if( !isAttached() || isTerminated() ) {
Packit ce96f2
        bpwarn("Warning: stop attempted on non-attached process\n");
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // See comment in continueProcess about this
Packit ce96f2
    if( isInEventHandling() ) {
Packit ce96f2
        proccontrol_printf("%s[%d]: process currently in event handling, not stopping\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return pcProc_->stopProc();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::terminateProcess() {
Packit ce96f2
    if( isTerminated() ) return true;
Packit ce96f2
Packit ce96f2
    if( !isAttached() ) return false;
Packit ce96f2
Packit ce96f2
    forcedTerminating_ = true;
Packit ce96f2
Packit ce96f2
    proccontrol_printf("%s[%d]: Terminating process %d\n", FILE__, __LINE__, getPid());
Packit ce96f2
    if( !pcProc_->terminate() ) {
Packit ce96f2
        proccontrol_printf("%s[%d]: Failed to terminate process %d\n", FILE__, __LINE__, 
Packit ce96f2
                getPid());
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    PCEventMuxer::handle();
Packit ce96f2
Packit ce96f2
    proccontrol_printf("%s[%d]: finished terminating process %d\n", FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::detachProcess(bool cont = true) {
Packit ce96f2
    if( isTerminated() ) return true;
Packit ce96f2
Packit ce96f2
    if( !isAttached() ) return false;
Packit ce96f2
Packit ce96f2
    if (tracedSyscalls_) {
Packit ce96f2
        // Process needs to be stopped to change instrumentation
Packit ce96f2
        bool needToContinue = false;
Packit ce96f2
        if( !isStopped() ) {
Packit ce96f2
            needToContinue = true;
Packit ce96f2
            if( !stopProcess() ) {
Packit ce96f2
                proccontrol_printf("%s[%d]: failed to stop process for removing syscalls\n",
Packit ce96f2
                        FILE__, __LINE__);
Packit ce96f2
		        return false;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        tracedSyscalls_->removePreFork();
Packit ce96f2
        tracedSyscalls_->removePostFork();
Packit ce96f2
        tracedSyscalls_->removePreExec();
Packit ce96f2
        tracedSyscalls_->removePostExec();
Packit ce96f2
        tracedSyscalls_->removePreExit();
Packit ce96f2
        tracedSyscalls_->removePreLwpExit();
Packit ce96f2
        if (cont) {
Packit ce96f2
            if( needToContinue ) {
Packit ce96f2
                if( !continueProcess() ) {
Packit ce96f2
                    proccontrol_printf("%s[%d]: failed to continue process after removing syscalls\n",
Packit ce96f2
                            FILE__, __LINE__);
Packit ce96f2
                }
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // TODO figure out if ProcControl should care about continuing a process
Packit ce96f2
    // after detach
Packit ce96f2
Packit ce96f2
    // NB: it's possible to get markExited() while handling events for the
Packit ce96f2
    // tracedSyscalls_->remove* calls above, clearing pcProc_.
Packit ce96f2
    if( isTerminated() || pcProc_->detach(!cont) ) {
Packit ce96f2
        attached_ = false;
Packit ce96f2
        return true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return false;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isBootstrapped() const {
Packit ce96f2
    return bootstrapState_ == bs_initialized;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isAttached() const {
Packit ce96f2
    return attached_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isStopped() const {
Packit ce96f2
    if( pcProc_ == Process::ptr() ) return true;
Packit ce96f2
    return pcProc_->allThreadsStopped();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isTerminated() const {
Packit ce96f2
    if( pcProc_ == Process::ptr() ) return true;
Packit ce96f2
    return pcProc_->isTerminated();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::hasExitedNormally() const {
Packit ce96f2
    if( pcProc_ == Process::ptr() ) return true;
Packit ce96f2
    return pcProc_->isExited();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isExecing() const {
Packit ce96f2
    return execing_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::setExecing(bool b) {
Packit ce96f2
    execing_ = b;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isExiting() const {
Packit ce96f2
    return exiting_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::setExiting(bool b) {
Packit ce96f2
    exiting_ = b;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isInEventHandling() const {
Packit ce96f2
    return inEventHandling_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::setInEventHandling(bool b) {
Packit ce96f2
    inEventHandling_ = b;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::hasReportedEvent() const {
Packit ce96f2
    return reportedEvent_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::setReportingEvent(bool b) {
Packit ce96f2
    reportedEvent_ = b;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::markExited() {
Packit ce96f2
    pcProc_.reset();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::writeDebugDataSpace(void *inTracedProcess, u_int amount,
Packit ce96f2
        const void *inSelf)
Packit ce96f2
{
Packit ce96f2
    static unsigned write_no = 0;
Packit ce96f2
Packit ce96f2
    if( !dyn_debug_write ) return;
Packit ce96f2
Packit ce96f2
    write_printf("const unsigned char ");
Packit ce96f2
    switch(getArch()) {
Packit ce96f2
        case Arch_x86:
Packit ce96f2
            write_printf("x86_");
Packit ce96f2
            break;
Packit ce96f2
        case Arch_x86_64:
Packit ce96f2
            write_printf("amd64_");
Packit ce96f2
            break;
Packit ce96f2
        case Arch_ppc32:
Packit ce96f2
        case Arch_ppc64:
Packit ce96f2
            write_printf("power_");
Packit ce96f2
            break;
Packit ce96f2
        default:
Packit ce96f2
            write_printf("unknown_");
Packit ce96f2
            break;
Packit ce96f2
    }
Packit ce96f2
    write_printf("%lx_%d_%u[] = {", inTracedProcess, getPid(), write_no++);
Packit ce96f2
Packit ce96f2
    if( amount > 0 ) {
Packit ce96f2
       const unsigned char *buffer = (const unsigned char *)inSelf;
Packit ce96f2
       for(unsigned i = 0; i < amount-1; ++i) {
Packit ce96f2
           if( i % 10 == 0 ) write_printf("\n");
Packit ce96f2
           write_printf("0x%02hhx, ", buffer[i]);
Packit ce96f2
       }
Packit ce96f2
       write_printf("0x%02hhx", buffer[amount-1]);
Packit ce96f2
    }
Packit ce96f2
    write_printf("\n};\n");
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::writeDataSpace(void *inTracedProcess, u_int amount,
Packit ce96f2
                               const void *inSelf) {
Packit ce96f2
    if( isTerminated() ) {
Packit ce96f2
       cerr << "Writing to terminated process!" << endl;
Packit ce96f2
       return false;
Packit ce96f2
    }
Packit ce96f2
    bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf,
Packit ce96f2
                                       amount);
Packit ce96f2
Packit ce96f2
    if( BPatch_defensiveMode == proc()->getHybridMode() && !result ) {
Packit ce96f2
        // the write may have failed because we've removed write permissions
Packit ce96f2
        // from the page, remove them and try again
Packit ce96f2
Packit ce96f2
        PCMemPerm origRights, rights(true, true, true);
Packit ce96f2
        if (!pcProc_->setMemoryAccessRights((Address)inTracedProcess,
Packit ce96f2
                                            amount, rights, origRights)) {
Packit ce96f2
            cerr << "Fail to set memory permissions!" << endl;
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        /*
Packit ce96f2
        int oldRights = pcProc_->setMemoryAccessRights((Address)inTracedProcess,
Packit ce96f2
                                                       amount,
Packit ce96f2
                                                       PAGE_EXECUTE_READWRITE);
Packit ce96f2
Packit ce96f2
        if( oldRights == PAGE_EXECUTE_READ || oldRights == PAGE_READONLY ) {
Packit ce96f2
        */
Packit ce96f2
Packit ce96f2
        if( origRights.isRX() || origRights.isR() ) {
Packit ce96f2
            result = pcProc_->writeMemory((Address)inTracedProcess, inSelf,
Packit ce96f2
                                          amount);
Packit ce96f2
Packit ce96f2
            /*
Packit ce96f2
            if( pcProc_->setMemoryAccessRights((Address)inTracedProcess,
Packit ce96f2
                                               amount, oldRights) == false ) {
Packit ce96f2
            */
Packit ce96f2
Packit ce96f2
            PCMemPerm tmpRights;
Packit ce96f2
            if( !pcProc_->setMemoryAccessRights((Address)inTracedProcess,
Packit ce96f2
                                                amount, origRights, tmpRights)) {
Packit ce96f2
                result = false;
Packit ce96f2
            }
Packit ce96f2
        } else {
Packit ce96f2
            result = false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
Packit ce96f2
Packit ce96f2
    return result;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::writeDataWord(void *inTracedProcess,
Packit ce96f2
                   u_int amount, const void *inSelf) 
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
Packit ce96f2
    // XXX ProcControlAPI should support word writes in the future
Packit ce96f2
    bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf, amount);
Packit ce96f2
    if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
Packit ce96f2
    return result;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::readDataSpace(const void *inTracedProcess, u_int amount,
Packit ce96f2
                   void *inSelf, bool displayErrMsg)
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
Packit ce96f2
    bool result = pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
Packit ce96f2
    if( !result && displayErrMsg ) {
Packit ce96f2
        stringstream msg;
Packit ce96f2
        msg << "System error: unable to read " << amount << "@" 
Packit ce96f2
            << Address_str((Address)inTracedProcess) << " from process data space: "
Packit ce96f2
            << getLastErrorMsg() << "(pid = " << getPid() << ")";
Packit ce96f2
       showErrorCallback(38, msg.str()); 
Packit ce96f2
    }
Packit ce96f2
    return result;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::readDataWord(const void *inTracedProcess, u_int amount,
Packit ce96f2
                  void *inSelf, bool displayErrMsg)
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
Packit ce96f2
    // XXX see writeDataWord above
Packit ce96f2
    bool result = pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
Packit ce96f2
    if( !result && displayErrMsg ) {
Packit ce96f2
        stringstream msg;
Packit ce96f2
        msg << "System error: unable to read " << amount << "@" 
Packit ce96f2
            << Address_str((Address)inTracedProcess) << " from process data space: "
Packit ce96f2
            << getLastErrorMsg() << "(pid = " << getPid() << ")";
Packit ce96f2
       showErrorCallback(38, msg.str());
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return result;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::writeTextSpace(void *inTracedProcess, u_int amount, const void *inSelf)
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
    bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf, amount);
Packit ce96f2
Packit ce96f2
    if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
Packit ce96f2
Packit ce96f2
    return result;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::writeTextWord(void *inTracedProcess, u_int amount, const void *inSelf)
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
Packit ce96f2
    // XXX see writeDataWord above
Packit ce96f2
    bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf, amount);
Packit ce96f2
Packit ce96f2
    if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
Packit ce96f2
Packit ce96f2
    return result;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::readTextSpace(const void *inTracedProcess, u_int amount,
Packit ce96f2
                   void *inSelf)
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
Packit ce96f2
    return pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::readTextWord(const void *inTracedProcess, u_int amount,
Packit ce96f2
                  void *inSelf)
Packit ce96f2
{
Packit ce96f2
    if( isTerminated() ) return false;
Packit ce96f2
Packit ce96f2
    // XXX see writeDataWord above
Packit ce96f2
    return pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCThread *PCProcess::getInitialThread() const {
Packit ce96f2
    return initialThread_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCThread *PCProcess::getThread(dynthread_t tid) const {
Packit ce96f2
    map<dynthread_t, PCThread *>::const_iterator findIter;
Packit ce96f2
    findIter = threadsByTid_.find(tid);
Packit ce96f2
    if( findIter == threadsByTid_.end() ) {
Packit ce96f2
        return NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return findIter->second;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::removeThread(dynthread_t tid) {
Packit ce96f2
    map<dynthread_t, PCThread *>::iterator result;
Packit ce96f2
    result = threadsByTid_.find(tid);
Packit ce96f2
Packit ce96f2
    if( result == threadsByTid_.end() ) return false;
Packit ce96f2
Packit ce96f2
    PCThread *toDelete = result->second;
Packit ce96f2
Packit ce96f2
    //if( !unregisterThread(toDelete) ) return false;
Packit ce96f2
Packit ce96f2
    threadsByTid_.erase(result);
Packit ce96f2
Packit ce96f2
    if( toDelete == initialThread_ ) {
Packit ce96f2
        initialThread_ = NULL;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    toDelete->markExited();
Packit ce96f2
Packit ce96f2
    // Note: don't delete the thread here, the BPatch_thread takes care of it
Packit ce96f2
    proccontrol_printf("%s[%d]: removed thread %lu from process %d\n",
Packit ce96f2
            FILE__, __LINE__, toDelete->getLWP(), getPid());
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
extern Address getVarAddr(PCProcess *proc, std::string str);
Packit ce96f2
Packit ce96f2
#if 0
Packit ce96f2
bool PCProcess::registerThread(PCThread *thread) {
Packit ce96f2
  
Packit ce96f2
   Address tid = (Address) thread->getTid();
Packit ce96f2
   Address index = thread->getIndex();
Packit ce96f2
   
Packit ce96f2
   Address tmp = 0;
Packit ce96f2
   unsigned ptrsize = getAddressWidth();
Packit ce96f2
Packit ce96f2
   if (tid == (Address) -1) return true;
Packit ce96f2
   if (index == (Address) -1) return true;
Packit ce96f2
Packit ce96f2
   if (!initializeRegisterThread()) {
Packit ce96f2
      startup_printf("%s[%d]: initializeRegisterThread failed\n",
Packit ce96f2
                     FILE__, __LINE__);
Packit ce96f2
	   
Packit ce96f2
	   return false;
Packit ce96f2
   }
Packit ce96f2
   // Must match the "hash" algorithm used in the RT lib
Packit ce96f2
   int working = (tid % thread_hash_size);
Packit ce96f2
   while(1) {
Packit ce96f2
      tmp = 0;
Packit ce96f2
      if (!readDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &tmp, false)) {
Packit ce96f2
         startup_printf("%s[%d]: Failed to read index slot, base 0x%lx, active 0x%lx\n", FILE__, __LINE__,
Packit ce96f2
                        thread_hash_indices, thread_hash_indices + (working * ptrsize));
Packit ce96f2
         return false;
Packit ce96f2
      }
Packit ce96f2
      startup_printf("%s[%d]: value of tid in slot %p is 0x%lx\n",
Packit ce96f2
                     FILE__, __LINE__, thread_hash_indices + (working * ptrsize), tmp);
Packit ce96f2
      if (ptrsize == 4 && tmp == 0xffffffff) {
Packit ce96f2
         int index_int = (int) index;
Packit ce96f2
         int tid_int = (int) tid;
Packit ce96f2
         startup_printf("%s[%d]: writing %d to %p and 0x%x to %p\n",
Packit ce96f2
                        FILE__, __LINE__, index_int, thread_hash_indices + (working * ptrsize),
Packit ce96f2
                        tid_int, thread_hash_tids + (working * ptrsize));
Packit ce96f2
         writeDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &index_int);
Packit ce96f2
         writeDataWord(( void *)(thread_hash_tids + (working * ptrsize)), ptrsize, &tid_int);
Packit ce96f2
         break;
Packit ce96f2
      }
Packit ce96f2
      else if (ptrsize == 8 && tmp == (Address)-1)  {
Packit ce96f2
         writeDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &index);
Packit ce96f2
         writeDataWord(( void *)(thread_hash_tids + (working * ptrsize)), ptrsize, &tid;;
Packit ce96f2
         break;
Packit ce96f2
      }
Packit ce96f2
      working++;
Packit ce96f2
      if (working == thread_hash_size) working = 0;
Packit ce96f2
      if (working == (int) (tid % thread_hash_size)) {
Packit ce96f2
         startup_printf("%s[%d]: Failed to find empty tid slot\n", FILE__, __LINE__);
Packit ce96f2
         return false;
Packit ce96f2
      }
Packit ce96f2
   }
Packit ce96f2
   return true;
Packit ce96f2
}
Packit ce96f2
bool PCProcess::unregisterThread(PCThread *thread) {	
Packit ce96f2
   return true;
Packit ce96f2
   Address tid = (Address) thread->getTid();
Packit ce96f2
   Address index = thread->getIndex();
Packit ce96f2
   Address tmp = 0;
Packit ce96f2
   
Packit ce96f2
   unsigned ptrsize = getAddressWidth();
Packit ce96f2
   if (tid == (Address) -1) return true;
Packit ce96f2
   if (index == (Address) -1) return true;
Packit ce96f2
Packit ce96f2
   initializeRegisterThread();
Packit ce96f2
Packit ce96f2
   // Must match the "hash" algorithm used in the RT lib
Packit ce96f2
   int working = tid % thread_hash_size;
Packit ce96f2
   while(1) {
Packit ce96f2
      tmp = 0;
Packit ce96f2
      if (!readDataWord((void *)(thread_hash_tids + (working * ptrsize)), ptrsize, &tmp, false)) return false;
Packit ce96f2
      if (tmp == tid) {
Packit ce96f2
         // Zero it out
Packit ce96f2
         tmp = (Address) -1;
Packit ce96f2
         writeDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &tmp);
Packit ce96f2
         break;
Packit ce96f2
      }
Packit ce96f2
      working++;
Packit ce96f2
      if (working == thread_hash_size) working = 0;
Packit ce96f2
      if (working == (int) (tid % thread_hash_size)) return false;
Packit ce96f2
   }
Packit ce96f2
   return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::initializeRegisterThread() {
Packit ce96f2
//   if (thread_hash_tids) return true;
Packit ce96f2
Packit ce96f2
   unsigned ptrsize = getAddressWidth();
Packit ce96f2
   
Packit ce96f2
   Address tidPtr = getVarAddr(this, "DYNINST_thread_hash_tids");
Packit ce96f2
   if (!tidPtr) return false;
Packit ce96f2
   Address indexPtr = getVarAddr(this, "DYNINST_thread_hash_indices");
Packit ce96f2
   if (!indexPtr) return false;
Packit ce96f2
   Address sizePtr = getVarAddr(this, "DYNINST_thread_hash_size");
Packit ce96f2
   if (!sizePtr) return false;
Packit ce96f2
   
Packit ce96f2
   if (!readDataWord((const void *)tidPtr, ptrsize, &thread_hash_tids, false)) return false;
Packit ce96f2
Packit ce96f2
   if (!readDataWord((const void *)indexPtr, ptrsize, &thread_hash_indices, false)) return false;
Packit ce96f2
Packit ce96f2
   if (!readDataWord((const void *)sizePtr, sizeof(int), &thread_hash_size, false)) return false;
Packit ce96f2
Packit ce96f2
   return true;
Packit ce96f2
}
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
Packit ce96f2
void PCProcess::addThread(PCThread *thread) {
Packit ce96f2
    pair<map<dynthread_t, PCThread *>::iterator, bool> result;
Packit ce96f2
    result = threadsByTid_.insert(make_pair(thread->getTid(), thread));
Packit ce96f2
Packit ce96f2
    assert( result.second && "Thread already in collection of threads" );
Packit ce96f2
    proccontrol_printf("%s[%d]: added thread %lu to process %d\n",
Packit ce96f2
            FILE__, __LINE__, thread->getLWP(), getPid());
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::getThreads(vector<PCThread* > &threads) const {
Packit ce96f2
    for(map<dynthread_t, PCThread *>::const_iterator i = threadsByTid_.begin();
Packit ce96f2
            i != threadsByTid_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
        threads.push_back(i->second);
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::wasRunningWhenAttached() const {
Packit ce96f2
    return runningWhenAttached_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::wasCreatedViaAttach() const {
Packit ce96f2
    return createdViaAttach_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::wasCreatedViaFork() const {
Packit ce96f2
    return parent_ != NULL;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
unsigned PCProcess::getMemoryPageSize() const {
Packit ce96f2
   assert(pcProc_);
Packit ce96f2
   return pcProc_->getMemoryPageSize();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
int PCProcess::getPid() const {
Packit ce96f2
    return savedPid_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
int PCProcess::incrementThreadIndex() {
Packit ce96f2
    int ret = curThreadIndex_;
Packit ce96f2
    curThreadIndex_++;
Packit ce96f2
    return ret;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
unsigned PCProcess::getAddressWidth() const {
Packit ce96f2
    if( mapped_objects.size() > 0 ) {
Packit ce96f2
        return mapped_objects[0]->parse_img()->codeObject()->cs()->getAddressWidth();
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // We can call this before we've attached...best effort guess
Packit ce96f2
    return sizeof(Address);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCEventHandler * PCProcess::getPCEventHandler() const {
Packit ce96f2
    return eventHandler_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::walkStacks(pdvector<pdvector<Frame> > &stackWalks) {
Packit ce96f2
    bool needToContinue = false;
Packit ce96f2
    bool retval = true;
Packit ce96f2
Packit ce96f2
    // sanity check
Packit ce96f2
	if( stackwalker_ == NULL ) return false;
Packit ce96f2
Packit ce96f2
    // Process needs to be stopped before doing a stackwalk
Packit ce96f2
    if( !isStopped() ) {
Packit ce96f2
        needToContinue = true;
Packit ce96f2
        if( !stopProcess() ) {
Packit ce96f2
            proccontrol_printf("%s[%d]: failed to stop process for stackwalking\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
Packit ce96f2
           i != threadsByTid_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
        PCThread *curThr = i->second;
Packit ce96f2
Packit ce96f2
        pdvector<Frame> stackWalk;
Packit ce96f2
        if( !curThr->walkStack(stackWalk) ) {
Packit ce96f2
            retval = false;
Packit ce96f2
            proccontrol_printf("%s[%d]: failed to walk stack for thread 0x%lx(%d)\n",
Packit ce96f2
                    FILE__, __LINE__,
Packit ce96f2
                    curThr->getTid(), curThr->getLWP());
Packit ce96f2
        }else{
Packit ce96f2
            stackWalks.push_back(stackWalk);
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    if( needToContinue ) {
Packit ce96f2
        if( !continueProcess() ) {
Packit ce96f2
            proccontrol_printf("%s[%d]: failed to continue process after performing stackwalking\n",
Packit ce96f2
                    FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return retval;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// Return a vector (possibly with one object) of active frames in the process
Packit ce96f2
bool PCProcess::getAllActiveFrames(pdvector<Frame> &activeFrames) {
Packit ce96f2
    Frame active;
Packit ce96f2
    if( threadsByTid_.size() == 0 ) return false;
Packit ce96f2
Packit ce96f2
    for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
Packit ce96f2
            i != threadsByTid_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
        Frame active = i->second->getActiveFrame();
Packit ce96f2
        if( active == Frame() ) return false;
Packit ce96f2
        activeFrames.push_back(active);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
//
Packit ce96f2
// dynamic inferior heap stuff
Packit ce96f2
//
Packit ce96f2
Packit ce96f2
#if defined(os_vxworks)
Packit ce96f2
#include "vxworks.h"
Packit ce96f2
#define HEAP_DYN_BUF_SIZE (0x4000)
Packit ce96f2
#else
Packit ce96f2
#define HEAP_DYN_BUF_SIZE (0x100000)
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
static const Address ADDRESS_LO = ((Address)0x10000);
Packit ce96f2
static const Address ADDRESS_HI = ((Address)~((Address)0));
Packit ce96f2
Packit ce96f2
Address PCProcess::inferiorMalloc(unsigned size, inferiorHeapType type,
Packit ce96f2
                                  Address near_, bool *err) 
Packit ce96f2
{
Packit ce96f2
   if(bootstrapState_ <= bs_readyToLoadRTLib) {
Packit ce96f2
      return 0;
Packit ce96f2
   }
Packit ce96f2
Packit ce96f2
    enum MallocAttempt {
Packit ce96f2
        AsIs = 0,
Packit ce96f2
        DeferredFree = 1, // compact free blocks
Packit ce96f2
        NewSegment1MBConstrained = 2, // allocate new segment (1 MB, constrained)
Packit ce96f2
        NewSegmentSizedConstrained = 3, // allocate new segment (sized, constrained)
Packit ce96f2
        RemoveRangeConstraints = 4,
Packit ce96f2
        NewSegment1MBUnconstrained = 5,
Packit ce96f2
        NewSegmentSizedUnconstrained = 6,
Packit ce96f2
        DeferredFreeAgain = 7 // why again?
Packit ce96f2
    };
Packit ce96f2
Packit ce96f2
    Address ret = 0;
Packit ce96f2
    if (err) *err = false;
Packit ce96f2
Packit ce96f2
    if( size <= 0 ) {
Packit ce96f2
        infmalloc_printf("%s[%d]: inferior malloc cannot be <= 0\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        if( err ) *err = true;
Packit ce96f2
        return 0;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // allocation range
Packit ce96f2
    Address lo = ADDRESS_LO; // Should get reset to a more reasonable value
Packit ce96f2
    Address hi = ADDRESS_HI; // Should get reset to a more reasonable value
Packit ce96f2
Packit ce96f2
    //#if defined(cap_dynamic_heap)
Packit ce96f2
    inferiorMallocAlign(size); // align size
Packit ce96f2
    // Set the lo/hi constraints (if necessary)
Packit ce96f2
    inferiorMallocConstraints(near_, lo, hi, type);
Packit ce96f2
    //#else
Packit ce96f2
    /* align to cache line size (32 bytes on SPARC) */
Packit ce96f2
    //size = (size + 0x1f) & ~0x1f;
Packit ce96f2
    //#endif
Packit ce96f2
Packit ce96f2
    infmalloc_printf("%s[%d]: inferiorMalloc entered; size %d, type %d, near 0x%lx (0x%lx to 0x%lx)\n",
Packit ce96f2
                     FILE__, __LINE__, size, type, near_, lo, hi);
Packit ce96f2
Packit ce96f2
    // find free memory block (multiple attempts)
Packit ce96f2
    int freeIndex = -1;
Packit ce96f2
    int ntry = 0;
Packit ce96f2
    for (ntry = 0; freeIndex == -1; ntry++) {
Packit ce96f2
        switch(ntry) {
Packit ce96f2
        case AsIs: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (1) AsIs\n", FILE__, __LINE__);
Packit ce96f2
            break;
Packit ce96f2
	    //#if defined(cap_dynamic_heap)
Packit ce96f2
        case DeferredFree: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (2) garbage collecting and compacting\n",
Packit ce96f2
                             FILE__, __LINE__);
Packit ce96f2
            inferiorFreeCompact();
Packit ce96f2
            break;
Packit ce96f2
        case NewSegment1MBConstrained: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (3) inferiorMallocDynamic "
Packit ce96f2
                    "for %d (0x%x) bytes between 0x%lx - 0x%lx\n", FILE__, __LINE__,
Packit ce96f2
                    HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
Packit ce96f2
            inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
Packit ce96f2
            break;
Packit ce96f2
        case NewSegmentSizedConstrained: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (4) inferiorMallocDynamic "
Packit ce96f2
                    "for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
Packit ce96f2
                             FILE__, __LINE__, size, size, lo, hi);
Packit ce96f2
            inferiorMallocDynamic(size, lo, hi);
Packit ce96f2
            break;
Packit ce96f2
        case RemoveRangeConstraints: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (5) inferiorMalloc: removing range constraints\n",
Packit ce96f2
                             FILE__, __LINE__);
Packit ce96f2
            lo = ADDRESS_LO;
Packit ce96f2
            hi = ADDRESS_HI;
Packit ce96f2
            if (err) {
Packit ce96f2
                infmalloc_printf("%s[%d]: error in inferiorMalloc\n", FILE__, __LINE__);
Packit ce96f2
                *err = true;
Packit ce96f2
            }
Packit ce96f2
            break;
Packit ce96f2
        case NewSegment1MBUnconstrained: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (6) inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
Packit ce96f2
                             FILE__, __LINE__, HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
Packit ce96f2
            inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
Packit ce96f2
            break;
Packit ce96f2
        case NewSegmentSizedUnconstrained: 
Packit ce96f2
            infmalloc_printf("%s[%d]:  (7) inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
Packit ce96f2
                             FILE__, __LINE__, size, size, lo, hi);
Packit ce96f2
            inferiorMallocDynamic(size, lo, hi);
Packit ce96f2
            break;
Packit ce96f2
        case DeferredFreeAgain: 
Packit ce96f2
            infmalloc_printf("%s[%d]: inferiorMalloc: recompacting\n", FILE__, __LINE__);
Packit ce96f2
            inferiorFreeCompact();
Packit ce96f2
            break;
Packit ce96f2
	    //#else /* !(cap_dynamic_heap) */
Packit ce96f2
	    //case DeferredFree: // deferred free, compact free blocks
Packit ce96f2
            //inferiorFreeCompact();
Packit ce96f2
            //break;
Packit ce96f2
	    //#endif /* cap_dynamic_heap */
Packit ce96f2
Packit ce96f2
        default: // error - out of memory
Packit ce96f2
            infmalloc_printf("%s[%d]: failed to allocate memory\n", FILE__, __LINE__);
Packit ce96f2
            if( err ) *err = true;
Packit ce96f2
            return 0;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        ret = inferiorMallocInternal(size, lo, hi, type);
Packit ce96f2
        if (ret) break;
Packit ce96f2
    }
Packit ce96f2
    infmalloc_printf("%s[%d]: inferiorMalloc, returning address 0x%lx\n", FILE__, __LINE__, ret);
Packit ce96f2
    return ret;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::inferiorFree(Dyninst::Address item) {
Packit ce96f2
    inferiorFreeInternal(item);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::inferiorRealloc(Dyninst::Address item, unsigned int newSize) {
Packit ce96f2
	if(bootstrapState_ <= bs_readyToLoadRTLib) {
Packit ce96f2
      return true;
Packit ce96f2
   }
Packit ce96f2
   return inferiorReallocInternal(item, newSize);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
static
Packit ce96f2
void alignUp(int &val, int align) {
Packit ce96f2
    assert(val >= 0);
Packit ce96f2
    assert(align >= 0);
Packit ce96f2
Packit ce96f2
    if (val % align != 0) {
Packit ce96f2
        val = ((val / align) + 1) * align;
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::inferiorMallocDynamic(int size, Address lo, Address hi) {
Packit ce96f2
    const int MallocFailed = 0;
Packit ce96f2
    const int UnalignedBuffer = -1;
Packit ce96f2
Packit ce96f2
    infmalloc_printf("%s[%d]: entering inferiorMallocDynamic\n", FILE__, __LINE__);
Packit ce96f2
Packit ce96f2
    // word-align buffer size
Packit ce96f2
    // (see "DYNINSTheap_align" in rtinst/src/RTheap-<os>.c)
Packit ce96f2
    alignUp(size, 4);
Packit ce96f2
    // build AstNode for "DYNINSTos_malloc" call
Packit ce96f2
    std::string callee = "DYNINSTos_malloc";
Packit ce96f2
    pdvector<AstNodePtr> args(3);
Packit ce96f2
    args[0] = AstNode::operandNode(AstNode::Constant, (void *)(Address)size);
Packit ce96f2
    args[1] = AstNode::operandNode(AstNode::Constant, (void *)lo);
Packit ce96f2
    args[2] = AstNode::operandNode(AstNode::Constant, (void *)hi);
Packit ce96f2
    AstNodePtr code = AstNode::funcCallNode(callee, args);
Packit ce96f2
Packit ce96f2
    // issue RPC and wait for result
Packit ce96f2
    bool wasRunning = !isStopped();
Packit ce96f2
Packit ce96f2
    proccontrol_printf("%s[%d]: running inferiorMalloc via iRPC on process %d\n",
Packit ce96f2
            FILE__, __LINE__, getPid());
Packit ce96f2
Packit ce96f2
    Address result = 0;
Packit ce96f2
    if( !postIRPC(code,
Packit ce96f2
                  NULL, // only care about the result
Packit ce96f2
                  wasRunning, // run when finished?
Packit ce96f2
                  NULL, // no specific thread
Packit ce96f2
                  true, // wait for completion
Packit ce96f2
                  (void **)&result,
Packit ce96f2
                  false, // internal iRPC
Packit ce96f2
                  true) ) // is a memory allocation RPC
Packit ce96f2
    {
Packit ce96f2
        infmalloc_printf("%s[%d]: failed to post iRPC for inferior malloc\n",
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    proccontrol_printf("%s[%d]: inferiorMalloc via iRPC returned 0x%lx\n",
Packit ce96f2
            FILE__, __LINE__, result);
Packit ce96f2
Packit ce96f2
    switch ((int)result) {
Packit ce96f2
        case MallocFailed:
Packit ce96f2
            infmalloc_printf("%s[%d]: DYNINSTos_malloc() failed\n",
Packit ce96f2
                               FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        case UnalignedBuffer:
Packit ce96f2
            infmalloc_printf("%s[%d]: DYNINSTos_malloc(): unaligned buffer size\n",
Packit ce96f2
                               FILE__, __LINE__);
Packit ce96f2
            return false;
Packit ce96f2
        default:
Packit ce96f2
            // add new segment to buffer pool
Packit ce96f2
            heapItem *h = new heapItem(result, size, getDynamicHeapType(),
Packit ce96f2
                    true, HEAPfree);
Packit ce96f2
            addHeap(h);
Packit ce96f2
            break;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// A copy of the BPatch-level instrumentation installer
Packit ce96f2
void PCProcess::installInstrRequests(const pdvector<instMapping*> &requests) {
Packit ce96f2
    if (requests.size() == 0) {
Packit ce96f2
        return;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Instrumentation is now generated on a per-function basis, while
Packit ce96f2
    // the requests are per-inst, not per-function. So 
Packit ce96f2
    // accumulate functions, then generate afterwards. 
Packit ce96f2
Packit ce96f2
    vector<func_instance *> instrumentedFuncs;
Packit ce96f2
Packit ce96f2
    for (unsigned lcv=0; lcv < requests.size(); lcv++) {
Packit ce96f2
      inst_printf("%s[%d]: handling request %d of %d\n", FILE__, __LINE__, lcv+1, requests.size());
Packit ce96f2
Packit ce96f2
        instMapping *req = requests[lcv];
Packit ce96f2
        pdvector<miniTramp *> minis;
Packit ce96f2
        
Packit ce96f2
        if(!multithread_capable() && req->is_MTonly())
Packit ce96f2
            continue;
Packit ce96f2
        
Packit ce96f2
        pdvector<func_instance *> matchingFuncs;
Packit ce96f2
        
Packit ce96f2
        if (!findFuncsByAll(req->func, matchingFuncs, req->lib)) {
Packit ce96f2
            inst_printf("%s[%d]: failed to find any functions matching %s (lib %s), returning failure from installInstrRequests\n", FILE__, __LINE__, req->func.c_str(), req->lib.c_str());
Packit ce96f2
            return;
Packit ce96f2
        }
Packit ce96f2
        else {
Packit ce96f2
            inst_printf("%s[%d]: found %d functions matching %s (lib %s), instrumenting...\n",
Packit ce96f2
                        FILE__, __LINE__, matchingFuncs.size(), req->func.c_str(), req->lib.c_str());
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        for (unsigned funcIter = 0; funcIter < matchingFuncs.size(); funcIter++) {
Packit ce96f2
           func_instance *func = matchingFuncs[funcIter];
Packit ce96f2
           if (!func) {
Packit ce96f2
              inst_printf("%s[%d]: null int_func detected\n",
Packit ce96f2
                          FILE__,__LINE__);
Packit ce96f2
              continue;  // probably should have a flag telling us whether errors
Packit ce96f2
           }
Packit ce96f2
Packit ce96f2
	   inst_printf("%s[%d]: Instrumenting %s at 0x%lx, offset 0x%lx in %s\n",
Packit ce96f2
		       FILE__, __LINE__, 
Packit ce96f2
		       func->symTabName().c_str(),
Packit ce96f2
		       func->addr(),
Packit ce96f2
		       func->addr() - func->obj()->codeBase(),
Packit ce96f2
		       func->obj()->fullName().c_str());
Packit ce96f2
            
Packit ce96f2
           // should be silently handled or not
Packit ce96f2
           AstNodePtr ast;
Packit ce96f2
           if ((req->where & FUNC_ARG) && req->args.size()>0) {
Packit ce96f2
              ast = AstNode::funcCallNode(req->inst, 
Packit ce96f2
                                          req->args,
Packit ce96f2
                                          this);
Packit ce96f2
           }
Packit ce96f2
           else {
Packit ce96f2
              pdvector<AstNodePtr> def_args;
Packit ce96f2
              def_args.push_back(AstNode::operandNode(AstNode::Constant,
Packit ce96f2
                                                      (void *)0));
Packit ce96f2
              ast = AstNode::funcCallNode(req->inst,
Packit ce96f2
                                          def_args);
Packit ce96f2
           }
Packit ce96f2
           // We mask to strip off the FUNC_ARG bit...
Packit ce96f2
           std::vector<Point *> points;
Packit ce96f2
           switch ( ( req->where & 0x7) ) {
Packit ce96f2
              case FUNC_EXIT:
Packit ce96f2
                 mgr()->findPoints(Dyninst::PatchAPI::Scope(func),
Packit ce96f2
                                   Point::FuncExit,
Packit ce96f2
                                   std::back_inserter(points));
Packit ce96f2
                 break;
Packit ce96f2
              case FUNC_ENTRY:
Packit ce96f2
                 mgr()->findPoints(Dyninst::PatchAPI::Scope(func),
Packit ce96f2
                                   Point::FuncEntry,
Packit ce96f2
                                   std::back_inserter(points));
Packit ce96f2
                 break;
Packit ce96f2
              case FUNC_CALL:
Packit ce96f2
                 mgr()->findPoints(Dyninst::PatchAPI::Scope(func),
Packit ce96f2
                                   Point::PreCall,
Packit ce96f2
                                   std::back_inserter(points));
Packit ce96f2
                 break;
Packit ce96f2
              default:
Packit ce96f2
                 fprintf(stderr, "Unknown where: %d\n",
Packit ce96f2
                         req->where);
Packit ce96f2
                 break;
Packit ce96f2
           } // switch
Packit ce96f2
	   inst_printf("%s[%d]: found %d points to instrument\n", FILE__, __LINE__, points.size());
Packit ce96f2
           for (std::vector<Point *>::iterator iter = points.begin();
Packit ce96f2
                iter != points.end(); ++iter) {
Packit ce96f2
              Dyninst::PatchAPI::Instance::Ptr inst = (req->order == orderFirstAtPoint) ? 
Packit ce96f2
                 (*iter)->pushFront(ast) :
Packit ce96f2
                 (*iter)->pushBack(ast);
Packit ce96f2
              if (inst) {
Packit ce96f2
                 if (!req->useTrampGuard) inst->disableRecursiveGuard();
Packit ce96f2
                 req->instances.push_back(inst);
Packit ce96f2
              }
Packit ce96f2
              else {
Packit ce96f2
                 fprintf(stderr, "%s[%d]:  failed to addInst here\n", FILE__, __LINE__);
Packit ce96f2
              }
Packit ce96f2
           }        } // matchingFuncs        
Packit ce96f2
        
Packit ce96f2
    } // requests
Packit ce96f2
    relocate();
Packit ce96f2
    return;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
static const unsigned MAX_IRPC_SIZE = 0x100000;
Packit ce96f2
Packit ce96f2
Packit ce96f2
bool PCProcess::postIRPC(void* buffer, int size, void* userData, bool runProcessWhenDone,
Packit ce96f2
                         PCThread* thread, bool synchronous, void** result,
Packit ce96f2
                         bool userRPC, bool isMemAlloc, Address addr)
Packit ce96f2
{
Packit ce96f2
   return postIRPC_internal(buffer,
Packit ce96f2
                            size,
Packit ce96f2
                            size,
Packit ce96f2
                            REG_NULL,
Packit ce96f2
                            addr,
Packit ce96f2
                            userData,
Packit ce96f2
                            runProcessWhenDone,
Packit ce96f2
                            thread,
Packit ce96f2
                            synchronous,
Packit ce96f2
                            userRPC,
Packit ce96f2
                            isMemAlloc,
Packit ce96f2
                            result);    
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::postIRPC(AstNodePtr action, void *userData, 
Packit ce96f2
                         bool runProcessWhenDone, PCThread *thread, bool synchronous,
Packit ce96f2
                         void **result, bool userRPC, bool isMemAlloc, Address addr)
Packit ce96f2
{   
Packit ce96f2
   // Generate the code for the iRPC
Packit ce96f2
   codeGen irpcBuf(MAX_IRPC_SIZE);
Packit ce96f2
   irpcBuf.setAddrSpace(this);
Packit ce96f2
   irpcBuf.setRegisterSpace(registerSpace::irpcRegSpace(proc()));
Packit ce96f2
   irpcBuf.beginTrackRegDefs();
Packit ce96f2
   irpcBuf.setThread(thread);
Packit ce96f2
   
Packit ce96f2
#if defined(bug_syscall_changepc_rewind)
Packit ce96f2
   // Reported by SGI, during attach to a process in a system call:
Packit ce96f2
   
Packit ce96f2
   // Insert eight NOP instructions before the actual call to dlopen(). Loading
Packit ce96f2
   // the runtime library when the mutatee was in a system call will sometimes
Packit ce96f2
   // cause the process to (on IA32 anyway) execute the instruction four bytes
Packit ce96f2
   // PREVIOUS to the PC we actually set here. No idea why. Prepending the
Packit ce96f2
   // actual dlopen() call with eight NOP instructions insures this doesn't
Packit ce96f2
   // really matter. Eight was selected rather than four because I don't know
Packit ce96f2
   // if x86-64 does the same thing (and jumps eight bytes instead of four).
Packit ce96f2
   
Packit ce96f2
   // We will put in <addr width> rather than always 8; this will be 4 on x86 and
Packit ce96f2
   // 32-bit AMD64, and 8 on 64-bit AMD64.
Packit ce96f2
   irpcBuf.fill(proc()->getAddressWidth(), codeGen::cgNOP);
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
   irpcTramp_->setIRPCAST(action);
Packit ce96f2
   
Packit ce96f2
   // Create a stack frame for the RPC
Packit ce96f2
   if( !irpcTramp_->generateSaves(irpcBuf, irpcBuf.rs()) ) {
Packit ce96f2
      proccontrol_printf("%s[%d]: failed to generate saves via baseTramp\n",
Packit ce96f2
                         FILE__, __LINE__);
Packit ce96f2
      return false;
Packit ce96f2
   }
Packit ce96f2
   
Packit ce96f2
   Register resultReg = REG_NULL;
Packit ce96f2
   if( !action->generateCode(irpcBuf, false, resultReg) ) {
Packit ce96f2
      proccontrol_printf("%s[%d]: failed to generate code from AST\n",
Packit ce96f2
                         FILE__, __LINE__);
Packit ce96f2
      return false;
Packit ce96f2
   }
Packit ce96f2
Packit ce96f2
    // Note: we should not do a corresponding baseTramp restore here:
Packit ce96f2
    // 1) It isn't necessary because ProcControl will restore the
Packit ce96f2
    //    registers
Packit ce96f2
    // 2) We need to be able to read registers to get the result of the iRPC
Packit ce96f2
    //    If we restore, we can't do that
Packit ce96f2
Packit ce96f2
    // Emit the trailer for the iRPC
Packit ce96f2
Packit ce96f2
    // breakOffset: where the irpc ends
Packit ce96f2
    unsigned breakOffset = irpcBuf.used();
Packit ce96f2
    insnCodeGen::generateTrap(irpcBuf);
Packit ce96f2
    insnCodeGen::generateTrap(irpcBuf);
Packit ce96f2
Packit ce96f2
    irpcBuf.endTrackRegDefs();
Packit ce96f2
Packit ce96f2
    //#sasha printing code patch for DYNINSTos_malloc
Packit ce96f2
    //cerr << "BUFFER for IRPC" << endl;
Packit ce96f2
    //cerr << irpcBuf.format() << endl;
Packit ce96f2
Packit ce96f2
    return postIRPC_internal(irpcBuf.start_ptr(),
Packit ce96f2
                             irpcBuf.used(),
Packit ce96f2
                             breakOffset,
Packit ce96f2
                             resultReg,
Packit ce96f2
                             addr,
Packit ce96f2
                             userData,
Packit ce96f2
                             runProcessWhenDone,
Packit ce96f2
                             thread,
Packit ce96f2
                             synchronous,
Packit ce96f2
                             userRPC,
Packit ce96f2
                             isMemAlloc,
Packit ce96f2
                             result);    
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// DEBUG
Packit ce96f2
#include "instructionAPI/h/InstructionDecoder.h"
Packit ce96f2
Packit ce96f2
bool PCProcess::postIRPC_internal(void *buf,
Packit ce96f2
                                  unsigned size,
Packit ce96f2
                                  unsigned breakOffset,
Packit ce96f2
                                  Register resultReg,
Packit ce96f2
                                  Address addr,
Packit ce96f2
                                  void *userData,
Packit ce96f2
                                  bool runProcessWhenDone,
Packit ce96f2
                                  PCThread *thread,
Packit ce96f2
                                  bool synchronous,
Packit ce96f2
                                  bool userRPC,
Packit ce96f2
                                  bool isMemAlloc,
Packit ce96f2
                                  void **result) {
Packit ce96f2
   if( isTerminated() ) {
Packit ce96f2
      proccontrol_printf("%s[%d]: cannot post RPC to exited or terminated process %d\n",
Packit ce96f2
                         FILE__, __LINE__, getpid());
Packit ce96f2
      return false;
Packit ce96f2
   }
Packit ce96f2
   
Packit ce96f2
   if( thread && !thread->isLive() ) {
Packit ce96f2
      proccontrol_printf("%s[%d]: attempted to post RPC to dead thread %d\n",
Packit ce96f2
                         FILE__, __LINE__, thread->getLWP());
Packit ce96f2
      return false;
Packit ce96f2
   }
Packit ce96f2
Packit ce96f2
Packit ce96f2
   inferiorRPCinProgress *newRPC = new inferiorRPCinProgress;
Packit ce96f2
   newRPC->runProcWhenDone = runProcessWhenDone;
Packit ce96f2
   newRPC->deliverCallbacks = userRPC;
Packit ce96f2
   newRPC->userData = userData;
Packit ce96f2
   newRPC->synchronous = synchronous;
Packit ce96f2
Packit ce96f2
   newRPC->resultRegister = resultReg;
Packit ce96f2
   
Packit ce96f2
   // Create the iRPC at the ProcControl level
Packit ce96f2
   if( addr == 0 ) {
Packit ce96f2
      bool err = false;
Packit ce96f2
      if( isMemAlloc ) {
Packit ce96f2
         // This assumes that there will always be space
Packit ce96f2
         addr = inferiorMalloc(size, lowmemHeap, 0, &err;;
Packit ce96f2
      }else{
Packit ce96f2
         // recursive RPCs are okay when this isn't an inferiorMalloc RPC
Packit ce96f2
         addr = inferiorMalloc(size, anyHeap, 0, &err;;
Packit ce96f2
      }
Packit ce96f2
      
Packit ce96f2
      if( err ) {
Packit ce96f2
         proccontrol_printf("%s[%d]: failed to allocate memory for RPC\n",
Packit ce96f2
                            FILE__, __LINE__);
Packit ce96f2
         delete newRPC;
Packit ce96f2
         return false;
Packit ce96f2
      }
Packit ce96f2
      newRPC->memoryAllocated = true;
Packit ce96f2
   }
Packit ce96f2
   
Packit ce96f2
    if (addr)
Packit ce96f2
       newRPC->rpc = IRPC::createIRPC(buf, size, addr);
Packit ce96f2
    else
Packit ce96f2
       newRPC->rpc = IRPC::createIRPC(buf, size);
Packit ce96f2
Packit ce96f2
#if 0
Packit ce96f2
   // DEBUG
Packit ce96f2
   InstructionAPI::InstructionDecoder d(buf,size,getArch());
Packit ce96f2
   Address foo = addr;
Packit ce96f2
   InstructionAPI::Instruction::Ptr insn = d.decode();
Packit ce96f2
   while(insn) {
Packit ce96f2
      cerr << "\t" << hex << foo << ": " << insn->format(foo) << dec << endl;
Packit ce96f2
      foo += insn->size();
Packit ce96f2
      insn = d.decode();
Packit ce96f2
   }
Packit ce96f2
#endif
Packit ce96f2
    newRPC->rpc->setData(newRPC);
Packit ce96f2
Packit ce96f2
    unsigned int start_offset = 0;
Packit ce96f2
#if defined(bug_syscall_changepc_rewind)
Packit ce96f2
    // Some Linux kernels have the following behavior:
Packit ce96f2
    // Process is in a system call;
Packit ce96f2
    // We interrupt the system call;
Packit ce96f2
    // We say "change PC to address N"
Packit ce96f2
    // The kernel helpfully changes it to (N - address width)
Packit ce96f2
    // The program crashes
Packit ce96f2
    // See a more complete comment above.
Packit ce96f2
    // For now, we pad the start of our code with NOOPS and change to just
Packit ce96f2
    // after those; if we hit rewind behavior, then we're executing safe code.
Packit ce96f2
    //
Packit ce96f2
    // Matt Note:  The above comment is slightly incorrect.  The kernel subracts
Packit ce96f2
    //  the length of the syscall/int instruction that triggered the system call,
Packit ce96f2
    //  not the address width.  Still address width is big enough, so I'm not
Packit ce96f2
    //  changing anything.
Packit ce96f2
    start_offset = proc()->getAddressWidth();
Packit ce96f2
    newRPC->rpcStartAddr += start_offset;
Packit ce96f2
#endif
Packit ce96f2
    newRPC->rpc->setStartOffset(start_offset);
Packit ce96f2
    newRPC->rpcCompletionAddr = addr + breakOffset;
Packit ce96f2
Packit ce96f2
    // Post the iRPC
Packit ce96f2
    Thread::ptr t;
Packit ce96f2
    if (thread) {
Packit ce96f2
       t = thread->pcThr();
Packit ce96f2
    }
Packit ce96f2
    newRPC->thread = t;
Packit ce96f2
    
Packit ce96f2
    bool res = false;
Packit ce96f2
    proccontrol_printf("%s[%d]: Launching IRPC\n", FILE__, __LINE__);
Packit ce96f2
    if (synchronous) {
Packit ce96f2
       // We have an interesting problem here. ProcControl allows callbacks to specify whether the 
Packit ce96f2
       // process should stop or run; however, that allows us to stop a process in the middle of an
Packit ce96f2
       // inferior RPC. If that happens, manually execute a continue and wait for completion ourselves.
Packit ce96f2
       if (t)
Packit ce96f2
          res = t->runIRPCSync(newRPC->rpc);
Packit ce96f2
       else
Packit ce96f2
          res = pcProc_->runIRPCSync(newRPC->rpc);
Packit ce96f2
       if (!res) {
Packit ce96f2
          bool done = false;
Packit ce96f2
          while (!done) {
Packit ce96f2
             proccontrol_printf("%s[%d]: Iterating in loop waiting for IRPC to complete\n", FILE__, __LINE__);
Packit ce96f2
             if (isTerminated()) {
Packit ce96f2
                fprintf(stderr, "IRPC on terminated process, ret false!\n");
Packit ce96f2
                delete newRPC;
Packit ce96f2
                return false;
Packit ce96f2
             }
Packit ce96f2
Packit ce96f2
            if (ProcControlAPI::getLastError() != ProcControlAPI::err_notrunning) {
Packit ce96f2
                // Something went wrong
Packit ce96f2
               proccontrol_printf("%s[%d]: failed to post %s RPC to %s, error %s\n",
Packit ce96f2
                                  FILE__, __LINE__, (synchronous ? "sync" : "async"), 
Packit ce96f2
                                  ((thread == NULL) ? "thread" : "process"),
Packit ce96f2
                                  ProcControlAPI::getLastErrorMsg());
Packit ce96f2
               delete newRPC;
Packit ce96f2
               return false;
Packit ce96f2
            }
Packit ce96f2
            else {
Packit ce96f2
               proccontrol_printf("%s[%d]: ProcControl reported IRPC thread stopped, continuing and consuming events\n", FILE__, __LINE__);
Packit ce96f2
               newRPC->rpc->continueStoppedIRPC();
Packit ce96f2
               proccontrol_printf("%s[%d]: handling events in ProcControl\n", FILE__, __LINE__);
Packit ce96f2
               res = pcProc_->handleEvents(true);
Packit ce96f2
               PCEventMuxer::muxer().handle(NULL);
Packit ce96f2
               if (newRPC->rpc->state() == ProcControlAPI::IRPC::Done) {
Packit ce96f2
                  proccontrol_printf("%s[%d]: IRPC complete\n", FILE__, __LINE__);
Packit ce96f2
                  done = true;
Packit ce96f2
               }
Packit ce96f2
            }
Packit ce96f2
          }
Packit ce96f2
       }
Packit ce96f2
    }
Packit ce96f2
    else {
Packit ce96f2
       if (t)
Packit ce96f2
          res = t->runIRPCAsync(newRPC->rpc);
Packit ce96f2
       else
Packit ce96f2
          res = pcProc_->runIRPCAsync(newRPC->rpc);
Packit ce96f2
    }
Packit ce96f2
    if(!res) {
Packit ce96f2
       proccontrol_printf("%s[%d]: failed to post %s RPC to %s\n",
Packit ce96f2
                          FILE__, __LINE__, (synchronous ? "sync" : "async"), ((thread == NULL) ? "thread" : "process"));
Packit ce96f2
       delete newRPC;
Packit ce96f2
       return false;
Packit ce96f2
    }
Packit ce96f2
    
Packit ce96f2
    if( result ) {
Packit ce96f2
       *result = newRPC->returnValue;
Packit ce96f2
    }
Packit ce96f2
    
Packit ce96f2
    // Make sure Dyninst has worked everything out
Packit ce96f2
    PCEventMuxer::muxer().wait(false);
Packit ce96f2
Packit ce96f2
   return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Packit ce96f2
BPatch_hybridMode PCProcess::getHybridMode() {
Packit ce96f2
    return analysisMode_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isExploratoryModeOn() const {
Packit ce96f2
    return BPatch_exploratoryMode == analysisMode_ ||
Packit ce96f2
           BPatch_defensiveMode   == analysisMode_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isRuntimeHeapAddr(Address addr) const {
Packit ce96f2
    for (unsigned hidx=0; hidx < dyninstRT_heaps_.size(); hidx++) {
Packit ce96f2
        if (addr >= dyninstRT_heaps_[hidx]->addr &&
Packit ce96f2
            addr < dyninstRT_heaps_[hidx]->addr + dyninstRT_heaps_[hidx]->length) {
Packit ce96f2
            return true;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
    return false;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
/* returns true if blocks were overwritten, initializes overwritten
Packit ce96f2
 * blocks and ranges by contrasting shadow pages with current memory
Packit ce96f2
 * contents
Packit ce96f2
 * 1. reads shadow pages in from memory
Packit ce96f2
 * 2. constructs overwritten region list
Packit ce96f2
 * 3. constructs overwrittn basic block list
Packit ce96f2
 * 4. determines if the last of the blocks has an abrupt end, in which
Packit ce96f2
 *    case it marks it as overwritten
Packit ce96f2
 */
Packit ce96f2
bool PCProcess::getOverwrittenBlocks
Packit ce96f2
  ( std::map<Address, unsigned char *>& overwrittenPages,//input
Packit ce96f2
    std::list<std::pair<Address,Address> >& overwrittenRanges,//output
Packit ce96f2
    std::list<block_instance *> &writtenBBIs)//output
Packit ce96f2
{
Packit ce96f2
    const unsigned MEM_PAGE_SIZE = getMemoryPageSize();
Packit ce96f2
    unsigned char * memVersion = (unsigned char *) ::malloc(MEM_PAGE_SIZE);
Packit ce96f2
    Address regionStart = 0;
Packit ce96f2
    bool foundStart = false;
Packit ce96f2
    map<Address, unsigned char*>::iterator pIter = overwrittenPages.begin();
Packit ce96f2
    set<mapped_object*> owObjs;
Packit ce96f2
    for (; pIter != overwrittenPages.end(); pIter++) {
Packit ce96f2
        Address curPageAddr = (*pIter).first / MEM_PAGE_SIZE * MEM_PAGE_SIZE;
Packit ce96f2
        unsigned char *curShadow = (*pIter).second;
Packit ce96f2
Packit ce96f2
        // 0. check to make sure curShadow is non-null, if it is null, 
Packit ce96f2
        //    that means it hasn't been written to
Packit ce96f2
        if ( ! curShadow ) {
Packit ce96f2
                        cerr << "\t\t No current shadow, continuing" << endl;
Packit ce96f2
                        continue;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        mapped_object* obj = findObject(curPageAddr);
Packit ce96f2
        if (owObjs.end() != owObjs.find(obj)) {
Packit ce96f2
            obj->setCodeBytesUpdated(false);
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        // 1. Read the modified page in from memory
Packit ce96f2
        Address readAddr = curPageAddr;
Packit ce96f2
        if (isMemoryEmulated()) {
Packit ce96f2
            bool valid = false;
Packit ce96f2
            boost::tie(valid,readAddr) = getMemEm()->translate(curPageAddr);
Packit ce96f2
                        cerr << "\t\t Reading from shadow page " << hex << readAddr << " instead of original " << curPageAddr << endl;
Packit ce96f2
            assert(valid);
Packit ce96f2
        }
Packit ce96f2
        readTextSpace((void*)readAddr, MEM_PAGE_SIZE, memVersion);
Packit ce96f2
Packit ce96f2
        // 2. build overwritten region list by comparing shadow, memory
Packit ce96f2
        for (unsigned mIdx = 0; mIdx < MEM_PAGE_SIZE; mIdx++) {
Packit ce96f2
            if ( ! foundStart && curShadow[mIdx] != memVersion[mIdx] ) {
Packit ce96f2
                foundStart = true;
Packit ce96f2
                regionStart = curPageAddr+mIdx;
Packit ce96f2
            } else if (foundStart && curShadow[mIdx] == memVersion[mIdx]) {
Packit ce96f2
                foundStart = false;
Packit ce96f2
                                cerr << "\t\t Adding overwritten range " << hex << regionStart << " -> " << curPageAddr + mIdx << dec << endl;
Packit ce96f2
Packit ce96f2
                overwrittenRanges.push_back(
Packit ce96f2
                    pair<Address,Address>(regionStart,curPageAddr+mIdx));
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
        if (foundStart) {
Packit ce96f2
Packit ce96f2
            foundStart = false;
Packit ce96f2
                        cerr << "\t\t Adding overwritten range " << hex << regionStart << " -> " << curPageAddr + MEM_PAGE_SIZE << dec << endl;
Packit ce96f2
Packit ce96f2
            overwrittenRanges.push_back(
Packit ce96f2
                pair<Address,Address>(regionStart,curPageAddr+MEM_PAGE_SIZE));
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // 3. Determine which basic blocks have been overwritten
Packit ce96f2
    list<pair<Address,Address> >::const_iterator rIter = overwrittenRanges.begin();
Packit ce96f2
    std::list<block_instance*> curBBIs;
Packit ce96f2
    while (rIter != overwrittenRanges.end()) {
Packit ce96f2
        mapped_object *curObject = findObject((*rIter).first);
Packit ce96f2
Packit ce96f2
        curObject->findBlocksByRange((*rIter).first,(*rIter).second,curBBIs);
Packit ce96f2
        if (curBBIs.size()) {
Packit ce96f2
            mal_printf("overwrote %d blocks in range %lx %lx \n",
Packit ce96f2
                       curBBIs.size(),(*rIter).first,(*rIter).second);
Packit ce96f2
            writtenBBIs.splice(writtenBBIs.end(), curBBIs);
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        curBBIs.clear();
Packit ce96f2
        rIter++;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    free(memVersion);
Packit ce96f2
    if (writtenBBIs.size()) {
Packit ce96f2
        return true;
Packit ce96f2
    } else {
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// distribute the work to mapped_objects
Packit ce96f2
void PCProcess::updateCodeBytes
Packit ce96f2
    ( const list<pair<Address, Address> > &owRanges ) // input
Packit ce96f2
{
Packit ce96f2
    std::map<mapped_object *,list<pair<Address,Address> >*> objRanges;
Packit ce96f2
    list<pair<Address,Address> >::const_iterator rIter = owRanges.begin();
Packit ce96f2
    for (; rIter != owRanges.end(); rIter++) {
Packit ce96f2
        mapped_object *obj = findObject((*rIter).first);
Packit ce96f2
        if (objRanges.find(obj) == objRanges.end()) {
Packit ce96f2
            objRanges[obj] = new list<pair<Address,Address> >();
Packit ce96f2
        }
Packit ce96f2
        objRanges[obj]->push_back(pair<Address,Address>(rIter->first, rIter->second));
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    std::map<mapped_object *,list<pair<Address,Address> > *>::iterator oIter = 
Packit ce96f2
        objRanges.begin();
Packit ce96f2
    for (; oIter != objRanges.end(); oIter++) 
Packit ce96f2
    {
Packit ce96f2
        oIter->first->updateCodeBytes( *(oIter->second) );
Packit ce96f2
        delete (oIter->second);
Packit ce96f2
    }
Packit ce96f2
    assert(objRanges.size() <= 1); //o/w analysis code may not be prepared for other cases
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
#if 0
Packit ce96f2
static void otherFuncBlocks(func_instance *func, 
Packit ce96f2
                            const set<block_instance*> &blks, 
Packit ce96f2
                            set<block_instance*> &otherBlks)
Packit ce96f2
{
Packit ce96f2
    const func_instance::BlockSet &allBlocks = 
Packit ce96f2
        func->blocks();
Packit ce96f2
    for (func_instance::BlockSet::const_iterator bit =
Packit ce96f2
         allBlocks.begin();
Packit ce96f2
         bit != allBlocks.end(); 
Packit ce96f2
         bit++) 
Packit ce96f2
    {
Packit ce96f2
        if (blks.end() == blks.find((*bit))) {
Packit ce96f2
            otherBlks.insert((*bit));
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
/* Summary
Packit ce96f2
 * Given a list of overwritten blocks, find blocks that are unreachable,
Packit ce96f2
 * functions that have been overwritten at their entry points and can go away,
Packit ce96f2
 * and new function entry for functions that are being overwritten while still
Packit ce96f2
 * executing
Packit ce96f2
 *
Packit ce96f2
 * variables
Packit ce96f2
 * f:  the overwritten function
Packit ce96f2
 * ow: the set of overwritten blocks
Packit ce96f2
 * ex: the set of blocks that are executing on the call stack that were not overwritten
Packit ce96f2
 * 
Packit ce96f2
 * primitives
Packit ce96f2
 * R(b,s): yields set of reachable blocks for collection of blocks b, starting
Packit ce96f2
 *         at seed blocks s.
Packit ce96f2
 * B(f):   the blocks pertaining to function f
Packit ce96f2
 * EP(f):  the entry point of function f
Packit ce96f2
 * F(b):   functions containing block b
Packit ce96f2
 * 
Packit ce96f2
 * calculations
Packit ce96f2
 * Elim(f): the set of blocks to eliminate from function f.
Packit ce96f2
 *          Elim(f) = B(f) - R( B(f)-ow , EP(f) )
Packit ce96f2
 * New(f):  new function entry candidates for f's surviving blocks.
Packit ce96f2
 *          If EB(f) not in ow(f), empty set
Packit ce96f2
 *          Else, all blocks b such that ( b in ex AND e in Elim(f) )
Packit ce96f2
 *          Eliminate New(f) elements that have ancestors in New(f)
Packit ce96f2
 * Del(f):  A block can be deleted altogether if
Packit ce96f2
 *          forall f in F(b): B(F) - R( B(f) - ow , New(f) U (EP(f) \ ow(f)) U (ex(f) intersect Elim(f)) ),
Packit ce96f2
 *          b is not in the resulting set. In other words, b is not
Packit ce96f2
 *          reachable from non-overwritten blocks in the functions in
Packit ce96f2
 *          which it appears, seeded at new entry points and original
Packit ce96f2
 *          non-overwritten entry points to the function, and at f's
Packit ce96f2
 *          executing blocks if these will be deleted from the
Packit ce96f2
 *          function (they constitute an entry point into the function 
Packit ce96f2
 *          even if they've been overwritten). 
Packit ce96f2
 * DeadF:   the set of functions that have no executing blocks 
Packit ce96f2
 *          and were overwritten in their entry blocks
Packit ce96f2
 *          EP(f) in ow(f) AND ex(f) is empty
Packit ce96f2
 */
Packit ce96f2
bool PCProcess::getDeadCode
Packit ce96f2
( const std::list<block_instance*> & /*owBlocks*/, // input
Packit ce96f2
  std::set<block_instance*> & /*delBlocks*/, //output: Del(for all f)
Packit ce96f2
  std::map<func_instance*,set<block_instance*> > & /*elimMap*/, //output: elimF
Packit ce96f2
  std::list<func_instance*> & /*deadFuncs*/, //output: DeadF
Packit ce96f2
  std::map<func_instance*,block_instance*> & /*newFuncEntries*/) //output: newF
Packit ce96f2
{
Packit ce96f2
   assert(0 && "TODO");
Packit ce96f2
   return false;
Packit ce96f2
#if 0
Packit ce96f2
    // do a stackwalk to see which functions are currently executing
Packit ce96f2
    pdvector<pdvector<Frame> >  stacks;
Packit ce96f2
    pdvector<Address> pcs;
Packit ce96f2
    if (!walkStacks(stacks)) {
Packit ce96f2
        inst_printf("%s[%d]:  walkStacks failed\n", FILE__, __LINE__);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
    for (unsigned i = 0; i < stacks.size(); ++i) {
Packit ce96f2
        pdvector<Frame> &stack = stacks[i];
Packit ce96f2
        for (unsigned int j = 0; j < stack.size(); ++j) {
Packit ce96f2
            Address origPC = 0;
Packit ce96f2
            vector<func_instance*> dontcare1;
Packit ce96f2
            baseTramp *dontcare2 = NULL;
Packit ce96f2
            getAddrInfo(stack[j].getPC(), origPC, dontcare1, dontcare2);
Packit ce96f2
            pcs.push_back( origPC );
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // group blocks by function
Packit ce96f2
    std::map<func_instance*,set<block_instance*> > deadMap;
Packit ce96f2
    std::set<func_instance*> deadEntryFuncs;
Packit ce96f2
    std::set<Address> owBlockAddrs;
Packit ce96f2
    for (list<block_instance*>::const_iterator bIter=owBlocks.begin();
Packit ce96f2
         bIter != owBlocks.end(); 
Packit ce96f2
         bIter++) 
Packit ce96f2
    {
Packit ce96f2
       deadMap[(*bIter)->func()].insert(*bIter);
Packit ce96f2
       owBlockAddrs.insert((*bIter)->start());
Packit ce96f2
       if ((*bIter)->llb() == (*bIter)->func()->ifunc()->entry()) {
Packit ce96f2
          deadEntryFuncs.insert((*bIter)->func());
Packit ce96f2
       }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // for each modified function, calculate ex, ElimF, NewF, DelF
Packit ce96f2
    for (map<func_instance*,set<block_instance*> >::iterator fit = deadMap.begin();
Packit ce96f2
         fit != deadMap.end(); 
Packit ce96f2
         fit++) 
Packit ce96f2
    {
Packit ce96f2
Packit ce96f2
        // calculate ex(f)
Packit ce96f2
        set<block_instance*> execBlocks;
Packit ce96f2
        for (unsigned pidx=0; pidx < pcs.size(); pidx++) {
Packit ce96f2
            std::set<block_instance *> candidateBlocks;
Packit ce96f2
            fit->first->findBlocksByAddr(pcs[pidx], candidateBlocks);
Packit ce96f2
            for (std::set<block_instance *>::iterator cb_iter = candidateBlocks.begin();
Packit ce96f2
                cb_iter != candidateBlocks.end(); ++cb_iter) {
Packit ce96f2
                block_instance *exB = *cb_iter;
Packit ce96f2
                if (exB && owBlockAddrs.end() == owBlockAddrs.find(
Packit ce96f2
                                                        exB->start())) 
Packit ce96f2
                {
Packit ce96f2
                    execBlocks.insert(exB);
Packit ce96f2
                }
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        // calculate DeadF: EP(f) in ow and EP(f) not in ex
Packit ce96f2
        if ( 0 == execBlocks.size() ) {
Packit ce96f2
            set<block_instance*>::iterator eb = fit->second.find(
Packit ce96f2
                fit->first->entryBlock());
Packit ce96f2
            if (eb != fit->second.end()) {
Packit ce96f2
                deadFuncs.push_back(fit->first);
Packit ce96f2
                continue;// treated specially, don't need elimF, NewF or DelF
Packit ce96f2
            }
Packit ce96f2
        } 
Packit ce96f2
Packit ce96f2
        // calculate elimF
Packit ce96f2
        set<block_instance*> keepF;
Packit ce96f2
        list<block_instance*> seedBs;
Packit ce96f2
        seedBs.push_back(fit->first->entryBlock());
Packit ce96f2
        fit->first->getReachableBlocks(fit->second, seedBs, keepF);
Packit ce96f2
        otherFuncBlocks(fit->first, keepF, elimMap[fit->first]);
Packit ce96f2
Packit ce96f2
        // calculate NewF
Packit ce96f2
        if (deadEntryFuncs.end() != deadEntryFuncs.find(fit->first)) {
Packit ce96f2
            for (set<block_instance*>::iterator bit = execBlocks.begin();
Packit ce96f2
                 bit != execBlocks.end();
Packit ce96f2
                 bit++) 
Packit ce96f2
            {
Packit ce96f2
                if (elimMap[fit->first].end() != 
Packit ce96f2
                    elimMap[fit->first].find(*bit)) 
Packit ce96f2
                {
Packit ce96f2
                    newFuncEntries[fit->first] = *bit;
Packit ce96f2
                    break; // just need one candidate
Packit ce96f2
                }
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        // calculate Del(f)
Packit ce96f2
        seedBs.clear();
Packit ce96f2
        if (deadEntryFuncs.end() == deadEntryFuncs.find(fit->first)) {
Packit ce96f2
            seedBs.push_back(fit->first->entryBlock());
Packit ce96f2
        }
Packit ce96f2
        else if (newFuncEntries.end() != newFuncEntries.find(fit->first)) {
Packit ce96f2
            seedBs.push_back(newFuncEntries[fit->first]);
Packit ce96f2
        }
Packit ce96f2
        for (set<block_instance*>::iterator xit = execBlocks.begin();
Packit ce96f2
             xit != execBlocks.end();
Packit ce96f2
             xit++) 
Packit ce96f2
        {
Packit ce96f2
            if (elimMap[fit->first].end() != elimMap[fit->first].find(*xit)) {
Packit ce96f2
                seedBs.push_back(*xit);
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
        keepF.clear();
Packit ce96f2
        fit->first->getReachableBlocks(fit->second, seedBs, keepF);
Packit ce96f2
        otherFuncBlocks(fit->first, keepF, delBlocks);
Packit ce96f2
        
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
#endif
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// will flush addresses of all addresses in the specified range, if the
Packit ce96f2
// range is null, flush all addresses from the cache.  Also flush 
Packit ce96f2
// rt-lib heap addrs that correspond to the range
Packit ce96f2
void PCProcess::flushAddressCache_RT(Address start, unsigned size)
Packit ce96f2
{
Packit ce96f2
    if (start != 0) {
Packit ce96f2
        mal_printf("Flushing address cache of range [%lx %lx]\n",
Packit ce96f2
                   start, 
Packit ce96f2
                   start + size);
Packit ce96f2
    } else {
Packit ce96f2
        mal_printf("Flushing address cache of rt_lib heap addrs only \n");
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Find the runtime cache's address if it hasn't been set yet
Packit ce96f2
    if (0 == RT_address_cache_addr_) {
Packit ce96f2
        std::string arg_str ("DYNINST_target_cache");
Packit ce96f2
        pdvector<int_variable *> vars;
Packit ce96f2
        if ( ! findVarsByAll(arg_str, vars) ) {
Packit ce96f2
            fprintf(stderr, "%s[%d]:  cannot find var %s\n", 
Packit ce96f2
                    FILE__, __LINE__, arg_str.c_str());
Packit ce96f2
            assert(0);
Packit ce96f2
        }
Packit ce96f2
        if (vars.size() != 1) {
Packit ce96f2
            fprintf(stderr, "%s[%d]:  ERROR:  %d vars matching %s, not 1\n", 
Packit ce96f2
                    FILE__, __LINE__, (int)vars.size(), arg_str.c_str());
Packit ce96f2
            assert(0);
Packit ce96f2
        }
Packit ce96f2
        RT_address_cache_addr_ = vars[0]->getAddress();
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Clear all cache entries that match the runtime library
Packit ce96f2
    // Read in the contents of the cache
Packit ce96f2
    Address* cacheCopy = (Address*)malloc(TARGET_CACHE_WIDTH*sizeof(Address));
Packit ce96f2
    if ( ! readDataSpace( (void*)RT_address_cache_addr_, 
Packit ce96f2
                          sizeof(Address)*TARGET_CACHE_WIDTH,(void*)cacheCopy,
Packit ce96f2
                          false ) ) 
Packit ce96f2
    {
Packit ce96f2
        assert(0);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    assert(dyninstRT_heaps_.size());
Packit ce96f2
    bool flushedHeaps = false;
Packit ce96f2
Packit ce96f2
    while ( true ) // iterate twice, once to flush the heaps, 
Packit ce96f2
    {              // and once to flush the flush range
Packit ce96f2
        Address flushStart=0;
Packit ce96f2
        Address flushEnd=0;
Packit ce96f2
        if (!flushedHeaps) {
Packit ce96f2
            // figure out the range of addresses we'll want to flush from
Packit ce96f2
Packit ce96f2
            flushStart = dyninstRT_heaps_[0]->addr;
Packit ce96f2
            flushEnd = flushStart + dyninstRT_heaps_[0]->length;
Packit ce96f2
            for (unsigned idx=1; idx < dyninstRT_heaps_.size(); idx++) {
Packit ce96f2
                Address curAddr = dyninstRT_heaps_[idx]->addr;
Packit ce96f2
                if (flushStart > curAddr) {
Packit ce96f2
                    flushStart = curAddr;
Packit ce96f2
                }
Packit ce96f2
                curAddr += dyninstRT_heaps_[idx]->length;
Packit ce96f2
                if (flushEnd < curAddr) {
Packit ce96f2
                    flushEnd = curAddr;
Packit ce96f2
                }
Packit ce96f2
            }
Packit ce96f2
        } else {
Packit ce96f2
            flushStart = start;
Packit ce96f2
            flushEnd = start + size;
Packit ce96f2
        }
Packit ce96f2
        //zero out entries that lie in the runtime heaps
Packit ce96f2
        for(int idx=0; idx < TARGET_CACHE_WIDTH; idx++) {
Packit ce96f2
            //printf("cacheCopy[%d]=%lx\n",idx,cacheCopy[idx]);
Packit ce96f2
            if (flushStart <= cacheCopy[idx] &&
Packit ce96f2
                flushEnd   >  cacheCopy[idx]) {
Packit ce96f2
                cacheCopy[idx] = 0;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
        if ( flushedHeaps || (start == 0) ) {
Packit ce96f2
            break;
Packit ce96f2
        }
Packit ce96f2
        flushedHeaps = true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // write the modified cache back into the RT_library
Packit ce96f2
    if ( ! writeDataSpace( (void*)RT_address_cache_addr_,
Packit ce96f2
                           sizeof(Address)*TARGET_CACHE_WIDTH,
Packit ce96f2
                           (void*)cacheCopy ) ) {
Packit ce96f2
        assert(0);
Packit ce96f2
    }
Packit ce96f2
    free(cacheCopy);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
/* Given an address that's on the call stack, find the function that's
Packit ce96f2
 * actively executing that address.  This makes most sense for finding the
Packit ce96f2
 * address that's triggered a context switch back to Dyninst, either
Packit ce96f2
 * through instrumentation or a signal
Packit ce96f2
 */
Packit ce96f2
func_instance *PCProcess::findActiveFuncByAddr(Address addr)
Packit ce96f2
{
Packit ce96f2
    std::set<func_instance *> funcs;
Packit ce96f2
    // error checking by size...
Packit ce96f2
    (void)findFuncsByAddr(addr, funcs, true);
Packit ce96f2
    if (funcs.empty()) return NULL;
Packit ce96f2
Packit ce96f2
    if (funcs.size() == 1) {
Packit ce96f2
        return *(funcs.begin());
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // unrelocated shared function address, do a stack walk to figure 
Packit ce96f2
    // out which of the shared functions is on the call stack
Packit ce96f2
    bool foundFrame = false;
Packit ce96f2
    func_instance *activeFunc = NULL; 
Packit ce96f2
    pdvector<pdvector<Frame> >  stacks;
Packit ce96f2
    if ( false == walkStacks(stacks) ) {
Packit ce96f2
        fprintf(stderr,"ERROR: %s[%d], walkStacks failed\n", 
Packit ce96f2
                FILE__, __LINE__);
Packit ce96f2
        assert(0);
Packit ce96f2
    }
Packit ce96f2
    for (unsigned int i = 0; !foundFrame && i < stacks.size(); ++i) {
Packit ce96f2
        pdvector<Frame> &stack = stacks[i];
Packit ce96f2
        for (unsigned int j = 0; !foundFrame && j < stack.size(); ++j) {
Packit ce96f2
            Frame *curFrame = &stack[j];
Packit ce96f2
            Address framePC = curFrame->getPC();
Packit ce96f2
Packit ce96f2
            // if we're at a relocated address, we can translate 
Packit ce96f2
            // back to the right function, if translation fails 
Packit ce96f2
            // frameFunc will still be NULL
Packit ce96f2
            RelocInfo ri;
Packit ce96f2
            func_instance *frameFunc = NULL;
Packit ce96f2
Packit ce96f2
            if (getRelocInfo(framePC, ri) &&
Packit ce96f2
                ri.func) {
Packit ce96f2
               frameFunc = ri.func;
Packit ce96f2
            }
Packit ce96f2
            else if (j < (stack.size() - 1)) {
Packit ce96f2
                // Okay, crawl original code. 
Packit ce96f2
                // Step 1: get our current function
Packit ce96f2
                std::set<func_instance *> curFuncs;
Packit ce96f2
                findFuncsByAddr(framePC, curFuncs);
Packit ce96f2
                // Step 2: get return addresses one frame up and map to possible callers
Packit ce96f2
                std::set<block_instance *> callerBlocks;
Packit ce96f2
                findBlocksByAddr(stack[j+1].getPC() - 1, callerBlocks);
Packit ce96f2
                for (std::set<block_instance *>::iterator cb_iter = callerBlocks.begin();
Packit ce96f2
                    cb_iter != callerBlocks.end(); ++cb_iter)
Packit ce96f2
                {
Packit ce96f2
                    if (!(*cb_iter)->containsCall()) continue;
Packit ce96f2
                    // We have a call point; now see if it called the entry of any function
Packit ce96f2
                    // that maps to a curFunc.
Packit ce96f2
                    for (std::set<func_instance *>::iterator cf_iter = curFuncs.begin();
Packit ce96f2
                         cf_iter != curFuncs.end(); ++cf_iter) {
Packit ce96f2
                       if ((*cf_iter) == (*cb_iter)->callee()) {
Packit ce96f2
                          frameFunc = *cf_iter;
Packit ce96f2
                       }
Packit ce96f2
                    }
Packit ce96f2
                }
Packit ce96f2
            }
Packit ce96f2
            if (frameFunc) {
Packit ce96f2
                foundFrame = true;
Packit ce96f2
                activeFunc = frameFunc;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
    if (!foundFrame) {
Packit ce96f2
        activeFunc = *(funcs.begin());
Packit ce96f2
    }
Packit ce96f2
                
Packit ce96f2
    return activeFunc;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::patchPostCallArea(instPoint *callPt) {
Packit ce96f2
   // 1) Find all the post-call patch areas that correspond to this 
Packit ce96f2
   //    call point
Packit ce96f2
   // 2) Generate and install the branches that will be inserted into 
Packit ce96f2
   //    these patch areas
Packit ce96f2
   
Packit ce96f2
   // 1...
Packit ce96f2
   AddrPairSet patchAreas;
Packit ce96f2
   if ( ! generateRequiredPatches(callPt, patchAreas) ) {
Packit ce96f2
      return false;
Packit ce96f2
   }
Packit ce96f2
   
Packit ce96f2
   // 2...
Packit ce96f2
   generatePatchBranches(patchAreas);
Packit ce96f2
   return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::generateRequiredPatches(instPoint *callPoint, 
Packit ce96f2
                                        AddrPairSet &patchAreas)
Packit ce96f2
{
Packit ce96f2
    // We need to figure out where this patch should branch to.
Packit ce96f2
    // To do that, we're going to:
Packit ce96f2
    // 1) Forward map the entry of the ft block to
Packit ce96f2
    //    its most recent relocated version (if that exists)
Packit ce96f2
    // 2) For each padding area, create a (padAddr,target) pair
Packit ce96f2
Packit ce96f2
    // 3)
Packit ce96f2
Packit ce96f2
    block_instance *callB = callPoint->block();
Packit ce96f2
    block_instance *ftBlk = callB->getFallthrough()->trg();
Packit ce96f2
    if (!ftBlk) {
Packit ce96f2
        // find the block at the next address, if there's no fallthrough block
Packit ce96f2
        ftBlk = callB->obj()->findBlockByEntry(callB->end());
Packit ce96f2
        assert(ftBlk);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // ensure that we patch other callPts at the same address
Packit ce96f2
Packit ce96f2
    vector<ParseAPI::Function*> callFuncs;
Packit ce96f2
    callPoint->block()->llb()->getFuncs(callFuncs);
Packit ce96f2
    for (vector<ParseAPI::Function*>::iterator fit = callFuncs.begin();
Packit ce96f2
         fit != callFuncs.end();
Packit ce96f2
         fit++)
Packit ce96f2
    {
Packit ce96f2
        func_instance *callF = findFunction((parse_func*)*fit);
Packit ce96f2
        instPoint *callP = instPoint::preCall(callF, callB);
Packit ce96f2
        Relocation::CodeTracker::RelocatedElements reloc;
Packit ce96f2
        CodeTrackers::reverse_iterator rit;
Packit ce96f2
        for (rit = relocatedCode_.rbegin(); rit != relocatedCode_.rend(); rit++)
Packit ce96f2
        {
Packit ce96f2
            if ((*rit)->origToReloc(ftBlk->start(), ftBlk, callF, reloc)) {
Packit ce96f2
                break;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
        if (rit == relocatedCode_.rend()) {
Packit ce96f2
            mal_printf("WARNING: no relocs of call-fallthrough at %lx "
Packit ce96f2
                       "in func at %lx, will not patch its post-call "
Packit ce96f2
                       "padding\n", callP->block()->last(),callF->addr());
Packit ce96f2
            (*relocatedCode_.rbegin())->debug();
Packit ce96f2
            continue;
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        Address to = reloc.instruction;
Packit ce96f2
        if (!reloc.instrumentation.empty()) {
Packit ce96f2
           // There could be a lot of instrumentation at this point. Bias towards the lowest,
Packit ce96f2
           // non-edge instrumentation
Packit ce96f2
           for (std::map<instPoint *, Address>::iterator inst_iter = reloc.instrumentation.begin();
Packit ce96f2
                inst_iter != reloc.instrumentation.end(); ++inst_iter) {
Packit ce96f2
              if (inst_iter->first->type() == PatchAPI::Point::EdgeDuring) continue;
Packit ce96f2
              to = (inst_iter->second < to) ? inst_iter->second : to;
Packit ce96f2
           }
Packit ce96f2
        }
Packit ce96f2
Packit ce96f2
        // 2) 
Packit ce96f2
        Address callInsnAddr = callP->block()->last();
Packit ce96f2
        if (forwardDefensiveMap_.end() != forwardDefensiveMap_.find(callInsnAddr)) {
Packit ce96f2
            map<func_instance*,set<DefensivePad> >::iterator mit = forwardDefensiveMap_[callInsnAddr].begin();
Packit ce96f2
            for (; mit != forwardDefensiveMap_[callInsnAddr].end(); ++mit) {
Packit ce96f2
              if (callF == mit->first) {
Packit ce96f2
                  set<DefensivePad>::iterator dit = mit->second.begin();
Packit ce96f2
                  for (; dit != mit->second.end(); ++dit) {
Packit ce96f2
                     Address jumpAddr = dit->first;
Packit ce96f2
                     patchAreas.insert(std::make_pair(jumpAddr, to));
Packit ce96f2
                     mal_printf("patching post-call pad for %lx[%lx] with %lx %s[%d]\n",
Packit ce96f2
                                callB->end(), jumpAddr, to, FILE__,__LINE__);
Packit ce96f2
                  }
Packit ce96f2
              }
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
    if (patchAreas.empty()) {
Packit ce96f2
       mal_printf("WARNING: no relocs to patch for call at %lx, block end %lx\n", 
Packit ce96f2
                  callPoint->addr_compat(),ftBlk->start());
Packit ce96f2
    }
Packit ce96f2
    return ! patchAreas.empty();
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::generatePatchBranches(AddrPairSet &branchesNeeded) {
Packit ce96f2
  for (AddrPairSet::iterator iter = branchesNeeded.begin();
Packit ce96f2
       iter != branchesNeeded.end(); ++iter) 
Packit ce96f2
  {
Packit ce96f2
    Address from = iter->first;
Packit ce96f2
    Address to = iter->second;
Packit ce96f2
Packit ce96f2
    codeGen gen(64);
Packit ce96f2
    insnCodeGen::generateBranch(gen, from, to);
Packit ce96f2
Packit ce96f2
    // Safety check: make sure we didn't overrun the patch area
Packit ce96f2
    Address lb = 0, ub = 0;
Packit ce96f2
    std::pair<func_instance*,Address> tmp;
Packit ce96f2
    if (!reverseDefensiveMap_.find(from, lb, ub, tmp)) {
Packit ce96f2
      // Huh? This worked before!
Packit ce96f2
      assert(0);
Packit ce96f2
    }
Packit ce96f2
    assert((from + gen.used()) <= ub);
Packit ce96f2
    if (!writeTextSpace((void *)from, 
Packit ce96f2
			gen.used(),
Packit ce96f2
			gen.start_ptr())) {
Packit ce96f2
      assert(0);
Packit ce96f2
    }
Packit ce96f2
  }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
/* debugSuicide is a kind of alternate debugging continueProc.  It runs the
Packit ce96f2
 * process until terminated in single step mode, printing each instruction as
Packit ce96f2
 * it executes.
Packit ce96f2
 */
Packit ce96f2
void PCProcess::debugSuicide() {
Packit ce96f2
    if( isTerminated() ) return;
Packit ce96f2
Packit ce96f2
    isInDebugSuicide_ = true;
Packit ce96f2
Packit ce96f2
    pdvector<Frame> activeFrames;
Packit ce96f2
    getAllActiveFrames(activeFrames);
Packit ce96f2
Packit ce96f2
    for(unsigned i=0; i < activeFrames.size(); ++i) {
Packit ce96f2
        Address addr = activeFrames[i].getPC();
Packit ce96f2
        fprintf(stderr, "Frame %u @ 0x%lx\n", i , addr);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    Thread::ptr initialThread = pcProc_->threads().getInitialThread();
Packit ce96f2
Packit ce96f2
    initialThread->setSingleStepMode(true);
Packit ce96f2
    while( !isTerminated() && isAttached() && initialThread->isLive() ) {
Packit ce96f2
        // Get the current PC
Packit ce96f2
        MachRegister pcReg = MachRegister::getPC(getArch());
Packit ce96f2
        MachRegisterVal resultVal;
Packit ce96f2
        if( !initialThread->getRegister(pcReg, resultVal) ) {
Packit ce96f2
            fprintf(stderr, "%s[%d]: failed to retreive register from thread %d/%d\n",
Packit ce96f2
                    FILE__, __LINE__, getPid(), initialThread->getLWP());
Packit ce96f2
            return;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
pdvector<func_instance *> PCProcess::pcsToFuncs(pdvector<Frame> stackWalk) {
Packit ce96f2
    pdvector <func_instance *> ret;
Packit ce96f2
    unsigned i;
Packit ce96f2
    func_instance *fn;
Packit ce96f2
    for(i=0;i
Packit ce96f2
        fn = (func_instance *)findOneFuncByAddr(stackWalk[i].getPC());
Packit ce96f2
        // no reason to add a null function to ret
Packit ce96f2
        if (fn != 0) ret.push_back(fn);
Packit ce96f2
    }
Packit ce96f2
    return ret;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isInSignalHandler(Address addr) {
Packit ce96f2
    codeRange *range;
Packit ce96f2
    if( signalHandlerLocations_.find(addr, range) ) {
Packit ce96f2
        return true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return false;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::addSignalHandler(Address addr, unsigned size) {
Packit ce96f2
    codeRange *handlerLoc;
Packit ce96f2
    if (signalHandlerLocations_.find(addr, handlerLoc)) {
Packit ce96f2
        return; // we're already tracking this location
Packit ce96f2
    }
Packit ce96f2
    handlerLoc = new signal_handler_location(addr, size);
Packit ce96f2
    signalHandlerLocations_.insert((signal_handler_location *)handlerLoc);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::mappedObjIsDeleted(mapped_object *obj) {
Packit ce96f2
    for(unsigned i = 0; i < deletedObjects_.size(); ++i) {
Packit ce96f2
        if( obj == deletedObjects_[i] ) return true;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return false;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// AddressSpace Implementation //
Packit ce96f2
Address PCProcess::offset() const {
Packit ce96f2
    assert(!"This function is not implemented");
Packit ce96f2
    return 0;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Address PCProcess::length() const {
Packit ce96f2
    assert(!"This function is not implemented");
Packit ce96f2
    return 0;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Architecture PCProcess::getArch() const {
Packit ce96f2
    return savedArch_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::multithread_ready(bool ignoreIfMtNotSet) {
Packit ce96f2
    // Since ProcControlAPI has taken over handling thread creation
Packit ce96f2
    // and destruction from the RT library, as soon as the process reaches
Packit ce96f2
    // the initialized state, the process is multithread ready if it
Packit ce96f2
    // is multithread capable.
Packit ce96f2
Packit ce96f2
    if( !hasReachedBootstrapState(bs_initialized) ) return false;
Packit ce96f2
    if( !multithread_capable(ignoreIfMtNotSet) ) return false;
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::needsPIC() {
Packit ce96f2
    return false;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::isInDebugSuicide() const {
Packit ce96f2
    return isInDebugSuicide_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
PCProcess::processState_t PCProcess::getDesiredProcessState() const {
Packit ce96f2
    return processState_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::setDesiredProcessState(PCProcess::processState_t pc) {
Packit ce96f2
    processState_ = pc;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::walkStack(pdvector<Frame> &stackWalk,
Packit ce96f2
                          PCThread *thread)
Packit ce96f2
{
Packit ce96f2
  if( stackwalker_ == NULL ) return false;
Packit ce96f2
Packit ce96f2
  vector<Dyninst::Stackwalker::Frame> swWalk;
Packit ce96f2
Packit ce96f2
  if (!stackwalker_->walkStack(swWalk, thread->getLWP()))
Packit ce96f2
  {
Packit ce96f2
    return false;
Packit ce96f2
  }
Packit ce96f2
Packit ce96f2
  for (vector<Dyninst::Stackwalker::Frame>::iterator SWB = swWalk.begin(),
Packit ce96f2
       SWI = SWB,
Packit ce96f2
       SWE = swWalk.end();
Packit ce96f2
       SWI != SWE;
Packit ce96f2
       ++SWI)
Packit ce96f2
  {
Packit ce96f2
    stackWalk.push_back(Frame(*SWI, this, thread, (SWI == SWB)));
Packit ce96f2
  }
Packit ce96f2
Packit ce96f2
  return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::getActiveFrame(Frame &frame, PCThread *thread)
Packit ce96f2
{
Packit ce96f2
  Dyninst::Stackwalker::Frame swFrame;
Packit ce96f2
  if (!stackwalker_->getInitialFrame(swFrame, thread->getLWP()))
Packit ce96f2
  {
Packit ce96f2
    return false;
Packit ce96f2
  }
Packit ce96f2
Packit ce96f2
  frame = Frame(swFrame, this, thread, true);
Packit ce96f2
  return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
/* This is the simple version
Packit ce96f2
 * 1. Need three pieces of information:
Packit ce96f2
 * 1a. The instrumentation point that triggered the stopThread event (pointAddress)
Packit ce96f2
 * 1b. The ID of the callback function given at the registration
Packit ce96f2
 *     of the stopThread snippet
Packit ce96f2
 * 1c. The result of the snippet calculation that was given by the user,
Packit ce96f2
 *     if the point is a return instruction, read the return address
Packit ce96f2
 * 2. If the calculation is an address that is meant to be interpreted, do that
Packit ce96f2
 * 3. Invoke the callback
Packit ce96f2
 */
Packit ce96f2
bool PCProcess::triggerStopThread(Address pointAddress, int callbackID, void *calculation) {
Packit ce96f2
    AddressSpace::RelocInfo ri;
Packit ce96f2
    if( !getRelocInfo(pointAddress, ri) ) {
Packit ce96f2
        assert(0);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // get instPoint from point address
Packit ce96f2
    func_instance *pointfunc = ri.func;
Packit ce96f2
    if (!pointfunc) {
Packit ce96f2
        mal_printf("%s[%d]: failed to find active function at 0x%lx\n",
Packit ce96f2
                FILE__, __LINE__, pointAddress);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    instPoint *intPoint = ri.bt->point();
Packit ce96f2
    if (!intPoint) {
Packit ce96f2
        mal_printf("%s[%d]: failed to find inst point at 0x%lx\n",
Packit ce96f2
                FILE__, __LINE__, pointAddress);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    mal_printf("handling stopThread %lx[%lx]=>%lx %s[%d]\n",
Packit ce96f2
            ri.reloc, pointAddress, (long)calculation, FILE__, __LINE__);
Packit ce96f2
Packit ce96f2
    /* 2. If the callbackID is negative, the calculation is meant to be
Packit ce96f2
      interpreted as the address of code, so we call stopThreadCtrlTransfer
Packit ce96f2
      to translate the target to an unrelocated address */
Packit ce96f2
    if (callbackID < 0) {
Packit ce96f2
        callbackID *= -1;
Packit ce96f2
        calculation = (void*)
Packit ce96f2
            stopThreadCtrlTransfer(intPoint, (Address)calculation);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    /* 3. Trigger the callback for the stopThread
Packit ce96f2
      using the correct snippet instance ID & event type */
Packit ce96f2
    ((BPatch_process*)up_ptr())->triggerStopThread
Packit ce96f2
        (intPoint, pointfunc, callbackID, (void*)calculation);
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
/*    If calculation is a relocated address, translate it to the original addr
Packit ce96f2
 *    case 1: The point is at a return instruction
Packit ce96f2
 *    case 2: The point is a control transfer into the runtime library
Packit ce96f2
 *    Mark returning functions as returning
Packit ce96f2
 *    Save the targets of indirect control transfers (not regular returns)
Packit ce96f2
 */
Packit ce96f2
Address PCProcess::stopThreadCtrlTransfer (instPoint* intPoint, 
Packit ce96f2
                                         Address target)
Packit ce96f2
{
Packit ce96f2
   Address pointAddr = intPoint->addr_compat();
Packit ce96f2
Packit ce96f2
    // if the point is a real return instruction and its target is a stack 
Packit ce96f2
    // address, get the return address off of the stack 
Packit ce96f2
    if (intPoint->type() == instPoint::FuncExit &&
Packit ce96f2
        intPoint->block()->isFuncExit() &&
Packit ce96f2
        !intPoint->func()->isSignalHandler()) 
Packit ce96f2
    {
Packit ce96f2
        mal_printf("%s[%d]: return address is %lx\n", FILE__,
Packit ce96f2
                    __LINE__,target);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    Address unrelocTarget = target;
Packit ce96f2
Packit ce96f2
    if ( isRuntimeHeapAddr( target ) ) {
Packit ce96f2
        // get unrelocated target address, there are three possibilities
Packit ce96f2
        // a. We're in post-call padding, and targBBI is the call block
Packit ce96f2
        // b. We're in an analyzed fallthrough block
Packit ce96f2
        // c. The stack was tampered with and we need the (mod_pc - pc) 
Packit ce96f2
        //    offset to figure out where we should be
Packit ce96f2
        malware_cerr << "Looking for matches to incoming address " 
Packit ce96f2
            << hex << target << dec << endl;
Packit ce96f2
        std::pair<func_instance*,Address> tmp;
Packit ce96f2
Packit ce96f2
        if ( reverseDefensiveMap_.find(target,tmp) ) {
Packit ce96f2
            // a. 
Packit ce96f2
           std::set<block_instance*> callBs;
Packit ce96f2
           tmp.first->getBlocks(tmp.second, callBs);
Packit ce96f2
           block_instance *callB = (*callBs.begin());
Packit ce96f2
           edge_instance *fallthrough = callB->getFallthrough();
Packit ce96f2
           if (fallthrough) {
Packit ce96f2
              unrelocTarget = fallthrough->trg()->start();
Packit ce96f2
           } else {
Packit ce96f2
              unrelocTarget = callB->end();
Packit ce96f2
           }
Packit ce96f2
        }
Packit ce96f2
        else {
Packit ce96f2
            // b. 
Packit ce96f2
            // if we're in the fallthrough block, match to call block, 
Packit ce96f2
            // and if necessary, add fallthrough edge
Packit ce96f2
           AddressSpace::RelocInfo ri;
Packit ce96f2
           bool hasFT = getRelocInfo(target, ri);
Packit ce96f2
           assert(hasFT); // otherwise we should be in the defensive map
Packit ce96f2
           if (ri.pad) {
Packit ce96f2
               unrelocTarget = ri.block->end();
Packit ce96f2
           } else {
Packit ce96f2
               unrelocTarget = ri.block->start();
Packit ce96f2
           }
Packit ce96f2
        }
Packit ce96f2
        mal_printf("translated target %lx to %lx %s[%d]\n",
Packit ce96f2
            target, unrelocTarget, FILE__, __LINE__);
Packit ce96f2
    }
Packit ce96f2
    else { // target is not relocated, nothing to do but find the 
Packit ce96f2
           // mapped_object, creating one if necessary, for transfers
Packit ce96f2
           // into memory regions that are allocated at runtime
Packit ce96f2
        mapped_object *obj = findObject(target);
Packit ce96f2
        if (!obj) {
Packit ce96f2
Packit ce96f2
#if 0           
Packit ce96f2
           Frame activeFrame = threads[0]->get_lwp()->getActiveFrame();
Packit ce96f2
           for (unsigned i = 0; i < 0x100; ++i) {
Packit ce96f2
		          Address stackTOP = activeFrame.esp;
Packit ce96f2
		          Address stackTOPVAL =0;
Packit ce96f2
                readDataSpace((void *) (stackTOP + 4*i), 
Packit ce96f2
                              sizeof(getAddressWidth()), 
Packit ce96f2
                              &stackTOPVAL, false);
Packit ce96f2
		          malware_cerr << "\tSTACK[" << hex << stackTOP+4*i << "]=" 
Packit ce96f2
                             << stackTOPVAL << dec << endl;
Packit ce96f2
           }
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
            obj = createObjectNoFile(target);
Packit ce96f2
            if (!obj) {
Packit ce96f2
                fprintf(stderr,"ERROR, point %lx has target %lx that responds "
Packit ce96f2
                        "to no object %s[%d]\n", pointAddr, target, 
Packit ce96f2
                        FILE__,__LINE__);
Packit ce96f2
                assert(0 && "stopThread snippet has an invalid target");
Packit ce96f2
                return 0;
Packit ce96f2
            }
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
#if 0
Packit ce96f2
           Frame activeFrame = threads[0]->get_lwp()->getActiveFrame();
Packit ce96f2
           Address stackTOP = activeFrame.esp;
Packit ce96f2
           Address stackTOPVAL =0;
Packit ce96f2
           for (unsigned i = 0; 
Packit ce96f2
                i < 0x100 && 0 != ((stackTOP + 4*i) % memoryPageSize_); 
Packit ce96f2
                ++i) 
Packit ce96f2
           {
Packit ce96f2
                readDataSpace((void *) (stackTOP + 4*i), 
Packit ce96f2
                              sizeof(getAddressWidth()), 
Packit ce96f2
                              &stackTOPVAL, false);
Packit ce96f2
		          malware_cerr << "\tSTACK[" << hex << stackTOP+4*i << "]=" 
Packit ce96f2
                             << stackTOPVAL << dec << endl;
Packit ce96f2
           }
Packit ce96f2
#endif
Packit ce96f2
Packit ce96f2
    return unrelocTarget;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::triggerNormalExit(int exitcode) {
Packit ce96f2
    for(std::map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
Packit ce96f2
            i != threadsByTid_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
        if( i->second != initialThread_ ) 
Packit ce96f2
            BPatch::bpatch->registerThreadExit(this, i->second);
Packit ce96f2
    }
Packit ce96f2
    BPatch::bpatch->registerNormalExit(this, exitcode);
Packit ce96f2
Packit ce96f2
    // Let the event handler know that the process should be moved to
Packit ce96f2
    // an exited state
Packit ce96f2
    setExiting(true);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// Debugging only
Packit ce96f2
bool PCProcess::setBreakpoint(Address addr) {
Packit ce96f2
    Breakpoint::ptr brkPt = Breakpoint::newBreakpoint();
Packit ce96f2
    if( !pcProc_->addBreakpoint(addr, brkPt) ) {
Packit ce96f2
        proccontrol_printf("%s[%d]: failed to set breakpoint at 0x%lx\n",
Packit ce96f2
                FILE__, __LINE__, addr);
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::launchDebugger() {
Packit ce96f2
    // Stop the process on detach 
Packit ce96f2
    pdvector<func_instance *> breakpointFuncs;
Packit ce96f2
    if( !findFuncsByAll("DYNINSTsafeBreakPoint", breakpointFuncs) ) {
Packit ce96f2
        fprintf(stderr, "Failed to find function DYNINSTsafeBreakPoint\n");
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    func_instance *safeBreakpoint = breakpointFuncs[0];
Packit ce96f2
    for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
Packit ce96f2
            i != threadsByTid_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
        if( !i->second->pcThr_->setRegister(MachRegister::getPC(getArch()),
Packit ce96f2
                    safeBreakpoint->addr()) )
Packit ce96f2
        {
Packit ce96f2
            fprintf(stderr, "Failed to set PC to 0x%lx\n", 
Packit ce96f2
                    safeBreakpoint->addr());
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    // Detach the process
Packit ce96f2
    if( !detachProcess(true) ) {
Packit ce96f2
        fprintf(stderr, "Failed to detach from process %d\n", getPid());
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    if( !startDebugger() ) {
Packit ce96f2
        fprintf(stderr, "Failed to start debugger on process %d\n", getPid());
Packit ce96f2
        return false;
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
// End debugging
Packit ce96f2
Packit ce96f2
Address getVarAddr(PCProcess *proc, std::string str) {
Packit ce96f2
    Address retAddr = 0;
Packit ce96f2
Packit ce96f2
    pdvector<int_variable *> vars;
Packit ce96f2
    if( proc->findVarsByAll(str, vars) ) {
Packit ce96f2
        if( vars.size() != 1 ) {
Packit ce96f2
            proccontrol_printf("%s[%d]: WARNING: multiple copies of %s found\n",
Packit ce96f2
                    FILE__, __LINE__, str.c_str());
Packit ce96f2
        }else{
Packit ce96f2
            retAddr = vars[0]->getAddress();
Packit ce96f2
        }
Packit ce96f2
    }else{
Packit ce96f2
        proccontrol_printf("%s[%d]: failed to find variable %s\n",
Packit ce96f2
                FILE__, __LINE__, str.c_str());
Packit ce96f2
    }
Packit ce96f2
    return retAddr;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Address PCProcess::getRTEventBreakpointAddr() {
Packit ce96f2
    if( sync_event_breakpoint_addr_ == 0 ) {
Packit ce96f2
        sync_event_breakpoint_addr_ = getVarAddr(this, "DYNINST_break_point_event");
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return sync_event_breakpoint_addr_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Address PCProcess::getRTEventIdAddr() {
Packit ce96f2
    if( sync_event_id_addr_ == 0 ) {
Packit ce96f2
        sync_event_id_addr_ = getVarAddr(this, "DYNINST_synch_event_id");
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return sync_event_id_addr_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Address PCProcess::getRTEventArg1Addr() {
Packit ce96f2
    if( sync_event_arg1_addr_ == 0 ) {
Packit ce96f2
        sync_event_arg1_addr_ = getVarAddr(this, "DYNINST_synch_event_arg1");
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return sync_event_arg1_addr_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Address PCProcess::getRTEventArg2Addr() {
Packit ce96f2
    if( sync_event_arg2_addr_ == 0 ) {
Packit ce96f2
        sync_event_arg2_addr_ = getVarAddr(this, "DYNINST_synch_event_arg2");
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return sync_event_arg2_addr_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Address PCProcess::getRTEventArg3Addr() {
Packit ce96f2
    if( sync_event_arg3_addr_ == 0 ) {
Packit ce96f2
        sync_event_arg3_addr_ = getVarAddr(this, "DYNINST_synch_event_arg3");
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return sync_event_arg3_addr_;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::hasPendingEvents() {
Packit ce96f2
   // Go to the muxer as a final arbiter
Packit ce96f2
   return PCEventMuxer::muxer().hasPendingEvents(this);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::hasRunningSyncRPC() const {
Packit ce96f2
    return (syncRPCThreads_.size() > 0);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::addSyncRPCThread(Thread::ptr thr) {
Packit ce96f2
   proccontrol_printf("%s[%d]: added sync rpc thread %d/%d\n",
Packit ce96f2
                      FILE__, __LINE__, getPid(), thr ? thr->getLWP() : 0);
Packit ce96f2
    syncRPCThreads_.insert(thr);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::removeSyncRPCThread(Thread::ptr thr) {
Packit ce96f2
    proccontrol_printf("%s[%d]: removed sync rpc thread %d/%d\n",
Packit ce96f2
		FILE__, __LINE__, getPid(), thr ? thr->getLWP() : 0);
Packit ce96f2
    syncRPCThreads_.erase(thr);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
bool PCProcess::continueSyncRPCThreads() {
Packit ce96f2
	for(set<Thread::ptr>::iterator i = syncRPCThreads_.begin();
Packit ce96f2
            i != syncRPCThreads_.end(); ++i)
Packit ce96f2
    {
Packit ce96f2
		if(!(*i)) {
Packit ce96f2
			if(!pcProc_->continueProc())
Packit ce96f2
			{
Packit ce96f2
				proccontrol_printf("%s[%d]: failed to continue entire process %d for sync RPC\n",
Packit ce96f2
						FILE__, __LINE__, getPid());
Packit ce96f2
				return false;
Packit ce96f2
			}
Packit ce96f2
		} else if( !(*i)->continueThread() ) {
Packit ce96f2
            proccontrol_printf("%s[%d]: failed to continue thread %d/%d for sync RPC\n",
Packit ce96f2
                    FILE__, __LINE__, getPid(), (*i)->getLWP());
Packit ce96f2
            return false;
Packit ce96f2
        }
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::addTrap(Address from, Address to, codeGen &gen) {
Packit Service 71288b
   gen.invalidate();
Packit Service 71288b
   gen.allocate(4);
Packit Service 71288b
   gen.setAddrSpace(this);
Packit Service 71288b
   gen.setAddr(from);
Packit Service 71288b
   insnCodeGen::generateTrap(gen);
Packit Service 71288b
   trapMapping.addTrapMapping(from, to, true);
Packit Service 71288b
   springboard_cerr << "Generated springboard trap " << hex << from << "->" << to << dec << endl;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::removeTrap(Address from) {
Packit ce96f2
    map<Address, Breakpoint::ptr>::iterator breakIter = 
Packit ce96f2
        installedCtrlBrkpts.find(from);
Packit ce96f2
    if( breakIter == installedCtrlBrkpts.end() ) return;
Packit ce96f2
Packit ce96f2
    if( !pcProc_->rmBreakpoint(from, breakIter->second) ) {
Packit ce96f2
        proccontrol_printf("%s[%d]: failed to remove ctrl transfer breakpoint from 0x%lx\n",
Packit ce96f2
                FILE__, __LINE__, from);
Packit ce96f2
    }
Packit ce96f2
Packit ce96f2
    installedCtrlBrkpts.erase(breakIter);
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
void PCProcess::invalidateMTCache() {
Packit ce96f2
    mt_cache_result_ = not_cached;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
Packit ce96f2
StackwalkSymLookup::StackwalkSymLookup(PCProcess *p)
Packit ce96f2
  : proc_(p)
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
StackwalkSymLookup::~StackwalkSymLookup()
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
bool StackwalkSymLookup::lookupAtAddr(Dyninst::Address addr, std::string &out_name, void* &out_value)
Packit ce96f2
{
Packit ce96f2
  func_instance *func = proc_->findOneFuncByAddr(addr);
Packit ce96f2
  if( func == NULL ) return false;
Packit ce96f2
Packit ce96f2
  // set out_name to the name of the function at this addr
Packit ce96f2
  // set out_value to NULL, this value is no longer used
Packit ce96f2
Packit ce96f2
  out_value = NULL;
Packit ce96f2
Packit ce96f2
  if (func)
Packit ce96f2
  {
Packit ce96f2
    out_name = func->prettyName();
Packit ce96f2
  }
Packit ce96f2
  else
Packit ce96f2
  {
Packit ce96f2
    out_name = string("[UNKNOWN]");
Packit ce96f2
  }
Packit ce96f2
  
Packit ce96f2
  return true;
Packit ce96f2
}
Packit ce96f2
Packit ce96f2
StackwalkInstrumentationHelper::StackwalkInstrumentationHelper(PCProcess *p)
Packit ce96f2
  : proc_(p)
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
StackwalkInstrumentationHelper::~StackwalkInstrumentationHelper()
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
DynFrameHelper::DynFrameHelper(PCProcess *p)
Packit ce96f2
  : FrameFuncHelper(NULL),
Packit ce96f2
  proc_(p)
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
DynFrameHelper::~DynFrameHelper()
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
DynWandererHelper::DynWandererHelper(PCProcess *p)
Packit ce96f2
  : WandererHelper(NULL),
Packit ce96f2
  proc_(p)
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
DynWandererHelper::~DynWandererHelper()
Packit ce96f2
{}
Packit ce96f2
Packit ce96f2
Packit ce96f2