ppc fixes
[dyninst.git] / dyninstAPI / src / dynProcess.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "dynProcess.h"
32 #include "dynThread.h"
33 #include "pcEventHandler.h"
34 #include "pcEventMuxer.h"
35 #include "function.h"
36 #include "os.h"
37 #include "debug.h"
38 #include "instPoint.h"
39 #include "BPatch.h"
40 #include "mapped_module.h"
41 #include "baseTramp.h"
42 #include "registerSpace.h"
43 #include "mapped_object.h"
44 #include "image.h"
45
46 #include "common/src/pathName.h"
47
48 #include "proccontrol/h/PCErrors.h"
49 #include "MemoryEmulator/memEmulator.h"
50 #include <boost/tuple/tuple.hpp>
51
52 #include "symtabAPI/h/SymtabReader.h"
53 #include "patchAPI/h/PatchMgr.h"
54 #include "patchAPI/h/Point.h"
55
56
57 #include <sstream>
58
59 using namespace Dyninst::ProcControlAPI;
60 using std::map;
61 using std::vector;
62 using std::string;
63 using std::stringstream;
64
65 Dyninst::SymtabAPI::SymtabReaderFactory *PCProcess::symReaderFactory_;
66
67 PCProcess *PCProcess::createProcess(const string file, pdvector<string> &argv,
68                                     BPatch_hybridMode analysisMode,
69                                     pdvector<string> &envp,
70                                     const string dir, int stdin_fd, int stdout_fd,
71                                     int stderr_fd)
72 {
73     // Debugging information
74     startup_cerr << "Creating process " << file << " in directory " << dir << endl;
75
76     startup_cerr << "Arguments: (" << argv.size() << ")" << endl;
77     for (unsigned a = 0; a < argv.size(); a++)
78         startup_cerr << "   " << a << ": " << argv[a] << endl;
79
80     startup_cerr << "Environment: (" << envp.size() << ")" << endl;
81     for (unsigned e = 0; e < envp.size(); e++)
82         startup_cerr << "   " << e << ": " << envp[e] << endl;
83
84     startup_printf("%s[%d]: stdin: %d, stdout: %d, stderr: %d\n", FILE__, __LINE__,
85             stdin_fd, stdout_fd, stderr_fd);
86
87     initSymtabReader();
88
89     // Create a full path to the executable
90     string path = createExecPath(file, dir);
91
92     std::map<int, int> fdMap;
93     redirectFds(stdin_fd, stdout_fd, stderr_fd, fdMap);
94
95     if( !setEnvPreload(envp, path) ) {
96         startup_cerr << "Failed to set environment var to preload RT library" << endl;
97         return NULL;
98     }
99
100     // Create the ProcControl process
101     Process::ptr tmpPcProc = Process::createProcess(path, argv, envp, fdMap);
102
103     if( !tmpPcProc ) {
104        cerr << "Failed to create process " << path << endl;
105        const char *lastErrMsg = getLastErrorMsg();
106         startup_printf("%s[%d]: failed to create process for %s: %s\n", __FILE__,
107                 __LINE__, file.c_str(), lastErrMsg);
108         string msg = string("Failed to create process for ") + file +
109            string(": ") + lastErrMsg;
110         showErrorCallback(68, msg.c_str());
111         return NULL;
112     }
113
114     startup_cerr << "Created process " << tmpPcProc->getPid() << endl;
115
116     PCProcess *ret = new PCProcess(tmpPcProc, file, analysisMode);
117     assert(ret);
118     tmpPcProc->setData(ret);
119
120     if( !ret->bootstrapProcess() ) {
121         startup_cerr << "Failed to bootstrap process " << ret->getPid()
122                      << ": terminating..." << endl;
123         ret->terminateProcess();
124
125         delete ret;
126         return NULL;
127     }
128
129     return ret;
130 }
131
132 PCProcess *PCProcess::attachProcess(const string &progpath, int pid,
133                                     BPatch_hybridMode analysisMode)
134 {
135     initSymtabReader();
136
137     startup_cerr << "Attaching to process " << pid << endl;
138     Process::ptr tmpPcProc = Process::attachProcess(pid, progpath);
139
140     if( !tmpPcProc ) {
141         const char *lastErrMsg = getLastErrorMsg();
142         startup_printf("%s[%d]: Failed to attach process %d: %s\n",
143                 __FILE__, __LINE__, pid, lastErrMsg);
144         stringstream msg;
145         msg << "Failed to attach to process " << pid << ": " << lastErrMsg;
146         showErrorCallback(26, msg.str());
147         return NULL;
148     }
149     startup_cerr << "Attached to process " << tmpPcProc->getPid() << endl;
150         
151     PCProcess *ret = new PCProcess(tmpPcProc, analysisMode);
152     assert(ret);
153
154     tmpPcProc->setData(ret);
155
156     ret->runningWhenAttached_ = tmpPcProc->allThreadsRunningWhenAttached();
157     ret->file_ = tmpPcProc->libraries().getExecutable()->getAbsoluteName();
158
159     if( !ret->bootstrapProcess() ) {
160         startup_cerr << "Failed to bootstrap process " << pid 
161                      << ": terminating..." << endl;
162         ret->terminateProcess();
163
164         delete ret;
165         return NULL;
166     }
167
168     return ret;
169 }
170
171 PCProcess *PCProcess::setupForkedProcess(PCProcess *parent, Process::ptr pcProc) {
172     startup_printf("%s[%d]: setting up forked process %d\n",
173             FILE__, __LINE__, pcProc->getPid());
174
175     PCProcess *ret = new PCProcess(parent, pcProc);
176     assert(ret);
177
178     pcProc->setData(ret);
179
180     ret->copyAddressSpace(parent);
181
182     // This requires the AddressSpace be copied from the parent
183     if (parent->tracedSyscalls_)
184       ret->tracedSyscalls_ = new syscallNotification(parent->tracedSyscalls_, ret);
185     else
186       ret->tracedSyscalls_ = NULL;
187
188     // Check if RT library exists in child
189     if( ret->runtime_lib.size() == 0 ) {
190         // Set the RT library name
191         if( !ret->getDyninstRTLibName() ) {
192             startup_printf("%s[%d]: failed to get Dyninst RT lib name\n",
193                     FILE__, __LINE__);
194             delete ret;
195             return NULL;
196         }
197         startup_printf("%s[%d]: Got Dyninst RT libname: %s\n", FILE__, __LINE__,
198                        ret->dyninstRT_name.c_str());
199
200         for(unsigned i = 0; i < ret->mapped_objects.size(); ++i) {
201             const fileDescriptor &desc = ret->mapped_objects[i]->getFileDesc();
202             fileDescriptor tmpDesc(ret->dyninstRT_name,
203                     desc.code(), desc.data(), true);
204             if( desc == tmpDesc ) {
205                 ret->runtime_lib.insert(ret->mapped_objects[i]);
206                 break;
207             }
208         }
209     }
210
211     // TODO hybrid mode stuff
212
213     // Copy signal handlers
214     pdvector<codeRange *> sigHandlers;
215     parent->signalHandlerLocations_.elements(sigHandlers);
216     for(unsigned i = 0; i < sigHandlers.size(); ++i) {
217         signal_handler_location *oldSig = dynamic_cast<signal_handler_location *>(sigHandlers[i]);
218         assert(oldSig);
219         signal_handler_location *newSig = new signal_handler_location(*oldSig);
220         ret->signalHandlerLocations_.insert(newSig);
221     }
222
223     // If required
224     if( !ret->copyDanglingMemory(parent) ) {
225         startup_printf("%s[%d]: failed to copy dangling memory from parent %d to child %d\n",
226                 FILE__, __LINE__, parent->getPid(), ret->getPid());
227         ret->terminateProcess();
228
229         delete ret;
230         return NULL;
231     }
232
233     ret->setInEventHandling(true);
234
235     if( !ret->bootstrapProcess() ) {
236         startup_cerr << "Failed to bootstrap process " << ret->getPid()
237                      << ": terminating..." << endl;
238         ret->terminateProcess();
239
240         delete ret;
241         return NULL;
242     }
243
244     ret->setDesiredProcessState(parent->getDesiredProcessState());
245
246     return ret;
247 }
248
249 PCProcess *PCProcess::setupExecedProcess(PCProcess *oldProc, std::string execPath) {
250     BPatch::bpatch->registerExecCleanup(oldProc, NULL);
251
252     PCProcess *newProc = new PCProcess(oldProc->pcProc_, execPath, oldProc->analysisMode_);
253
254     oldProc->pcProc_->setData(newProc);
255     newProc->setExecing(true);
256
257     if( !newProc->bootstrapProcess() ) {
258         proccontrol_printf("%s[%d]: failed to bootstrap execed process %d\n",
259                 FILE__, __LINE__, newProc->getPid());
260         delete newProc;
261         return NULL;
262     }
263
264     delete oldProc;
265     oldProc = NULL;
266
267     newProc->setInEventHandling(true);
268     //newProc->incPendingEvents();
269
270     BPatch::bpatch->registerExecExit(newProc);
271
272     newProc->setExecing(false);
273     newProc->setDesiredProcessState(ps_running);
274
275     return newProc;
276 }
277
278 PCProcess::~PCProcess() {
279     if( tracedSyscalls_ ) delete tracedSyscalls_;
280     tracedSyscalls_ = NULL;
281
282     if( irpcTramp_ ) delete irpcTramp_;
283     irpcTramp_ = NULL;
284
285     signalHandlerLocations_.clear();
286
287     trapMapping.clearTrapMappings();
288 }
289
290 void PCProcess::initSymtabReader()
291 {
292    //Set SymbolReaderFactory in Stackwalker before create/attach
293    if (!symReaderFactory_) {
294       symReaderFactory_ = new Dyninst::SymtabAPI::SymtabReaderFactory();
295       Dyninst::Stackwalker::Walker::setSymbolReader(symReaderFactory_);
296    }
297 }
298
299 /***************************************************************************
300  **** Runtime library initialization code (Dyninst)                     ****
301  ***************************************************************************/
302
303 /*
304  *
305  * Gratuitously large comment. This diagrams the startup flow of
306  * messages between the mutator and mutatee. Entry points
307  * for create and attach process are both given.
308  *     Mutator           Signal              Mutatee
309  * Create:
310  *     Fork/Exec
311  *                     <-- Trap              Halted in exec (handled by ProcControlAPI)
312  *     Install trap in main
313  *                     <-- Trap              Halted in main
314  *  Attach: (also paused, not in main)
315  *     Install call to dlopen/
316  *     LoadLibrary
317  *                     <-- Trap              In library load
318  *     Set parameters in library
319  *                     <-- Trap              Finished loading
320  *     Restore code and leave paused
321  *     Finalize library
322  *       If finalizing fails, init via iRPC
323  */
324
325 /*
326  * In all cases, the process is left paused at the entry of main
327  * (create) or where it was (attach). No permanent instrumentation
328  * is inserted.
329  */
330
331 bool PCProcess::hasReachedBootstrapState(bootstrapState_t state) const {
332     return state <= bootstrapState_;
333 }
334
335 void PCProcess::setBootstrapState(bootstrapState_t newState) {
336     bootstrapState_ = newState;
337 }
338
339 bool PCProcess::bootstrapProcess() {
340     assert( pcProc_->allThreadsStopped() );
341
342     startup_printf("%s[%d]: attempting to bootstrap process %d\n", 
343             FILE__, __LINE__, getPid());
344
345     if( !wasCreatedViaFork() ) {
346         // Initialize the inferior heaps
347         initializeHeap();
348
349         for(unsigned i = 0; i < mapped_objects.size(); ++i) {
350             addInferiorHeap(mapped_objects[i]);
351         }
352
353         // Create the mapped_objects for the executable and shared libraries
354         if( !createInitialMappedObjects() ) {
355             startup_printf("%s[%d]: bootstrap failed while creating mapped objects\n",
356                     FILE__, __LINE__);
357             return false;
358         }
359     }
360
361     // Create the initial threads
362     createInitialThreads();
363
364     // Initialize StackwalkerAPI
365     if ( !createStackwalker() )
366     {
367       startup_printf("Bootstrap failed while initializing Stackwalker\n");
368       return false;
369     }
370
371     // Insert a breakpoint at the entry point of main (and possibly __libc_start_main)
372     if( !hasPassedMain() ) {
373       startup_printf("%s[%d]: inserting breakpoint at main\n", FILE__, __LINE__);
374         if( !insertBreakpointAtMain() ) {
375             startup_printf("%s[%d]: bootstrap failed while setting a breakpoint at main\n",
376                     FILE__, __LINE__);
377             return false;
378         }
379         startup_printf("%s[%d]: continuing process to breakpoint\n", FILE__, __LINE__);
380         if( !continueProcess() ) {
381             startup_printf("%s[%d]: bootstrap failed while continuing the process\n",
382                     FILE__, __LINE__);
383             return false;
384         }
385
386         while( !hasReachedBootstrapState(bs_readyToLoadRTLib) ) {
387           startup_printf("%s[%d]: waiting for main() loop\n", FILE__, __LINE__);
388             if( isStopped() ) {
389               startup_printf("%s[%d]: We think the process is stopped, continuing\n", FILE__, __LINE__);
390                 if( !continueProcess() ) {
391                     startup_printf("%s[%d]: bootstrap failed while continuing the process\n",
392                             FILE__, __LINE__);
393                     return false;
394                 }
395             }
396
397             if( isTerminated() ) {
398                 bperr("The process exited during startup.  This is likely due to one "
399                       "of two reasons:\n"
400                       "A). The application is mis-built and unable to load.  Try "
401                       "running the application outside of Dyninst and see if it "
402                       "loads properly.\n"
403                       "B). libdyninstAPI_RT is mis-built.  Try loading the library "
404                       "into another application and see if it reports any errors.  "
405                       "Ubuntu users - You may need to rebuild the RT library "
406                       "with the DISABLE_STACK_PROT line enabled in "
407                       "core/make.config.local");
408                 startup_printf("%s[%d]: program exited early, never reached "
409                                "initialized state\n", FILE__, __LINE__);
410                 startup_printf("Error is likely due to the application or RT "
411                                "library having missing symbols or dependencies\n");
412                 return false;
413             }
414
415             startup_printf("%s[%d]: bootstrap waiting for process to initialize\n",
416                     FILE__, __LINE__);
417             if( PCEventMuxer::wait(true) == PCEventMuxer::Error) {
418                 startup_printf("%s[%d]: bootstrap failed to wait for events\n",
419                         FILE__, __LINE__);
420                 return false;
421             }
422         }
423     }else{
424         bootstrapState_ = bs_readyToLoadRTLib;
425     }
426     startup_printf("%s[%d]: process initialized, loading the RT library\n",
427             FILE__, __LINE__);
428
429     // Load the RT library
430     if( !loadRTLib() ) {
431         bperr("Dyninst was unable to load the dyninst runtime library "
432               "into the application.  This may be caused by statically "
433               "linked executables, or by having dyninst linked against a "
434               "different version of libelf than it was built with.");
435         startup_printf("%s[%d]: bootstrap failed to load RT library\n",
436                 FILE__, __LINE__);
437         return false;
438     }
439
440
441     pdvector<int_variable *> obsCostVec;
442     if( !findVarsByAll("DYNINSTobsCostLow", obsCostVec) ) {
443         startup_printf("%s[%d]: failed to find DYNINSTobsCostLow\n",
444                 FILE__, __LINE__);
445         return false;
446     }
447
448     costAddr_ = obsCostVec[0]->getAddress();
449     assert(costAddr_);
450
451     if( !wasCreatedViaFork() ) {
452         // Install system call tracing
453         startup_printf("%s[%d]: installing default Dyninst instrumentation into process %d\n", 
454             FILE__, __LINE__, getPid());
455
456         tracedSyscalls_ = new syscallNotification(this);
457
458         // TODO 
459         // pre-fork and pre-exit should depend on whether a callback is defined
460         // 
461         // This will require checking whether BPatch holds a defined callback and also
462         // adding a way for BPatch enable this instrumentation in all processes when
463         // a callback is registered
464
465         if (!tracedSyscalls_->installPreFork()) {
466             startup_printf("%s[%d]: failed pre-fork notification setup\n",
467                     FILE__, __LINE__);
468             return false;
469         }
470
471         if (!tracedSyscalls_->installPostFork()) {
472             startup_printf("%s[%d]: failed post-fork notification setup\n",
473                     FILE__, __LINE__);
474             return false;
475         }
476
477         if (!tracedSyscalls_->installPreExec()) {
478             startup_printf("%s[%d]: failed pre-exec notification setup\n",
479                     FILE__, __LINE__);
480             return false;
481         }
482
483         if (!tracedSyscalls_->installPostExec()) {
484             startup_printf("%s[%d]: failed post-exec notification setup\n",
485                     FILE__, __LINE__);
486             return false;
487         }
488
489         if (!tracedSyscalls_->installPreExit()) {
490             startup_printf("%s[%d]: failed pre-exit notification setup\n",
491                     FILE__, __LINE__);
492             return false;
493         }
494
495         if (!tracedSyscalls_->installPreLwpExit()) {
496             startup_printf("%s[%d]: failed pre-lwp-exit notification setup\n",
497                     FILE__, __LINE__);
498             return false;
499         }
500
501         // Initialize the tramp guard
502         startup_printf("%s[%d]: initializing tramp guard\n", FILE__, __LINE__);
503         if( !initTrampGuard() ) {
504             startup_printf("%s[%d]: failed to initalize tramp guards\n", FILE__, __LINE__);
505             return false;
506         }
507
508         // Initialize the MT stuff
509         if (multithread_capable()) {
510             if( !instrumentMTFuncs() ) {
511                 startup_printf("%s[%d]: Failed to instrument MT funcs\n",
512                         FILE__, __LINE__);
513                 return false;
514             }
515         }
516     }
517
518     // Register the initial threads
519     startup_printf("%s[%d]: registering initial threads with RT library\n",
520             FILE__, __LINE__);
521     vector<pair<dynthread_t, PCThread *> > toUpdate;
522     for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
523             i != threadsByTid_.end(); ++i)
524     {
525         if( !registerThread(i->second) ) {
526             startup_printf("%s[%d]: bootstrap failed while registering threads with RT library\n",
527                     FILE__, __LINE__);
528             return false;
529         }
530
531         // If the information available has improved, update the mapping to reflect this
532         if( i->first != i->second->getTid() ) toUpdate.push_back(*i);
533     }
534
535     for(vector<pair<dynthread_t, PCThread *> >::iterator i = toUpdate.begin();
536             i != toUpdate.end(); ++i)
537     {
538         threadsByTid_.erase(i->first);
539         threadsByTid_.insert(make_pair(i->second->getTid(), i->second));
540     }
541
542     startup_printf("%s[%d]: finished registering initial threads with RT library\n",
543             FILE__, __LINE__);
544
545     // use heuristics to set hybrid analysis mode
546     if (BPatch_heuristicMode == analysisMode_) {
547         if (getAOut()->parse_img()->codeObject()->defensiveMode()) {
548             analysisMode_ = BPatch_defensiveMode;
549         } else {
550             analysisMode_ = BPatch_normalMode;
551         }
552     }
553
554     bootstrapState_ = bs_initialized;
555     startup_printf("%s[%d]: finished bootstrapping process %d\n", FILE__, __LINE__, getPid());
556
557     return true;
558 }
559
560 bool PCProcess::initTrampGuard() {
561     const std::string vrbleName = "DYNINST_tramp_guards";
562     pdvector<int_variable *> vars;
563     if (!findVarsByAll(vrbleName, vars)) {
564         return false;
565     }
566     assert(vars.size() == 1);
567
568     Address allocedTrampAddr = 0;
569
570     if (getAddressWidth() == 4) {
571         // Don't write directly into trampGuardBase_ as a buffer,
572         //   in case we're on a big endian architechture.
573         unsigned int value;
574         readDataWord((void *)vars[0]->getAddress(), 4, &value, true);
575         allocedTrampAddr = value;
576
577     } else if (getAddressWidth() == 8) {
578         readDataWord((void *)vars[0]->getAddress(), 8, &allocedTrampAddr, true);
579     } else assert(0 && "Incompatible mutatee address width");
580
581     trampGuardBase_ = getAOut()->getDefaultModule()->createVariable("DYNINST_tramp_guard", 
582             allocedTrampAddr, getAddressWidth());
583
584     return true;
585 }
586
587 bool PCProcess::createStackwalker()
588 {
589   using namespace Stackwalker;
590   ProcDebug *procDebug = NULL;
591   StackwalkSymLookup *symLookup = NULL;
592
593   // Create ProcessState
594   if (NULL == (procDebug = ProcDebug::newProcDebug(pcProc_)))
595   {
596     startup_printf("Could not create Stackwalker process state\n");
597     return false;
598   }
599
600   // Create SymbolLookup
601   symLookup = new StackwalkSymLookup(this);
602
603   // Create Walker without default steppers
604   if (NULL == (stackwalker_ = Walker::newWalker(procDebug,
605                                                 NULL,
606                                                 symLookup,
607                                                 false)))
608   {
609     startup_printf("Could not create Stackwalker\n");
610     return false;
611   }
612
613   return createStackwalkerSteppers();
614 }
615
616 void PCProcess::createInitialThreads() {
617     ThreadPool &pcThreads = pcProc_->threads();
618     initialThread_ = PCThread::createPCThread(this, pcThreads.getInitialThread());
619     addThread(initialThread_);
620
621     for(ThreadPool::iterator i = pcThreads.begin(); i != pcThreads.end(); ++i) {
622         if( *i == pcThreads.getInitialThread() ) continue;
623
624         // Wait to create threads until they have user thread information available
625         if( !(*i)->haveUserThreadInfo() ) continue;
626
627         PCThread *newThr = PCThread::createPCThread(this, *i);
628         addThread(newThr);
629     }
630 }
631
632 bool PCProcess::createInitialMappedObjects() {
633     if( file_.empty() ) {
634         startup_printf("%s[%d]: failed to determine executable for process %d\n",
635                 FILE__, __LINE__, getPid());
636         return false;
637     }
638
639     startup_printf("Processing initial shared objects\n");
640     startup_printf("----\n");
641
642     initPatchAPI();
643
644     // Do the a.out first...
645     mapped_object *aout = mapped_object::createMappedObject(pcProc_->libraries().getExecutable(), this, analysisMode_);
646     addASharedObject(aout);
647
648     // Set the RT library name
649     if( !getDyninstRTLibName() ) {
650         startup_printf("%s[%d]: failed to get Dyninst RT lib name\n",
651                 FILE__, __LINE__);
652         return false;
653     }
654
655     // Find main
656     startup_printf("%s[%d]:  leave setAOut/setting main\n", FILE__, __LINE__);
657     setMainFunction();
658
659     // Create mapped objects for any loaded shared libraries
660     const LibraryPool &libraries = pcProc_->libraries();
661     for(LibraryPool::const_iterator i = libraries.begin(); i != libraries.end(); ++i) {
662        // Some platforms don't use the data load address field
663        if ((*i) == libraries.getExecutable()) continue;
664
665        startup_cerr << "Library: " << (*i)->getAbsoluteName() 
666             << hex << " / " << (*i)->getLoadAddress() 
667             << ", " << ((*i)->isSharedLib() ? "<lib>" : "<aout>") << dec << endl;
668
669        mapped_object *newObj = mapped_object::createMappedObject(*i, 
670                                                                  this, analysisMode_);
671        if( newObj == NULL ) {
672            startup_printf("%s[%d]: failed to create mapped object for library %s\n",
673                    FILE__, __LINE__, (*i)->getAbsoluteName().c_str());
674            return false;
675        }
676
677        const fileDescriptor &desc = newObj->getFileDesc();
678        fileDescriptor tmpDesc(dyninstRT_name, desc.code(), desc.data(), true);
679        if( desc == tmpDesc ) {
680           startup_printf("%s[%d]: RT library already loaded, manual loading not necessary\n",
681                          FILE__, __LINE__);
682           runtime_lib.insert(newObj);
683        }
684
685        addASharedObject(newObj);
686     }
687
688
689     startup_printf("----\n");
690
691     return true;
692 }
693
694 // creates an image, creates new resources for a new shared object
695 // adds it to the collection of mapped_objects
696 void PCProcess::addASharedObject(mapped_object *newObj) {
697     assert(newObj);
698
699     addMappedObject(newObj);
700
701     findSignalHandler(newObj);
702
703     startup_printf("%s[%d]: adding shared object %s, addr range 0x%lx to 0x%lx\n",
704             FILE__, __LINE__,
705             newObj->fileName().c_str(),
706             newObj->getBaseAddress(),
707             newObj->getBaseAddress() + newObj->get_size());
708     parsing_printf("Adding shared object %s, addr range 0x%x to 0x%x\n",
709             newObj->fileName().c_str(),
710             newObj->getBaseAddress(),
711             newObj->getBaseAddress() + newObj->get_size());
712
713     if( heapInitialized_ ) {
714         addInferiorHeap(newObj);
715     }else{
716         startup_printf("%s[%d]: skipping check for new inferior heaps, heap uninitialized\n",
717                                        FILE__, __LINE__);
718     }
719 }
720
721 void PCProcess::removeASharedObject(mapped_object *obj) {
722     // Remove from mapped_objects list
723     for (unsigned j = 0; j < mapped_objects.size(); j++) {
724         if (obj == mapped_objects[j]) {
725             mapped_objects[j] = mapped_objects.back();
726             mapped_objects.pop_back();
727             deletedObjects_.push_back(obj);
728             break;
729         }
730     }
731
732     if (runtime_lib.end() != runtime_lib.find(obj)) {
733         runtime_lib.erase( runtime_lib.find(obj) );
734     }
735     proccontrol_printf("Removing shared object %s, addr range 0x%x to 0x%x\n",
736                   obj->fileName().c_str(),
737                   obj->getBaseAddress(),
738                   obj->get_size());
739
740     // TODO Signal handler...
741 }
742
743 bool PCProcess::setAOut(fileDescriptor &desc) {
744     startup_printf("%s[%d]:  enter setAOut\n", FILE__, __LINE__);
745
746     assert(mapped_objects.size() == 0);
747
748     mapped_object *aout = mapped_object::createMappedObject
749                           (desc, this, getHybridMode());
750     if (!aout) {
751         startup_printf("%s[%d]:  fail setAOut\n", FILE__, __LINE__);
752         return false;
753     }
754
755
756     return true;
757 }
758
759 // We keep a vector of all signal handler locations
760 void PCProcess::findSignalHandler(mapped_object *obj) {
761     startup_printf("%s[%d]: findSignalhandler(%p)\n", FILE__, __LINE__, obj);
762     assert(obj);
763
764     int_symbol sigSym;
765     string signame(SIGNAL_HANDLER);
766
767     startup_printf("%s[%d]: findSignalhandler(%p): gettingSymbolInfo\n", FILE__, __LINE__, obj);
768     if (obj->getSymbolInfo(signame, sigSym)) {
769         // Symbols often have a size of 0. This b0rks the codeRange code,
770         // so override to 1 if this is true...
771         unsigned size_to_use = sigSym.getSize();
772         if (!size_to_use) size_to_use = 1;
773
774         startup_printf("%s[%d]: findSignalhandler(%p): addingSignalHandler(%p, %d)\n", FILE__, __LINE__, obj, (void *) sigSym.getAddr(), size_to_use);
775         addSignalHandler(sigSym.getAddr(), size_to_use);
776     }
777
778     startup_printf("%s[%d]: leaving findSignalhandler(%p)\n", FILE__, __LINE__, obj);
779 }
780
781 // NUMBER_OF_MAIN_POSSIBILITIES is defined in image.h
782 void PCProcess::setMainFunction() {
783     assert(!main_function_);
784
785     for (unsigned i = 0; i < NUMBER_OF_MAIN_POSSIBILITIES; i++) {
786         main_function_ = findOnlyOneFunction(main_function_names[i]);
787         if (main_function_) {
788            break;
789         }
790     }
791 }
792  
793 /*
794  * Given an image, add all static heaps inside it
795  * (DYNINSTstaticHeap...) to the buffer pool.
796  */
797 void PCProcess::addInferiorHeap(mapped_object *obj) {
798     pdvector<heapDescriptor> infHeaps;
799     /* Get a list of inferior heaps in the new image */
800     if (obj->getInfHeapList(infHeaps)) {
801         /* Add the vector to the inferior heap structure */
802         for (u_int j=0; j < infHeaps.size(); j++) {
803             infmalloc_printf("%s[%d]: adding heap at 0x%lx to 0x%lx, name %s\n",
804                              FILE__, __LINE__,
805                              infHeaps[j].addr(),
806                              infHeaps[j].addr() + infHeaps[j].size(),
807                              infHeaps[j].name().c_str());
808
809             // platform-specific check to ignore this heap
810             if( skipHeap(infHeaps[j]) ) continue;
811
812             heapItem *h = new heapItem (infHeaps[j].addr(), infHeaps[j].size(),
813                                         infHeaps[j].type(), false);
814
815             infmalloc_printf("%s[%d]: Adding heap from 0x%lx - 0x%lx (%d bytes, type %d) from mapped object %s\n",
816                              FILE__, __LINE__,
817                              infHeaps[j].addr(),
818                              infHeaps[j].addr() + infHeaps[j].size(),
819                              infHeaps[j].size(),
820                              infHeaps[j].type(),
821                              obj->fileName().c_str());
822
823             addHeap(h);
824
825             // set rtlib heaps (runtime_lib hasn't been set yet)
826             if ( ! obj->fullName().compare( dyninstRT_name ) ) {
827                 dyninstRT_heaps_.push_back(h);
828             }
829         }
830     }
831 }
832
833 static const unsigned MAX_THREADS = 32; // Should match MAX_THREADS in RTcommon.c
834
835 bool PCProcess::loadRTLib() {
836     // Check if the RT library has already been loaded
837    if( runtime_lib.size() != 0 ) {
838       startup_printf("%s[%d]: RT library already loaded\n",
839                      FILE__, __LINE__);
840
841       bootstrapState_ = bs_loadedRTLib;
842    }
843    else {
844      if (!pcProc_->addLibrary(dyninstRT_name)) {
845        startup_printf("%s[%d]: failed to start loading RT lib\n", FILE__,
846                       __LINE__);
847        return false;
848      }
849      bootstrapState_ = bs_loadedRTLib;
850      
851      // Process the library load (we hope)
852      PCEventMuxer::handle();
853      
854      if( runtime_lib.size() == 0 ) {
855        startup_printf("%s[%d]: failed to load RT lib\n", FILE__,
856                       __LINE__);
857        return false;
858      }
859      
860      bootstrapState_ = bs_loadedRTLib;
861    }
862    int loaded_ok = 0;
863    pdvector<int_variable *> vars;
864    if (!findVarsByAll("DYNINSThasInitialized", vars)) {
865         startup_printf("%s[%d]: no DYNINSThasInitialized variable\n", FILE__, __LINE__);
866                 return false;
867    }
868    if (!readDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *)&loaded_ok, false)) {
869         startup_printf("%s[%d]: readDataWord failed\n", FILE__, __LINE__);
870         return false;
871    }
872    if(!loaded_ok)
873    {
874            startup_printf("%s[%d]: DYNINSTinit not called automatically\n", FILE__, __LINE__);
875    }
876    startup_printf("%s[%d]: DYNINSTinit succeeded\n", FILE__, __LINE__);
877    return setRTLibInitParams();
878 }
879
880 // Set up the parameters for DYNINSTinit in the RT lib
881 bool PCProcess::setRTLibInitParams() {
882     startup_printf("%s[%d]: welcome to PCProcess::setRTLibInitParams\n",
883             FILE__, __LINE__);
884
885     int pid = P_getpid();
886
887
888     // Now we write these variables into the following global vrbles
889     // in the dyninst library:
890     // libdyninstAPI_RT_init_localCause
891     // libdyninstAPI_RT_init_localPid
892
893     pdvector<int_variable *> vars;
894
895
896     if (!findVarsByAll("libdyninstAPI_RT_init_localPid", vars)) {
897         if (!findVarsByAll("_libdyninstAPI_RT_init_localPid", vars)) {
898             startup_printf("%s[%d]: could not find necessary internal variable\n",
899                     FILE__, __LINE__);
900             return false;
901         }
902     }
903
904     assert(vars.size() == 1);
905     if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *)&pid)) {
906         startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
907         return false;
908     }
909     vars.clear();
910
911     if (!findVarsByAll("libdyninstAPI_RT_init_maxthreads", vars)) {
912         if (!findVarsByAll("_libdyninstAPI_RT_init_maxthreads", vars)) {
913             startup_printf("%s[%d]: could not find necessary internal variable\n",
914                     FILE__, __LINE__);
915             return false;
916         }
917     }
918
919     unsigned numThreads = MAX_THREADS;
920     if( !multithread_capable() ) numThreads = 1;
921
922     assert(vars.size() == 1);
923     if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *) &numThreads)) {
924         startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
925         return false;
926     }
927     vars.clear();
928
929     if (!findVarsByAll("libdyninstAPI_RT_init_debug_flag", vars)) {
930         if (!findVarsByAll("_libdyninstAPI_RT_init_debug_flag", vars)) {
931             startup_printf("%s[%d]: could not find necessary internal variable\n",
932                     FILE__, __LINE__);
933             return false;
934         }
935     }
936
937     assert(vars.size() == 1);
938     if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *) &dyn_debug_rtlib)) {
939         startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
940         return false;
941     }
942     vars.clear();
943     if (dyn_debug_rtlib) {
944         fprintf(stderr, "%s[%d]:  set var in RTlib for debug...\n", FILE__, __LINE__);
945     }
946
947     int static_mode = 0;
948     if (!findVarsByAll("DYNINSTstaticMode", vars)) {
949         if (!findVarsByAll("DYNINSTstaticMode", vars)) {
950             startup_printf("%s[%d]: could not find necessary internal variable\n",
951                     FILE__, __LINE__);
952             return false;
953         }
954     }
955
956     assert(vars.size() == 1);
957     if (!writeDataWord((void*)vars[0]->getAddress(), sizeof(int), (void *) &static_mode)) {
958         startup_printf("%s[%d]: writeDataWord failed\n", FILE__, __LINE__);
959         return false;
960     }
961     vars.clear();
962     return true;
963 }
964
965
966 #if defined(os_vxworks)
967 bool PCProcess::insertBreakpointAtMain() {
968     // We don't need any extra processing of the RTlib.
969     return true;
970 }
971 #else
972 bool PCProcess::insertBreakpointAtMain() {
973     if( main_function_ == NULL ) {
974         startup_printf("%s[%d]: main function not yet found, cannot insert breakpoint\n",
975                 FILE__, __LINE__);
976         return false;
977     }
978     Address addr = main_function_->addr();
979
980     // Create the breakpoint
981     mainBrkPt_ = Breakpoint::newBreakpoint();
982     if( !pcProc_->addBreakpoint(addr, mainBrkPt_) ) {
983         startup_printf("%s[%d]: failed to insert a breakpoint at main entry: 0x%x\n",
984                 FILE__, __LINE__, addr);
985         return false;
986     }
987
988     startup_printf("%s[%d]: added trap to entry of main, address 0x%x\n", 
989             FILE__, __LINE__, addr);
990
991     return true;
992 }
993 #endif
994
995 bool PCProcess::removeBreakpointAtMain() {
996     if( main_function_ == NULL || mainBrkPt_ == Breakpoint::ptr() ) {
997         startup_printf("%s[%d]: no breakpoint set at main function, not removing\n",
998                 FILE__, __LINE__);
999         return true;
1000     }
1001
1002     Address addr = main_function_->addr();
1003
1004     if( !pcProc_->rmBreakpoint(addr, mainBrkPt_) ) {
1005         startup_printf("%s[%d]: failed to remove breakpoint at main entry: 0x%x\n",
1006                 FILE__, __LINE__, addr);
1007         return false;
1008     }
1009     mainBrkPt_ = Breakpoint::ptr();
1010
1011     return true;
1012 }
1013
1014 Breakpoint::ptr PCProcess::getBreakpointAtMain() const {
1015     return mainBrkPt_;
1016 }
1017
1018 // End Runtime library initialization code
1019
1020 bool PCProcess::continueProcess() {
1021     proccontrol_printf("%s[%d]: Continuing process %d\n", FILE__, __LINE__, getPid());
1022
1023     if( !isAttached() || isTerminated() ) {
1024         bpwarn("Warning: continue attempted on non-attached process\n");
1025         return false;
1026     }
1027
1028     // If the process is in event handling, the process should not be continued, 
1029     // the processState_t value will be used after event handling to determine the
1030     // state of the process
1031     if( isInEventHandling() ) {
1032         proccontrol_printf("%s[%d]: process currently in event handling, not continuing\n",
1033                 FILE__, __LINE__);
1034         return true;
1035     }
1036
1037     for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
1038             i != threadsByTid_.end(); ++i)
1039     {
1040         i->second->clearStackwalk();
1041     }
1042
1043     return pcProc_->continueProc();
1044 }
1045
1046 bool PCProcess::stopProcess() {
1047     proccontrol_printf("%s[%d]: Stopping process %d\n", FILE__, __LINE__, getPid());
1048
1049     if( !isAttached() || isTerminated() ) {
1050         bpwarn("Warning: stop attempted on non-attached process\n");
1051         return false;
1052     }
1053
1054     // See comment in continueProcess about this
1055     if( isInEventHandling() ) {
1056         proccontrol_printf("%s[%d]: process currently in event handling, not stopping\n",
1057                 FILE__, __LINE__);
1058         return true;
1059     }
1060
1061     return pcProc_->stopProc();
1062 }
1063
1064 bool PCProcess::terminateProcess() {
1065     if( isTerminated() ) return true;
1066
1067     if( !isAttached() ) return false;
1068
1069     forcedTerminating_ = true;
1070
1071     proccontrol_printf("%s[%d]: Terminating process %d\n", FILE__, __LINE__, getPid());
1072     if( !pcProc_->terminate() ) {
1073         proccontrol_printf("%s[%d]: Failed to terminate process %d\n", FILE__, __LINE__, 
1074                 getPid());
1075         return false;
1076     }
1077     PCEventMuxer::handle();
1078
1079     proccontrol_printf("%s[%d]: finished terminating process %d\n", FILE__, __LINE__, getPid());
1080
1081     return true;
1082 }
1083
1084 bool PCProcess::detachProcess(bool /*cont*/) {
1085     if( isTerminated() ) return true;
1086
1087     if( !isAttached() ) return false;
1088
1089     if (tracedSyscalls_) {
1090         tracedSyscalls_->removePreFork();
1091         tracedSyscalls_->removePostFork();
1092         tracedSyscalls_->removePreExec();
1093         tracedSyscalls_->removePostExec();
1094         tracedSyscalls_->removePreExit();
1095         tracedSyscalls_->removePreLwpExit();
1096     }
1097
1098     // TODO figure out if ProcControl should care about continuing a process
1099     // after detach
1100
1101     // NB: it's possible to get markExited() while handling events for the
1102     // tracedSyscalls_->remove* calls above, clearing pcProc_.
1103     if( isTerminated() || pcProc_->detach() ) {
1104         attached_ = false;
1105         return true;
1106     }
1107
1108     return false;
1109 }
1110
1111 bool PCProcess::isBootstrapped() const {
1112     return bootstrapState_ == bs_initialized;
1113 }
1114
1115 bool PCProcess::isAttached() const {
1116     return attached_;
1117 }
1118
1119 bool PCProcess::isStopped() const {
1120     if( pcProc_ == Process::ptr() ) return true;
1121     return pcProc_->allThreadsStopped();
1122 }
1123
1124 bool PCProcess::isTerminated() const {
1125     if( pcProc_ == Process::ptr() ) return true;
1126     return pcProc_->isTerminated();
1127 }
1128
1129 bool PCProcess::hasExitedNormally() const {
1130     if( pcProc_ == Process::ptr() ) return true;
1131     return pcProc_->isExited();
1132 }
1133
1134 bool PCProcess::isExecing() const {
1135     return execing_;
1136 }
1137
1138 void PCProcess::setExecing(bool b) {
1139     execing_ = b;
1140 }
1141
1142 bool PCProcess::isExiting() const {
1143     return exiting_;
1144 }
1145
1146 void PCProcess::setExiting(bool b) {
1147     exiting_ = b;
1148 }
1149
1150 bool PCProcess::isInEventHandling() const {
1151     return inEventHandling_;
1152 }
1153
1154 void PCProcess::setInEventHandling(bool b) {
1155     inEventHandling_ = b;
1156 }
1157
1158 bool PCProcess::hasReportedEvent() const {
1159     return reportedEvent_;
1160 }
1161
1162 void PCProcess::setReportingEvent(bool b) {
1163     reportedEvent_ = b;
1164 }
1165
1166 void PCProcess::markExited() {
1167     pcProc_ = Process::ptr();
1168 }
1169
1170 void PCProcess::writeDebugDataSpace(void *inTracedProcess, u_int amount,
1171         const void *inSelf)
1172 {
1173     static unsigned write_no = 0;
1174
1175     if( !dyn_debug_write ) return;
1176
1177     write_printf("const unsigned char ");
1178     switch(getArch()) {
1179         case Arch_x86:
1180             write_printf("x86_");
1181             break;
1182         case Arch_x86_64:
1183             write_printf("amd64_");
1184             break;
1185         case Arch_ppc32:
1186         case Arch_ppc64:
1187             write_printf("power_");
1188             break;
1189         default:
1190             write_printf("unknown_");
1191             break;
1192     }
1193     write_printf("%lx_%d_%u[] = {", inTracedProcess, getPid(), write_no++);
1194
1195     const unsigned char *buffer = (const unsigned char *)inSelf;
1196     for(unsigned i = 0; i < amount-1; ++i) {
1197         if( amount && (i % 10 == 0) ) write_printf("\n");
1198         write_printf("0x%02hhx, ", buffer[i]);
1199     }
1200     if(amount) write_printf("0x%02hhx", buffer[amount-1]);
1201     write_printf("\n};\n");
1202 }
1203
1204 bool PCProcess::writeDataSpace(void *inTracedProcess, u_int amount,
1205                                const void *inSelf) {
1206     if( isTerminated() ) {
1207        cerr << "Writing to terminated process!" << endl;
1208        return false;
1209     }
1210     bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf,
1211                                        amount);
1212
1213     if( BPatch_defensiveMode == proc()->getHybridMode() && !result ) {
1214         // the write may have failed because we've removed write permissions
1215         // from the page, remove them and try again
1216
1217         PCMemPerm origRights, rights(true, true, true);
1218         if (!pcProc_->setMemoryAccessRights((Address)inTracedProcess,
1219                                             amount, rights, origRights)) {
1220             cerr << "Fail to set memory permissions!" << endl;
1221             return false;
1222         }
1223
1224         /*
1225         int oldRights = pcProc_->setMemoryAccessRights((Address)inTracedProcess,
1226                                                        amount,
1227                                                        PAGE_EXECUTE_READWRITE);
1228
1229         if( oldRights == PAGE_EXECUTE_READ || oldRights == PAGE_READONLY ) {
1230         */
1231
1232         if( origRights.isRX() || origRights.isR() ) {
1233             result = pcProc_->writeMemory((Address)inTracedProcess, inSelf,
1234                                           amount);
1235
1236             /*
1237             if( pcProc_->setMemoryAccessRights((Address)inTracedProcess,
1238                                                amount, oldRights) == false ) {
1239             */
1240
1241             PCMemPerm tmpRights;
1242             if( !pcProc_->setMemoryAccessRights((Address)inTracedProcess,
1243                                                 amount, origRights, tmpRights)) {
1244                 result = false;
1245             }
1246         } else {
1247             result = false;
1248         }
1249     }
1250
1251     if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
1252
1253     return result;
1254 }
1255
1256 bool PCProcess::writeDataWord(void *inTracedProcess,
1257                    u_int amount, const void *inSelf) 
1258 {
1259     if( isTerminated() ) return false;
1260
1261     // XXX ProcControlAPI should support word writes in the future
1262     bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf, amount);
1263     if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
1264     return result;
1265 }
1266
1267 bool PCProcess::readDataSpace(const void *inTracedProcess, u_int amount,
1268                    void *inSelf, bool displayErrMsg)
1269 {
1270     if( isTerminated() ) return false;
1271
1272     bool result = pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
1273     if( !result && displayErrMsg ) {
1274         stringstream msg;
1275         msg << "System error: unable to read " << amount << "@" 
1276             << Address_str((Address)inTracedProcess) << " from process data space: "
1277             << getLastErrorMsg() << "(pid = " << getPid() << ")";
1278        showErrorCallback(38, msg.str()); 
1279     }
1280     return result;
1281 }
1282
1283 bool PCProcess::readDataWord(const void *inTracedProcess, u_int amount,
1284                   void *inSelf, bool displayErrMsg)
1285 {
1286     if( isTerminated() ) return false;
1287
1288     // XXX see writeDataWord above
1289     bool result = pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
1290     if( !result && displayErrMsg ) {
1291         stringstream msg;
1292         msg << "System error: unable to read " << amount << "@" 
1293             << Address_str((Address)inTracedProcess) << " from process data space: "
1294             << getLastErrorMsg() << "(pid = " << getPid() << ")";
1295        showErrorCallback(38, msg.str());
1296     }
1297
1298     return result;
1299 }
1300
1301 bool PCProcess::writeTextSpace(void *inTracedProcess, u_int amount, const void *inSelf)
1302 {
1303     if( isTerminated() ) return false;
1304     bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf, amount);
1305
1306     if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
1307
1308     return result;
1309 }
1310
1311 bool PCProcess::writeTextWord(void *inTracedProcess, u_int amount, const void *inSelf)
1312 {
1313     if( isTerminated() ) return false;
1314
1315     // XXX see writeDataWord above
1316     bool result = pcProc_->writeMemory((Address)inTracedProcess, inSelf, amount);
1317
1318     if( result && dyn_debug_write ) writeDebugDataSpace(inTracedProcess, amount, inSelf);
1319
1320     return result;
1321 }
1322
1323 bool PCProcess::readTextSpace(const void *inTracedProcess, u_int amount,
1324                    void *inSelf)
1325 {
1326     if( isTerminated() ) return false;
1327
1328     return pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
1329 }
1330
1331 bool PCProcess::readTextWord(const void *inTracedProcess, u_int amount,
1332                   void *inSelf)
1333 {
1334     if( isTerminated() ) return false;
1335
1336     // XXX see writeDataWord above
1337     return pcProc_->readMemory(inSelf, (Address)inTracedProcess, amount);
1338 }
1339
1340 PCThread *PCProcess::getInitialThread() const {
1341     return initialThread_;
1342 }
1343
1344 PCThread *PCProcess::getThread(dynthread_t tid) const {
1345     map<dynthread_t, PCThread *>::const_iterator findIter;
1346     findIter = threadsByTid_.find(tid);
1347     if( findIter == threadsByTid_.end() ) {
1348         return NULL;
1349     }
1350
1351     return findIter->second;
1352 }
1353
1354 bool PCProcess::removeThread(dynthread_t tid) {
1355     map<dynthread_t, PCThread *>::iterator result;
1356     result = threadsByTid_.find(tid);
1357
1358     if( result == threadsByTid_.end() ) return false;
1359
1360     PCThread *toDelete = result->second;
1361
1362     if( !unregisterThread(toDelete) ) return false;
1363
1364     threadsByTid_.erase(result);
1365
1366     if( toDelete == initialThread_ ) {
1367         initialThread_ = NULL;
1368     }
1369
1370     toDelete->markExited();
1371
1372     // Note: don't delete the thread here, the BPatch_thread takes care of it
1373     proccontrol_printf("%s[%d]: removed thread %lu from process %d\n",
1374             FILE__, __LINE__, toDelete->getLWP(), getPid());
1375     return true;
1376 }
1377 extern Address getVarAddr(PCProcess *proc, std::string str);
1378
1379
1380 bool PCProcess::registerThread(PCThread *thread) {      
1381    Address tid = (Address) thread->getTid();
1382    Address index = thread->getIndex();
1383    
1384    Address tmp = 0;
1385    unsigned ptrsize = getAddressWidth();
1386
1387    if (tid == (Address) -1) return true;
1388    if (index == (Address) -1) return true;
1389
1390    if (!initializeRegisterThread()) {
1391       startup_printf("%s[%d]: initializeRegisterThread failed\n",
1392                      FILE__, __LINE__);
1393            
1394            return false;
1395    }
1396    // Must match the "hash" algorithm used in the RT lib
1397    int working = (tid % thread_hash_size);
1398    while(1) {
1399       tmp = 0;
1400       if (!readDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &tmp, false)) {
1401          startup_printf("%s[%d]: Failed to read index slot, base 0x%lx, active 0x%lx\n", FILE__, __LINE__,
1402                         thread_hash_indices, thread_hash_indices + (working * ptrsize));
1403          return false;
1404       }
1405       startup_printf("%s[%d]: value of tid in slot %p is 0x%lx\n",
1406                      FILE__, __LINE__, thread_hash_indices + (working * ptrsize), tmp);
1407       if (ptrsize == 4 && tmp == 0xffffffff) {
1408          int index_int = (int) index;
1409          int tid_int = (int) tid;
1410          startup_printf("%s[%d]: writing %d to %p and 0x%x to %p\n",
1411                         FILE__, __LINE__, index_int, thread_hash_indices + (working * ptrsize),
1412                         tid_int, thread_hash_tids + (working * ptrsize));
1413          writeDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &index_int);
1414          writeDataWord(( void *)(thread_hash_tids + (working * ptrsize)), ptrsize, &tid_int);
1415          break;
1416       }
1417       else if (ptrsize == 8 && tmp == (Address)-1)  {
1418          writeDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &index);
1419          writeDataWord(( void *)(thread_hash_tids + (working * ptrsize)), ptrsize, &tid);
1420          break;
1421       }
1422       working++;
1423       if (working == thread_hash_size) working = 0;
1424       if (working == (int) (tid % thread_hash_size)) {
1425          startup_printf("%s[%d]: Failed to find empty tid slot\n", FILE__, __LINE__);
1426          return false;
1427       }
1428    }
1429    return true;
1430 }
1431 bool PCProcess::unregisterThread(PCThread *thread) {    
1432    return true;
1433    Address tid = (Address) thread->getTid();
1434    Address index = thread->getIndex();
1435    Address tmp = 0;
1436    
1437    unsigned ptrsize = getAddressWidth();
1438    if (tid == (Address) -1) return true;
1439    if (index == (Address) -1) return true;
1440
1441    initializeRegisterThread();
1442
1443    // Must match the "hash" algorithm used in the RT lib
1444    int working = tid % thread_hash_size;
1445    while(1) {
1446       tmp = 0;
1447       if (!readDataWord((void *)(thread_hash_tids + (working * ptrsize)), ptrsize, &tmp, false)) return false;
1448       if (tmp == tid) {
1449          // Zero it out
1450          tmp = (Address) -1;
1451          writeDataWord(( void *)(thread_hash_indices + (working * ptrsize)), ptrsize, &tmp);
1452          break;
1453       }
1454       working++;
1455       if (working == thread_hash_size) working = 0;
1456       if (working == (int) (tid % thread_hash_size)) return false;
1457    }
1458    return true;
1459 }
1460
1461 bool PCProcess::initializeRegisterThread() {
1462 //   if (thread_hash_tids) return true;
1463
1464    unsigned ptrsize = getAddressWidth();
1465    
1466    Address tidPtr = getVarAddr(this, "DYNINST_thread_hash_tids");
1467    if (!tidPtr) return false;
1468    Address indexPtr = getVarAddr(this, "DYNINST_thread_hash_indices");
1469    if (!indexPtr) return false;
1470    Address sizePtr = getVarAddr(this, "DYNINST_thread_hash_size");
1471    if (!sizePtr) return false;
1472    
1473    if (!readDataWord((const void *)tidPtr, ptrsize, &thread_hash_tids, false)) return false;
1474
1475    if (!readDataWord((const void *)indexPtr, ptrsize, &thread_hash_indices, false)) return false;
1476
1477    if (!readDataWord((const void *)sizePtr, sizeof(int), &thread_hash_size, false)) return false;
1478
1479    return true;
1480 }
1481
1482
1483
1484 void PCProcess::addThread(PCThread *thread) {
1485     pair<map<dynthread_t, PCThread *>::iterator, bool> result;
1486     result = threadsByTid_.insert(make_pair(thread->getTid(), thread));
1487
1488     assert( result.second && "Thread already in collection of threads" );
1489     proccontrol_printf("%s[%d]: added thread %lu to process %d\n",
1490             FILE__, __LINE__, thread->getLWP(), getPid());
1491 }
1492
1493 void PCProcess::getThreads(vector<PCThread* > &threads) const {
1494     for(map<dynthread_t, PCThread *>::const_iterator i = threadsByTid_.begin();
1495             i != threadsByTid_.end(); ++i)
1496     {
1497         threads.push_back(i->second);
1498     }
1499 }
1500
1501 bool PCProcess::wasRunningWhenAttached() const {
1502     return runningWhenAttached_;
1503 }
1504
1505 bool PCProcess::wasCreatedViaAttach() const {
1506     return createdViaAttach_;
1507 }
1508
1509 bool PCProcess::wasCreatedViaFork() const {
1510     return parent_ != NULL;
1511 }
1512
1513 unsigned PCProcess::getMemoryPageSize() const {
1514    assert(pcProc_);
1515    return pcProc_->getMemoryPageSize();
1516 }
1517
1518 int PCProcess::getPid() const {
1519     return savedPid_;
1520 }
1521
1522 int PCProcess::incrementThreadIndex() {
1523     int ret = curThreadIndex_;
1524     curThreadIndex_++;
1525     return ret;
1526 }
1527
1528 unsigned PCProcess::getAddressWidth() const {
1529     if( mapped_objects.size() > 0 ) {
1530         return mapped_objects[0]->parse_img()->codeObject()->cs()->getAddressWidth();
1531     }
1532
1533     // We can call this before we've attached...best effort guess
1534     return sizeof(Address);
1535 }
1536
1537 PCEventHandler * PCProcess::getPCEventHandler() const {
1538     return eventHandler_;
1539 }
1540
1541 bool PCProcess::walkStacks(pdvector<pdvector<Frame> > &stackWalks) {
1542     bool needToContinue = false;
1543     bool retval = true;
1544
1545     // sanity check
1546         if( stackwalker_ == NULL ) return false;
1547
1548     // Process needs to be stopped before doing a stackwalk
1549     if( !isStopped() ) {
1550         needToContinue = true;
1551         if( !stopProcess() ) {
1552             proccontrol_printf("%s[%d]: failed to stop process for stackwalking\n",
1553                     FILE__, __LINE__);
1554             return false;
1555         }
1556     }
1557
1558     for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
1559            i != threadsByTid_.end(); ++i)
1560     {
1561         PCThread *curThr = i->second;
1562
1563         pdvector<Frame> stackWalk;
1564         if( !curThr->walkStack(stackWalk) ) {
1565             retval = false;
1566             proccontrol_printf("%s[%d]: failed to walk stack for thread 0x%lx(%d)\n",
1567                     FILE__, __LINE__,
1568                     curThr->getTid(), curThr->getLWP());
1569         }else{
1570             stackWalks.push_back(stackWalk);
1571         }
1572     }
1573
1574     if( needToContinue ) {
1575         if( !continueProcess() ) {
1576             proccontrol_printf("%s[%d]: failed to continue process after performing stackwalking\n",
1577                     FILE__, __LINE__);
1578             return false;
1579         }
1580     }
1581
1582     return retval;
1583 }
1584
1585 // Return a vector (possibly with one object) of active frames in the process
1586 bool PCProcess::getAllActiveFrames(pdvector<Frame> &activeFrames) {
1587     Frame active;
1588     if( threadsByTid_.size() == 0 ) return false;
1589
1590     for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
1591             i != threadsByTid_.end(); ++i)
1592     {
1593         Frame active = i->second->getActiveFrame();
1594         if( active == Frame() ) return false;
1595         activeFrames.push_back(active);
1596     }
1597
1598     return true;
1599 }
1600
1601 //
1602 // dynamic inferior heap stuff
1603 //
1604
1605 #if defined(os_vxworks)
1606 #include "vxworks.h"
1607 #define HEAP_DYN_BUF_SIZE (0x4000)
1608 #else
1609 #define HEAP_DYN_BUF_SIZE (0x100000)
1610 #endif
1611
1612 static const Address ADDRESS_LO = ((Address)0);
1613 static const Address ADDRESS_HI = ((Address)~((Address)0));
1614
1615 Address PCProcess::inferiorMalloc(unsigned size, inferiorHeapType type,
1616                                   Address near_, bool *err) 
1617 {
1618    if(bootstrapState_ <= bs_readyToLoadRTLib) {
1619       return 0;
1620    }
1621
1622     enum MallocAttempt {
1623         AsIs = 0,
1624         DeferredFree = 1, // compact free blocks
1625         NewSegment1MBConstrained = 2, // allocate new segment (1 MB, constrained)
1626         NewSegmentSizedConstrained = 3, // allocate new segment (sized, constrained)
1627         RemoveRangeConstraints = 4,
1628         NewSegment1MBUnconstrained = 5,
1629         NewSegmentSizedUnconstrained = 6,
1630         DeferredFreeAgain = 7 // why again?
1631     };
1632
1633     Address ret = 0;
1634     if (err) *err = false;
1635
1636     if( size <= 0 ) {
1637         infmalloc_printf("%s[%d]: inferior malloc cannot be <= 0\n",
1638                 FILE__, __LINE__);
1639         if( err ) *err = true;
1640         return 0;
1641     }
1642
1643     // allocation range
1644     Address lo = ADDRESS_LO; // Should get reset to a more reasonable value
1645     Address hi = ADDRESS_HI; // Should get reset to a more reasonable value
1646
1647     //#if defined(cap_dynamic_heap)
1648     inferiorMallocAlign(size); // align size
1649     // Set the lo/hi constraints (if necessary)
1650     inferiorMallocConstraints(near_, lo, hi, type);
1651     //#else
1652     /* align to cache line size (32 bytes on SPARC) */
1653     //size = (size + 0x1f) & ~0x1f;
1654     //#endif
1655
1656     infmalloc_printf("%s[%d]: inferiorMalloc entered; size %d, type %d, near 0x%lx (0x%lx to 0x%lx)\n",
1657                      FILE__, __LINE__, size, type, near_, lo, hi);
1658
1659     // find free memory block (multiple attempts)
1660     int freeIndex = -1;
1661     int ntry = 0;
1662     for (ntry = 0; freeIndex == -1; ntry++) {
1663         switch(ntry) {
1664         case AsIs: 
1665             break;
1666             //#if defined(cap_dynamic_heap)
1667         case DeferredFree: 
1668             infmalloc_printf("%s[%d]: garbage collecting and compacting\n",
1669                              FILE__, __LINE__);
1670             inferiorFreeCompact();
1671             break;
1672         case NewSegment1MBConstrained: 
1673             infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
1674                              FILE__, __LINE__, HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
1675             inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
1676             break;
1677         case NewSegmentSizedConstrained: 
1678             infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
1679                              FILE__, __LINE__, size, size, lo, hi);
1680             inferiorMallocDynamic(size, lo, hi);
1681             break;
1682         case RemoveRangeConstraints: 
1683             infmalloc_printf("%s[%d]: inferiorMalloc: removing range constraints\n",
1684                              FILE__, __LINE__);
1685             lo = ADDRESS_LO;
1686             hi = ADDRESS_HI;
1687             if (err) {
1688                 infmalloc_printf("%s[%d]: error in inferiorMalloc\n", FILE__, __LINE__);
1689                 *err = true;
1690             }
1691             break;
1692         case NewSegment1MBUnconstrained: 
1693             infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
1694                              FILE__, __LINE__, HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
1695             inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
1696             break;
1697         case NewSegmentSizedUnconstrained: 
1698             infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
1699                              FILE__, __LINE__, size, size, lo, hi);
1700             inferiorMallocDynamic(size, lo, hi);
1701             break;
1702         case DeferredFreeAgain: 
1703             infmalloc_printf("%s[%d]: inferiorMalloc: recompacting\n", FILE__, __LINE__);
1704             inferiorFreeCompact();
1705             break;
1706             //#else /* !(cap_dynamic_heap) */
1707             //case DeferredFree: // deferred free, compact free blocks
1708             //inferiorFreeCompact();
1709             //break;
1710             //#endif /* cap_dynamic_heap */
1711
1712         default: // error - out of memory
1713             infmalloc_printf("%s[%d]: failed to allocate memory\n", FILE__, __LINE__);
1714             if( err ) *err = true;
1715             return 0;
1716         }
1717
1718         ret = inferiorMallocInternal(size, lo, hi, type);
1719         if (ret) break;
1720     }
1721     infmalloc_printf("%s[%d]: inferiorMalloc, returning address 0x%lx\n", FILE__, __LINE__, ret);
1722     return ret;
1723 }
1724
1725 void PCProcess::inferiorFree(Dyninst::Address item) {
1726     inferiorFreeInternal(item);
1727 }
1728
1729 bool PCProcess::inferiorRealloc(Dyninst::Address item, unsigned int newSize) {
1730         if(bootstrapState_ <= bs_readyToLoadRTLib) {
1731       return true;
1732    }
1733    return inferiorReallocInternal(item, newSize);
1734 }
1735
1736 static
1737 void alignUp(int &val, int align) {
1738     assert(val >= 0);
1739     assert(align >= 0);
1740
1741     if (val % align != 0) {
1742         val = ((val / align) + 1) * align;
1743     }
1744 }
1745
1746 bool PCProcess::inferiorMallocDynamic(int size, Address lo, Address hi) {
1747     const int MallocFailed = 0;
1748     const int UnalignedBuffer = -1;
1749
1750     infmalloc_printf("%s[%d]: entering inferiorMallocDynamic\n", FILE__, __LINE__);
1751
1752     // word-align buffer size
1753     // (see "DYNINSTheap_align" in rtinst/src/RTheap-<os>.c)
1754     alignUp(size, 4);
1755     // build AstNode for "DYNINSTos_malloc" call
1756     std::string callee = "DYNINSTos_malloc";
1757     pdvector<AstNodePtr> args(3);
1758     args[0] = AstNode::operandNode(AstNode::Constant, (void *)(Address)size);
1759     args[1] = AstNode::operandNode(AstNode::Constant, (void *)lo);
1760     args[2] = AstNode::operandNode(AstNode::Constant, (void *)hi);
1761     AstNodePtr code = AstNode::funcCallNode(callee, args);
1762
1763     // issue RPC and wait for result
1764     bool wasRunning = !isStopped();
1765
1766     proccontrol_printf("%s[%d]: running inferiorMalloc via iRPC on process %d\n",
1767             FILE__, __LINE__, getPid());
1768
1769     Address result = 0;
1770     if( !postIRPC(code,
1771                   NULL, // only care about the result
1772                   wasRunning, // run when finished?
1773                   NULL, // no specific thread
1774                   true, // wait for completion
1775                   (void **)&result,
1776                   false, // internal iRPC
1777                   true) ) // is a memory allocation RPC
1778     {
1779         infmalloc_printf("%s[%d]: failed to post iRPC for inferior malloc\n",
1780                 FILE__, __LINE__);
1781         return false;
1782     }
1783     proccontrol_printf("%s[%d]: inferiorMalloc via iRPC returned 0x%lx\n",
1784             FILE__, __LINE__, result);
1785
1786     switch ((int)result) {
1787         case MallocFailed:
1788             infmalloc_printf("%s[%d]: DYNINSTos_malloc() failed\n",
1789                                FILE__, __LINE__);
1790             return false;
1791         case UnalignedBuffer:
1792             infmalloc_printf("%s[%d]: DYNINSTos_malloc(): unaligned buffer size\n",
1793                                FILE__, __LINE__);
1794             return false;
1795         default:
1796             // add new segment to buffer pool
1797             heapItem *h = new heapItem(result, size, getDynamicHeapType(),
1798                     true, HEAPfree);
1799             addHeap(h);
1800             break;
1801     }
1802
1803     return true;
1804 }
1805
1806 // A copy of the BPatch-level instrumentation installer
1807 void PCProcess::installInstrRequests(const pdvector<instMapping*> &requests) {
1808     if (requests.size() == 0) {
1809         return;
1810     }
1811
1812     // Instrumentation is now generated on a per-function basis, while
1813     // the requests are per-inst, not per-function. So 
1814     // accumulate functions, then generate afterwards. 
1815
1816     vector<func_instance *> instrumentedFuncs;
1817
1818     for (unsigned lcv=0; lcv < requests.size(); lcv++) {
1819       inst_printf("%s[%d]: handling request %d of %d\n", FILE__, __LINE__, lcv+1, requests.size());
1820
1821         instMapping *req = requests[lcv];
1822         pdvector<miniTramp *> minis;
1823         
1824         if(!multithread_capable() && req->is_MTonly())
1825             continue;
1826         
1827         pdvector<func_instance *> matchingFuncs;
1828         
1829         if (!findFuncsByAll(req->func, matchingFuncs, req->lib)) {
1830             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());
1831             return;
1832         }
1833         else {
1834             inst_printf("%s[%d]: found %d functions matching %s (lib %s), instrumenting...\n",
1835                         FILE__, __LINE__, matchingFuncs.size(), req->func.c_str(), req->lib.c_str());
1836         }
1837
1838         for (unsigned funcIter = 0; funcIter < matchingFuncs.size(); funcIter++) {
1839            func_instance *func = matchingFuncs[funcIter];
1840            if (!func) {
1841               inst_printf("%s[%d]: null int_func detected\n",
1842                           FILE__,__LINE__);
1843               continue;  // probably should have a flag telling us whether errors
1844            }
1845
1846            inst_printf("%s[%d]: Instrumenting %s at 0x%lx, offset 0x%lx in %s\n",
1847                        FILE__, __LINE__, 
1848                        func->symTabName().c_str(),
1849                        func->addr(),
1850                        func->addr() - func->obj()->codeBase(),
1851                        func->obj()->fullName().c_str());
1852             
1853            // should be silently handled or not
1854            AstNodePtr ast;
1855            if ((req->where & FUNC_ARG) && req->args.size()>0) {
1856               ast = AstNode::funcCallNode(req->inst, 
1857                                           req->args,
1858                                           this);
1859            }
1860            else {
1861               pdvector<AstNodePtr> def_args;
1862               def_args.push_back(AstNode::operandNode(AstNode::Constant,
1863                                                       (void *)0));
1864               ast = AstNode::funcCallNode(req->inst,
1865                                           def_args);
1866            }
1867            // We mask to strip off the FUNC_ARG bit...
1868            std::vector<Point *> points;
1869            switch ( ( req->where & 0x7) ) {
1870               case FUNC_EXIT:
1871                  mgr()->findPoints(Dyninst::PatchAPI::Scope(func),
1872                                    Point::FuncExit,
1873                                    std::back_inserter(points));
1874                  break;
1875               case FUNC_ENTRY:
1876                  mgr()->findPoints(Dyninst::PatchAPI::Scope(func),
1877                                    Point::FuncEntry,
1878                                    std::back_inserter(points));
1879                  break;
1880               case FUNC_CALL:
1881                  mgr()->findPoints(Dyninst::PatchAPI::Scope(func),
1882                                    Point::PreCall,
1883                                    std::back_inserter(points));
1884                  break;
1885               default:
1886                  fprintf(stderr, "Unknown where: %d\n",
1887                          req->where);
1888                  break;
1889            } // switch
1890            inst_printf("%s[%d]: found %d points to instrument\n", FILE__, __LINE__, points.size());
1891            for (std::vector<Point *>::iterator iter = points.begin();
1892                 iter != points.end(); ++iter) {
1893               Dyninst::PatchAPI::Instance::Ptr inst = (req->order == orderFirstAtPoint) ? 
1894                  (*iter)->pushFront(ast) :
1895                  (*iter)->pushBack(ast);
1896               if (inst) {
1897                  if (!req->useTrampGuard) inst->disableRecursiveGuard();
1898                  req->instances.push_back(inst);
1899               }
1900               else {
1901                  fprintf(stderr, "%s[%d]:  failed to addInst here\n", FILE__, __LINE__);
1902               }
1903            }        } // matchingFuncs        
1904         
1905     } // requests
1906     relocate();
1907     return;
1908 }
1909
1910 static const unsigned MAX_IRPC_SIZE = 0x100000;
1911
1912
1913 bool PCProcess::postIRPC(void* buffer, int size, void* userData, bool runProcessWhenDone,
1914                          PCThread* thread, bool synchronous, void** result,
1915                          bool userRPC, bool isMemAlloc, Address addr)
1916 {
1917    return postIRPC_internal(buffer,
1918                             size,
1919                             size,
1920                             REG_NULL,
1921                             addr,
1922                             userData,
1923                             runProcessWhenDone,
1924                             thread,
1925                             synchronous,
1926                             userRPC,
1927                             isMemAlloc,
1928                             result);    
1929 }
1930
1931 bool PCProcess::postIRPC(AstNodePtr action, void *userData, 
1932                          bool runProcessWhenDone, PCThread *thread, bool synchronous,
1933                          void **result, bool userRPC, bool isMemAlloc, Address addr)
1934 {   
1935    // Generate the code for the iRPC
1936    codeGen irpcBuf(MAX_IRPC_SIZE);
1937    irpcBuf.setAddrSpace(this);
1938    irpcBuf.setRegisterSpace(registerSpace::irpcRegSpace(proc()));
1939    irpcBuf.beginTrackRegDefs();
1940    irpcBuf.setThread(thread);
1941    
1942 #if defined(bug_syscall_changepc_rewind)
1943    // Reported by SGI, during attach to a process in a system call:
1944    
1945    // Insert eight NOP instructions before the actual call to dlopen(). Loading
1946    // the runtime library when the mutatee was in a system call will sometimes
1947    // cause the process to (on IA32 anyway) execute the instruction four bytes
1948    // PREVIOUS to the PC we actually set here. No idea why. Prepending the
1949    // actual dlopen() call with eight NOP instructions insures this doesn't
1950    // really matter. Eight was selected rather than four because I don't know
1951    // if x86-64 does the same thing (and jumps eight bytes instead of four).
1952    
1953    // We will put in <addr width> rather than always 8; this will be 4 on x86 and
1954    // 32-bit AMD64, and 8 on 64-bit AMD64.
1955    irpcBuf.fill(proc()->getAddressWidth(), codeGen::cgNOP);
1956 #endif
1957
1958    irpcTramp_->setIRPCAST(action);
1959    
1960    // Create a stack frame for the RPC
1961    if( !irpcTramp_->generateSaves(irpcBuf, irpcBuf.rs()) ) {
1962       proccontrol_printf("%s[%d]: failed to generate saves via baseTramp\n",
1963                          FILE__, __LINE__);
1964       return false;
1965    }
1966    
1967    Register resultReg = REG_NULL;
1968    if( !action->generateCode(irpcBuf, false, resultReg) ) {
1969       proccontrol_printf("%s[%d]: failed to generate code from AST\n",
1970                          FILE__, __LINE__);
1971       return false;
1972    }
1973
1974     // Note: we should not do a corresponding baseTramp restore here:
1975     // 1) It isn't necessary because ProcControl will restore the
1976     //    registers
1977     // 2) We need to be able to read registers to get the result of the iRPC
1978     //    If we restore, we can't do that
1979
1980     // Emit the trailer for the iRPC
1981
1982     // breakOffset: where the irpc ends
1983     unsigned breakOffset = irpcBuf.used();
1984     insnCodeGen::generateTrap(irpcBuf);
1985     insnCodeGen::generateTrap(irpcBuf);
1986
1987     irpcBuf.endTrackRegDefs();
1988
1989     return postIRPC_internal(irpcBuf.start_ptr(),
1990                              irpcBuf.used(),
1991                              breakOffset,
1992                              resultReg,
1993                              addr,
1994                              userData,
1995                              runProcessWhenDone,
1996                              thread,
1997                              synchronous,
1998                              userRPC,
1999                              isMemAlloc,
2000                              result);    
2001 }
2002
2003 // DEBUG
2004 #include "instructionAPI/h/InstructionDecoder.h"
2005
2006 bool PCProcess::postIRPC_internal(void *buf,
2007                                   unsigned size,
2008                                   unsigned breakOffset,
2009                                   Register resultReg,
2010                                   Address addr,
2011                                   void *userData,
2012                                   bool runProcessWhenDone,
2013                                   PCThread *thread,
2014                                   bool synchronous,
2015                                   bool userRPC,
2016                                   bool isMemAlloc,
2017                                   void **result) {
2018    if( isTerminated() ) {
2019       proccontrol_printf("%s[%d]: cannot post RPC to exited or terminated process %d\n",
2020                          FILE__, __LINE__, getpid());
2021       return false;
2022    }
2023    
2024    if( thread && !thread->isLive() ) {
2025       proccontrol_printf("%s[%d]: attempted to post RPC to dead thread %d\n",
2026                          FILE__, __LINE__, thread->getLWP());
2027       return false;
2028    }
2029
2030
2031    inferiorRPCinProgress *newRPC = new inferiorRPCinProgress;
2032    newRPC->runProcWhenDone = runProcessWhenDone;
2033    newRPC->deliverCallbacks = userRPC;
2034    newRPC->userData = userData;
2035    newRPC->synchronous = synchronous;
2036
2037    newRPC->resultRegister = resultReg;
2038    
2039    // Create the iRPC at the ProcControl level
2040    if( addr == 0 ) {
2041       bool err = false;
2042       if( isMemAlloc ) {
2043          // This assumes that there will always be space
2044          addr = inferiorMalloc(size, lowmemHeap, 0, &err);
2045       }else{
2046          // recursive RPCs are okay when this isn't an inferiorMalloc RPC
2047          addr = inferiorMalloc(size, anyHeap, 0, &err);
2048       }
2049       
2050       if( err ) {
2051          proccontrol_printf("%s[%d]: failed to allocate memory for RPC\n",
2052                             FILE__, __LINE__);
2053          delete newRPC;
2054          return false;
2055       }
2056       newRPC->memoryAllocated = true;
2057    }
2058    
2059     if (addr)
2060        newRPC->rpc = IRPC::createIRPC(buf, size, addr);
2061     else
2062        newRPC->rpc = IRPC::createIRPC(buf, size);
2063
2064 #if 0
2065    // DEBUG
2066    InstructionAPI::InstructionDecoder d(buf,size,getArch());
2067    Address foo = addr;
2068    InstructionAPI::Instruction::Ptr insn = d.decode();
2069    while(insn) {
2070       cerr << "\t" << hex << foo << ": " << insn->format(foo) << dec << endl;
2071       foo += insn->size();
2072       insn = d.decode();
2073    }
2074 #endif
2075     newRPC->rpc->setData(newRPC);
2076
2077     unsigned int start_offset = 0;
2078 #if defined(bug_syscall_changepc_rewind)
2079     // Some Linux kernels have the following behavior:
2080     // Process is in a system call;
2081     // We interrupt the system call;
2082     // We say "change PC to address N"
2083     // The kernel helpfully changes it to (N - address width)
2084     // The program crashes
2085     // See a more complete comment above.
2086     // For now, we pad the start of our code with NOOPS and change to just
2087     // after those; if we hit rewind behavior, then we're executing safe code.
2088     //
2089     // Matt Note:  The above comment is slightly incorrect.  The kernel subracts
2090     //  the length of the syscall/int instruction that triggered the system call,
2091     //  not the address width.  Still address width is big enough, so I'm not
2092     //  changing anything.
2093     start_offset = proc()->getAddressWidth();
2094     newRPC->rpcStartAddr += start_offset;
2095 #endif
2096     newRPC->rpc->setStartOffset(start_offset);
2097     newRPC->rpcCompletionAddr = addr + breakOffset;
2098
2099     // Post the iRPC
2100     Thread::ptr t;
2101     if (thread) {
2102        t = thread->pcThr();
2103     }
2104     newRPC->thread = t;
2105     
2106     bool res = false;
2107     proccontrol_printf("%s[%d]: Launching IRPC\n", FILE__, __LINE__);
2108     if (synchronous) {
2109        // We have an interesting problem here. ProcControl allows callbacks to specify whether the 
2110        // process should stop or run; however, that allows us to stop a process in the middle of an
2111        // inferior RPC. If that happens, manually execute a continue and wait for completion ourselves.
2112        if (t)
2113           res = t->runIRPCSync(newRPC->rpc);
2114        else
2115           res = pcProc_->runIRPCSync(newRPC->rpc);
2116        if (!res) {
2117           bool done = false;
2118           while (!done) {
2119              proccontrol_printf("%s[%d]: Iterating in loop waiting for IRPC to complete\n", FILE__, __LINE__);
2120              if (isTerminated()) {
2121                 fprintf(stderr, "IRPC on terminated process, ret false!\n");
2122                 delete newRPC;
2123                 return false;
2124              }
2125
2126             if (ProcControlAPI::getLastError() != ProcControlAPI::err_notrunning) {
2127                 // Something went wrong
2128                proccontrol_printf("%s[%d]: failed to post %s RPC to %s, error %s\n",
2129                                   FILE__, __LINE__, (synchronous ? "sync" : "async"), 
2130                                   ((thread == NULL) ? "thread" : "process"),
2131                                   ProcControlAPI::getLastErrorMsg());
2132                delete newRPC;
2133                return false;
2134             }
2135             else {
2136                proccontrol_printf("%s[%d]: ProcControl reported IRPC thread stopped, continuing and consuming events\n", FILE__, __LINE__);
2137                newRPC->rpc->continueStoppedIRPC();
2138                proccontrol_printf("%s[%d]: handling events in ProcControl\n", FILE__, __LINE__);
2139                res = pcProc_->handleEvents(true);
2140                PCEventMuxer::muxer().handle(NULL);
2141                if (newRPC->rpc->state() == ProcControlAPI::IRPC::Done) {
2142                   proccontrol_printf("%s[%d]: IRPC complete\n", FILE__, __LINE__);
2143                   done = true;
2144                }
2145             }
2146           }
2147        }
2148     }
2149     else {
2150        if (t)
2151           res = t->runIRPCAsync(newRPC->rpc);
2152        else
2153           res = pcProc_->runIRPCAsync(newRPC->rpc);
2154     }
2155     if(!res) {
2156        proccontrol_printf("%s[%d]: failed to post %s RPC to %s\n",
2157                           FILE__, __LINE__, (synchronous ? "sync" : "async"), ((thread == NULL) ? "thread" : "process"));
2158        delete newRPC;
2159        return false;
2160     }
2161     
2162     if( result ) {
2163        *result = newRPC->returnValue;
2164     }
2165     
2166     // Make sure Dyninst has worked everything out
2167     PCEventMuxer::muxer().wait(false);
2168
2169    return true;
2170 }
2171
2172
2173 BPatch_hybridMode PCProcess::getHybridMode() {
2174     return BPatch_normalMode;
2175 }
2176
2177 bool PCProcess::isExploratoryModeOn() const {
2178     return BPatch_exploratoryMode == analysisMode_ ||
2179            BPatch_defensiveMode   == analysisMode_;
2180 }
2181
2182 bool PCProcess::isRuntimeHeapAddr(Address addr) const {
2183     for (unsigned hidx=0; hidx < dyninstRT_heaps_.size(); hidx++) {
2184         if (addr >= dyninstRT_heaps_[hidx]->addr &&
2185             addr < dyninstRT_heaps_[hidx]->addr + dyninstRT_heaps_[hidx]->length) {
2186             return true;
2187         }
2188     }
2189     return false;
2190 }
2191
2192 /* returns true if blocks were overwritten, initializes overwritten
2193  * blocks and ranges by contrasting shadow pages with current memory
2194  * contents
2195  * 1. reads shadow pages in from memory
2196  * 2. constructs overwritten region list
2197  * 3. constructs overwrittn basic block list
2198  * 4. determines if the last of the blocks has an abrupt end, in which
2199  *    case it marks it as overwritten
2200  */
2201 bool PCProcess::getOverwrittenBlocks
2202   ( std::map<Address, unsigned char *>& overwrittenPages,//input
2203     std::list<std::pair<Address,Address> >& overwrittenRanges,//output
2204     std::list<block_instance *> &writtenBBIs)//output
2205 {
2206     const unsigned MEM_PAGE_SIZE = getMemoryPageSize();
2207     unsigned char * memVersion = (unsigned char *) ::malloc(MEM_PAGE_SIZE);
2208     Address regionStart = 0;
2209     bool foundStart = false;
2210     map<Address, unsigned char*>::iterator pIter = overwrittenPages.begin();
2211     set<mapped_object*> owObjs;
2212     for (; pIter != overwrittenPages.end(); pIter++) {
2213         Address curPageAddr = (*pIter).first / MEM_PAGE_SIZE * MEM_PAGE_SIZE;
2214         unsigned char *curShadow = (*pIter).second;
2215
2216         // 0. check to make sure curShadow is non-null, if it is null, 
2217         //    that means it hasn't been written to
2218         if ( ! curShadow ) {
2219                         cerr << "\t\t No current shadow, continuing" << endl;
2220                         continue;
2221         }
2222
2223         mapped_object* obj = findObject(curPageAddr);
2224         if (owObjs.end() != owObjs.find(obj)) {
2225             obj->setCodeBytesUpdated(false);
2226         }
2227
2228         // 1. Read the modified page in from memory
2229         Address readAddr = curPageAddr;
2230         if (isMemoryEmulated()) {
2231             bool valid = false;
2232             boost::tie(valid,readAddr) = getMemEm()->translate(curPageAddr);
2233                         cerr << "\t\t Reading from shadow page " << hex << readAddr << " instead of original " << curPageAddr << endl;
2234             assert(valid);
2235         }
2236         readTextSpace((void*)readAddr, MEM_PAGE_SIZE, memVersion);
2237
2238         // 2. build overwritten region list by comparing shadow, memory
2239         for (unsigned mIdx = 0; mIdx < MEM_PAGE_SIZE; mIdx++) {
2240             if ( ! foundStart && curShadow[mIdx] != memVersion[mIdx] ) {
2241                 foundStart = true;
2242                 regionStart = curPageAddr+mIdx;
2243             } else if (foundStart && curShadow[mIdx] == memVersion[mIdx]) {
2244                 foundStart = false;
2245                                 cerr << "\t\t Adding overwritten range " << hex << regionStart << " -> " << curPageAddr + mIdx << dec << endl;
2246
2247                 overwrittenRanges.push_back(
2248                     pair<Address,Address>(regionStart,curPageAddr+mIdx));
2249             }
2250         }
2251         if (foundStart) {
2252
2253             foundStart = false;
2254                         cerr << "\t\t Adding overwritten range " << hex << regionStart << " -> " << curPageAddr + MEM_PAGE_SIZE << dec << endl;
2255
2256             overwrittenRanges.push_back(
2257                 pair<Address,Address>(regionStart,curPageAddr+MEM_PAGE_SIZE));
2258         }
2259     }
2260
2261     // 3. Determine which basic blocks have been overwritten
2262     list<pair<Address,Address> >::const_iterator rIter = overwrittenRanges.begin();
2263     std::list<block_instance*> curBBIs;
2264     while (rIter != overwrittenRanges.end()) {
2265         mapped_object *curObject = findObject((*rIter).first);
2266
2267         curObject->findBlocksByRange((*rIter).first,(*rIter).second,curBBIs);
2268         if (curBBIs.size()) {
2269             mal_printf("overwrote %d blocks in range %lx %lx \n",
2270                        curBBIs.size(),(*rIter).first,(*rIter).second);
2271             writtenBBIs.splice(writtenBBIs.end(), curBBIs);
2272         }
2273
2274         curBBIs.clear();
2275         rIter++;
2276     }
2277
2278     free(memVersion);
2279     if (writtenBBIs.size()) {
2280         return true;
2281     } else {
2282         return false;
2283     }
2284 }
2285
2286 // distribute the work to mapped_objects
2287 void PCProcess::updateCodeBytes
2288     ( const list<pair<Address, Address> > &owRanges ) // input
2289 {
2290     std::map<mapped_object *,list<pair<Address,Address> >*> objRanges;
2291     list<pair<Address,Address> >::const_iterator rIter = owRanges.begin();
2292     for (; rIter != owRanges.end(); rIter++) {
2293         mapped_object *obj = findObject((*rIter).first);
2294         if (objRanges.find(obj) == objRanges.end()) {
2295             objRanges[obj] = new list<pair<Address,Address> >();
2296         }
2297         objRanges[obj]->push_back(pair<Address,Address>(rIter->first, rIter->second));
2298     }
2299
2300     std::map<mapped_object *,list<pair<Address,Address> > *>::iterator oIter = 
2301         objRanges.begin();
2302     for (; oIter != objRanges.end(); oIter++) 
2303     {
2304         oIter->first->updateCodeBytes( *(oIter->second) );
2305         delete (oIter->second);
2306     }
2307     assert(objRanges.size() <= 1); //o/w analysis code may not be prepared for other cases
2308 }
2309
2310 #if 0
2311 static void otherFuncBlocks(func_instance *func, 
2312                             const set<block_instance*> &blks, 
2313                             set<block_instance*> &otherBlks)
2314 {
2315     const func_instance::BlockSet &allBlocks = 
2316         func->blocks();
2317     for (func_instance::BlockSet::const_iterator bit =
2318          allBlocks.begin();
2319          bit != allBlocks.end(); 
2320          bit++) 
2321     {
2322         if (blks.end() == blks.find((*bit))) {
2323             otherBlks.insert((*bit));
2324         }
2325     }
2326 }
2327 #endif
2328
2329 /* Summary
2330  * Given a list of overwritten blocks, find blocks that are unreachable,
2331  * functions that have been overwritten at their entry points and can go away,
2332  * and new function entry for functions that are being overwritten while still
2333  * executing
2334  *
2335  * variables
2336  * f:  the overwritten function
2337  * ow: the set of overwritten blocks
2338  * ex: the set of blocks that are executing on the call stack that were not overwritten
2339  * 
2340  * primitives
2341  * R(b,s): yields set of reachable blocks for collection of blocks b, starting
2342  *         at seed blocks s.
2343  * B(f):   the blocks pertaining to function f
2344  * EP(f):  the entry point of function f
2345  * F(b):   functions containing block b
2346  * 
2347  * calculations
2348  * Elim(f): the set of blocks to eliminate from function f.
2349  *          Elim(f) = B(f) - R( B(f)-ow , EP(f) )
2350  * New(f):  new function entry candidates for f's surviving blocks.
2351  *          If EB(f) not in ow(f), empty set
2352  *          Else, all blocks b such that ( b in ex AND e in Elim(f) )
2353  *          Eliminate New(f) elements that have ancestors in New(f)
2354  * Del(f):  A block can be deleted altogether if
2355  *          forall f in F(b): B(F) - R( B(f) - ow , New(f) U (EP(f) \ ow(f)) U (ex(f) intersect Elim(f)) ),
2356  *          b is not in the resulting set. In other words, b is not
2357  *          reachable from non-overwritten blocks in the functions in
2358  *          which it appears, seeded at new entry points and original
2359  *          non-overwritten entry points to the function, and at f's
2360  *          executing blocks if these will be deleted from the
2361  *          function (they constitute an entry point into the function 
2362  *          even if they've been overwritten). 
2363  * DeadF:   the set of functions that have no executing blocks 
2364  *          and were overwritten in their entry blocks
2365  *          EP(f) in ow(f) AND ex(f) is empty
2366  */
2367 bool PCProcess::getDeadCode
2368 ( const std::list<block_instance*> & /*owBlocks*/, // input
2369   std::set<block_instance*> & /*delBlocks*/, //output: Del(for all f)
2370   std::map<func_instance*,set<block_instance*> > & /*elimMap*/, //output: elimF
2371   std::list<func_instance*> & /*deadFuncs*/, //output: DeadF
2372   std::map<func_instance*,block_instance*> & /*newFuncEntries*/) //output: newF
2373 {
2374    assert(0 && "TODO");
2375    return false;
2376 #if 0
2377     // do a stackwalk to see which functions are currently executing
2378     pdvector<pdvector<Frame> >  stacks;
2379     pdvector<Address> pcs;
2380     if (!walkStacks(stacks)) {
2381         inst_printf("%s[%d]:  walkStacks failed\n", FILE__, __LINE__);
2382         return false;
2383     }
2384     for (unsigned i = 0; i < stacks.size(); ++i) {
2385         pdvector<Frame> &stack = stacks[i];
2386         for (unsigned int j = 0; j < stack.size(); ++j) {
2387             Address origPC = 0;
2388             vector<func_instance*> dontcare1;
2389             baseTramp *dontcare2 = NULL;
2390             getAddrInfo(stack[j].getPC(), origPC, dontcare1, dontcare2);
2391             pcs.push_back( origPC );
2392         }
2393     }
2394
2395     // group blocks by function
2396     std::map<func_instance*,set<block_instance*> > deadMap;
2397     std::set<func_instance*> deadEntryFuncs;
2398     std::set<Address> owBlockAddrs;
2399     for (list<block_instance*>::const_iterator bIter=owBlocks.begin();
2400          bIter != owBlocks.end(); 
2401          bIter++) 
2402     {
2403        deadMap[(*bIter)->func()].insert(*bIter);
2404        owBlockAddrs.insert((*bIter)->start());
2405        if ((*bIter)->llb() == (*bIter)->func()->ifunc()->entry()) {
2406           deadEntryFuncs.insert((*bIter)->func());
2407        }
2408     }
2409
2410     // for each modified function, calculate ex, ElimF, NewF, DelF
2411     for (map<func_instance*,set<block_instance*> >::iterator fit = deadMap.begin();
2412          fit != deadMap.end(); 
2413          fit++) 
2414     {
2415
2416         // calculate ex(f)
2417         set<block_instance*> execBlocks;
2418         for (unsigned pidx=0; pidx < pcs.size(); pidx++) {
2419             std::set<block_instance *> candidateBlocks;
2420             fit->first->findBlocksByAddr(pcs[pidx], candidateBlocks);
2421             for (std::set<block_instance *>::iterator cb_iter = candidateBlocks.begin();
2422                 cb_iter != candidateBlocks.end(); ++cb_iter) {
2423                 block_instance *exB = *cb_iter;
2424                 if (exB && owBlockAddrs.end() == owBlockAddrs.find(
2425                                                         exB->start())) 
2426                 {
2427                     execBlocks.insert(exB);
2428                 }
2429             }
2430         }
2431
2432         // calculate DeadF: EP(f) in ow and EP(f) not in ex
2433         if ( 0 == execBlocks.size() ) {
2434             set<block_instance*>::iterator eb = fit->second.find(
2435                 fit->first->entryBlock());
2436             if (eb != fit->second.end()) {
2437                 deadFuncs.push_back(fit->first);
2438                 continue;// treated specially, don't need elimF, NewF or DelF
2439             }
2440         } 
2441
2442         // calculate elimF
2443         set<block_instance*> keepF;
2444         list<block_instance*> seedBs;
2445         seedBs.push_back(fit->first->entryBlock());
2446         fit->first->getReachableBlocks(fit->second, seedBs, keepF);
2447         otherFuncBlocks(fit->first, keepF, elimMap[fit->first]);
2448
2449         // calculate NewF
2450         if (deadEntryFuncs.end() != deadEntryFuncs.find(fit->first)) {
2451             for (set<block_instance*>::iterator bit = execBlocks.begin();
2452                  bit != execBlocks.end();
2453                  bit++) 
2454             {
2455                 if (elimMap[fit->first].end() != 
2456                     elimMap[fit->first].find(*bit)) 
2457                 {
2458                     newFuncEntries[fit->first] = *bit;
2459                     break; // just need one candidate
2460                 }
2461             }
2462         }
2463
2464         // calculate Del(f)
2465         seedBs.clear();
2466         if (deadEntryFuncs.end() == deadEntryFuncs.find(fit->first)) {
2467             seedBs.push_back(fit->first->entryBlock());
2468         }
2469         else if (newFuncEntries.end() != newFuncEntries.find(fit->first)) {
2470             seedBs.push_back(newFuncEntries[fit->first]);
2471         }
2472         for (set<block_instance*>::iterator xit = execBlocks.begin();
2473              xit != execBlocks.end();
2474              xit++) 
2475         {
2476             if (elimMap[fit->first].end() != elimMap[fit->first].find(*xit)) {
2477                 seedBs.push_back(*xit);
2478             }
2479         }
2480         keepF.clear();
2481         fit->first->getReachableBlocks(fit->second, seedBs, keepF);
2482         otherFuncBlocks(fit->first, keepF, delBlocks);
2483         
2484     }
2485
2486     return true;
2487 #endif
2488 }
2489
2490 // will flush addresses of all addresses in the specified range, if the
2491 // range is null, flush all addresses from the cache.  Also flush 
2492 // rt-lib heap addrs that correspond to the range
2493 void PCProcess::flushAddressCache_RT(Address start, unsigned size)
2494 {
2495     if (start != 0) {
2496         mal_printf("Flushing address cache of range [%lx %lx]\n",
2497                    start, 
2498                    start + size);
2499     } else {
2500         mal_printf("Flushing address cache of rt_lib heap addrs only \n");
2501     }
2502
2503     // Find the runtime cache's address if it hasn't been set yet
2504     if (0 == RT_address_cache_addr_) {
2505         std::string arg_str ("DYNINST_target_cache");
2506         pdvector<int_variable *> vars;
2507         if ( ! findVarsByAll(arg_str, vars) ) {
2508             fprintf(stderr, "%s[%d]:  cannot find var %s\n", 
2509                     FILE__, __LINE__, arg_str.c_str());
2510             assert(0);
2511         }
2512         if (vars.size() != 1) {
2513             fprintf(stderr, "%s[%d]:  ERROR:  %d vars matching %s, not 1\n", 
2514                     FILE__, __LINE__, (int)vars.size(), arg_str.c_str());
2515             assert(0);
2516         }
2517         RT_address_cache_addr_ = vars[0]->getAddress();
2518     }
2519
2520     // Clear all cache entries that match the runtime library
2521     // Read in the contents of the cache
2522     Address* cacheCopy = (Address*)malloc(TARGET_CACHE_WIDTH*sizeof(Address));
2523     if ( ! readDataSpace( (void*)RT_address_cache_addr_, 
2524                           sizeof(Address)*TARGET_CACHE_WIDTH,(void*)cacheCopy,
2525                           false ) ) 
2526     {
2527         assert(0);
2528     }
2529
2530     assert(dyninstRT_heaps_.size());
2531     bool flushedHeaps = false;
2532
2533     while ( true ) // iterate twice, once to flush the heaps, 
2534     {              // and once to flush the flush range
2535         Address flushStart=0;
2536         Address flushEnd=0;
2537         if (!flushedHeaps) {
2538             // figure out the range of addresses we'll want to flush from
2539
2540             flushStart = dyninstRT_heaps_[0]->addr;
2541             flushEnd = flushStart + dyninstRT_heaps_[0]->length;
2542             for (unsigned idx=1; idx < dyninstRT_heaps_.size(); idx++) {
2543                 Address curAddr = dyninstRT_heaps_[idx]->addr;
2544                 if (flushStart > curAddr) {
2545                     flushStart = curAddr;
2546                 }
2547                 curAddr += dyninstRT_heaps_[idx]->length;
2548                 if (flushEnd < curAddr) {
2549                     flushEnd = curAddr;
2550                 }
2551             }
2552         } else {
2553             flushStart = start;
2554             flushEnd = start + size;
2555         }
2556         //zero out entries that lie in the runtime heaps
2557         for(int idx=0; idx < TARGET_CACHE_WIDTH; idx++) {
2558             //printf("cacheCopy[%d]=%lx\n",idx,cacheCopy[idx]);
2559             if (flushStart <= cacheCopy[idx] &&
2560                 flushEnd   >  cacheCopy[idx]) {
2561                 cacheCopy[idx] = 0;
2562             }
2563         }
2564         if ( flushedHeaps || (start == 0) ) {
2565             break;
2566         }
2567         flushedHeaps = true;
2568     }
2569
2570     // write the modified cache back into the RT_library
2571     if ( ! writeDataSpace( (void*)RT_address_cache_addr_,
2572                            sizeof(Address)*TARGET_CACHE_WIDTH,
2573                            (void*)cacheCopy ) ) {
2574         assert(0);
2575     }
2576     free(cacheCopy);
2577 }
2578
2579 /* Given an address that's on the call stack, find the function that's
2580  * actively executing that address.  This makes most sense for finding the
2581  * address that's triggered a context switch back to Dyninst, either
2582  * through instrumentation or a signal
2583  */
2584 func_instance *PCProcess::findActiveFuncByAddr(Address addr)
2585 {
2586     std::set<func_instance *> funcs;
2587     // error checking by size...
2588     (void)findFuncsByAddr(addr, funcs, true);
2589     if (funcs.empty()) return NULL;
2590
2591     if (funcs.size() == 1) {
2592         return *(funcs.begin());
2593     }
2594
2595     // unrelocated shared function address, do a stack walk to figure 
2596     // out which of the shared functions is on the call stack
2597     bool foundFrame = false;
2598     func_instance *activeFunc = NULL; 
2599     pdvector<pdvector<Frame> >  stacks;
2600     if ( false == walkStacks(stacks) ) {
2601         fprintf(stderr,"ERROR: %s[%d], walkStacks failed\n", 
2602                 FILE__, __LINE__);
2603         assert(0);
2604     }
2605     for (unsigned int i = 0; !foundFrame && i < stacks.size(); ++i) {
2606         pdvector<Frame> &stack = stacks[i];
2607         for (unsigned int j = 0; !foundFrame && j < stack.size(); ++j) {
2608             Frame *curFrame = &stack[j];
2609             Address framePC = curFrame->getPC();
2610
2611             // if we're at a relocated address, we can translate 
2612             // back to the right function, if translation fails 
2613             // frameFunc will still be NULL
2614             RelocInfo ri;
2615             func_instance *frameFunc = NULL;
2616
2617             if (getRelocInfo(framePC, ri) &&
2618                 ri.func) {
2619                frameFunc = ri.func;
2620             }
2621             else if (j < (stack.size() - 1)) {
2622                 // Okay, crawl original code. 
2623                 // Step 1: get our current function
2624                 std::set<func_instance *> curFuncs;
2625                 findFuncsByAddr(framePC, curFuncs);
2626                 // Step 2: get return addresses one frame up and map to possible callers
2627                 std::set<block_instance *> callerBlocks;
2628                 findBlocksByAddr(stack[j+1].getPC() - 1, callerBlocks);
2629                 for (std::set<block_instance *>::iterator cb_iter = callerBlocks.begin();
2630                     cb_iter != callerBlocks.end(); ++cb_iter)
2631                 {
2632                     if (!(*cb_iter)->containsCall()) continue;
2633                     // We have a call point; now see if it called the entry of any function
2634                     // that maps to a curFunc.
2635                     for (std::set<func_instance *>::iterator cf_iter = curFuncs.begin();
2636                          cf_iter != curFuncs.end(); ++cf_iter) {
2637                        if ((*cf_iter) == (*cb_iter)->callee()) {
2638                           frameFunc = *cf_iter;
2639                        }
2640                     }
2641                 }
2642             }
2643             if (frameFunc) {
2644                 foundFrame = true;
2645                 activeFunc = frameFunc;
2646             }
2647         }
2648     }
2649     if (!foundFrame) {
2650         activeFunc = *(funcs.begin());
2651     }
2652                 
2653     return activeFunc;
2654 }
2655
2656 bool PCProcess::patchPostCallArea(instPoint *callPt) {
2657    // 1) Find all the post-call patch areas that correspond to this 
2658    //    call point
2659    // 2) Generate and install the branches that will be inserted into 
2660    //    these patch areas
2661    
2662    // 1...
2663    AddrPairSet patchAreas;
2664    if ( ! generateRequiredPatches(callPt, patchAreas) ) {
2665       return false;
2666    }
2667    
2668    // 2...
2669    generatePatchBranches(patchAreas);
2670    return true;
2671 }
2672
2673 bool PCProcess::generateRequiredPatches(instPoint *callPoint, 
2674                                         AddrPairSet &patchAreas)
2675 {
2676     // We need to figure out where this patch should branch to.
2677     // To do that, we're going to:
2678     // 1) Forward map the entry of the ft block to
2679     //    its most recent relocated version (if that exists)
2680     // 2) For each padding area, create a (padAddr,target) pair
2681
2682     // 3)
2683
2684     block_instance *callB = callPoint->block();
2685     block_instance *ftBlk = callB->getFallthrough()->trg();
2686     if (!ftBlk) {
2687         // find the block at the next address, if there's no fallthrough block
2688         ftBlk = callB->obj()->findBlockByEntry(callB->end());
2689         assert(ftBlk);
2690     }
2691
2692     // ensure that we patch other callPts at the same address
2693
2694     vector<ParseAPI::Function*> callFuncs;
2695     callPoint->block()->llb()->getFuncs(callFuncs);
2696     for (vector<ParseAPI::Function*>::iterator fit = callFuncs.begin();
2697          fit != callFuncs.end();
2698          fit++)
2699     {
2700         func_instance *callF = findFunction((parse_func*)*fit);
2701         instPoint *callP = instPoint::preCall(callF, callB);
2702         Relocation::CodeTracker::RelocatedElements reloc;
2703         CodeTrackers::reverse_iterator rit;
2704         for (rit = relocatedCode_.rbegin(); rit != relocatedCode_.rend(); rit++)
2705         {
2706             if ((*rit)->origToReloc(ftBlk->start(), ftBlk, callF, reloc)) {
2707                 break;
2708             }
2709         }
2710         if (rit == relocatedCode_.rend()) {
2711             mal_printf("WARNING: no relocs of call-fallthrough at %lx "
2712                        "in func at %lx, will not patch its post-call "
2713                        "padding\n", callP->block()->last(),callF->addr());
2714             (*relocatedCode_.rbegin())->debug();
2715             continue;
2716         }
2717
2718         Address to = reloc.instruction;
2719         if (!reloc.instrumentation.empty()) {
2720            // There could be a lot of instrumentation at this point. Bias towards the lowest,
2721            // non-edge instrumentation
2722            for (std::map<instPoint *, Address>::iterator inst_iter = reloc.instrumentation.begin();
2723                 inst_iter != reloc.instrumentation.end(); ++inst_iter) {
2724               if (inst_iter->first->type() == PatchAPI::Point::EdgeDuring) continue;
2725               to = (inst_iter->second < to) ? inst_iter->second : to;
2726            }
2727         }
2728
2729         // 2) 
2730         Address callInsnAddr = callP->block()->last();
2731         if (forwardDefensiveMap_.end() != forwardDefensiveMap_.find(callInsnAddr)) {
2732             map<func_instance*,set<DefensivePad> >::iterator mit = forwardDefensiveMap_[callInsnAddr].begin();
2733             for (; mit != forwardDefensiveMap_[callInsnAddr].end(); ++mit) {
2734               if (callF == mit->first) {
2735                   set<DefensivePad>::iterator dit = mit->second.begin();
2736                   for (; dit != mit->second.end(); ++dit) {
2737                      Address jumpAddr = dit->first;
2738                      patchAreas.insert(std::make_pair(jumpAddr, to));
2739                      mal_printf("patching post-call pad for %lx[%lx] with %lx %s[%d]\n",
2740                                 callB->end(), jumpAddr, to, FILE__,__LINE__);
2741                   }
2742               }
2743             }
2744         }
2745     }
2746     if (patchAreas.empty()) {
2747        mal_printf("WARNING: no relocs to patch for call at %lx, block end %lx\n", 
2748                   callPoint->addr_compat(),ftBlk->start());
2749     }
2750     return ! patchAreas.empty();
2751 }
2752
2753 void PCProcess::generatePatchBranches(AddrPairSet &branchesNeeded) {
2754   for (AddrPairSet::iterator iter = branchesNeeded.begin();
2755        iter != branchesNeeded.end(); ++iter) 
2756   {
2757     Address from = iter->first;
2758     Address to = iter->second;
2759
2760     codeGen gen(64);
2761     insnCodeGen::generateBranch(gen, from, to);
2762
2763     // Safety check: make sure we didn't overrun the patch area
2764     Address lb = 0, ub = 0;
2765     std::pair<func_instance*,Address> tmp;
2766     if (!reverseDefensiveMap_.find(from, lb, ub, tmp)) {
2767       // Huh? This worked before!
2768       assert(0);
2769     }
2770     assert((from + gen.used()) <= ub);
2771     if (!writeTextSpace((void *)from, 
2772                         gen.used(),
2773                         gen.start_ptr())) {
2774       assert(0);
2775     }
2776   }
2777 }
2778
2779 /* debugSuicide is a kind of alternate debugging continueProc.  It runs the
2780  * process until terminated in single step mode, printing each instruction as
2781  * it executes.
2782  */
2783 void PCProcess::debugSuicide() {
2784     if( isTerminated() ) return;
2785
2786     isInDebugSuicide_ = true;
2787
2788     pdvector<Frame> activeFrames;
2789     getAllActiveFrames(activeFrames);
2790
2791     for(unsigned i=0; i < activeFrames.size(); ++i) {
2792         Address addr = activeFrames[i].getPC();
2793         fprintf(stderr, "Frame %u @ 0x%lx\n", i , addr);
2794     }
2795
2796     Thread::ptr initialThread = pcProc_->threads().getInitialThread();
2797
2798     initialThread->setSingleStepMode(true);
2799     while( !isTerminated() && isAttached() && initialThread->isLive() ) {
2800         // Get the current PC
2801         MachRegister pcReg = MachRegister::getPC(getArch());
2802         MachRegisterVal resultVal;
2803         if( !initialThread->getRegister(pcReg, resultVal) ) {
2804             fprintf(stderr, "%s[%d]: failed to retreive register from thread %d/%d\n",
2805                     FILE__, __LINE__, getPid(), initialThread->getLWP());
2806             return;
2807         }
2808     }
2809 }
2810
2811 pdvector<func_instance *> PCProcess::pcsToFuncs(pdvector<Frame> stackWalk) {
2812     pdvector <func_instance *> ret;
2813     unsigned i;
2814     func_instance *fn;
2815     for(i=0;i<stackWalk.size();i++) {
2816         fn = (func_instance *)findOneFuncByAddr(stackWalk[i].getPC());
2817         // no reason to add a null function to ret
2818         if (fn != 0) ret.push_back(fn);
2819     }
2820     return ret;
2821 }
2822
2823 bool PCProcess::isInSignalHandler(Address addr) {
2824     codeRange *range;
2825     if( signalHandlerLocations_.find(addr, range) ) {
2826         return true;
2827     }
2828
2829     return false;
2830 }
2831
2832 void PCProcess::addSignalHandler(Address addr, unsigned size) {
2833     codeRange *handlerLoc;
2834     if (signalHandlerLocations_.find(addr, handlerLoc)) {
2835         return; // we're already tracking this location
2836     }
2837     handlerLoc = new signal_handler_location(addr, size);
2838     signalHandlerLocations_.insert((signal_handler_location *)handlerLoc);
2839 }
2840
2841 bool PCProcess::mappedObjIsDeleted(mapped_object *obj) {
2842     for(unsigned i = 0; i < deletedObjects_.size(); ++i) {
2843         if( obj == deletedObjects_[i] ) return true;
2844     }
2845
2846     return false;
2847 }
2848
2849 // AddressSpace Implementation //
2850 Address PCProcess::offset() const {
2851     assert(!"This function is not implemented");
2852     return 0;
2853 }
2854
2855 Address PCProcess::length() const {
2856     assert(!"This function is not implemented");
2857     return 0;
2858 }
2859
2860 Architecture PCProcess::getArch() const {
2861     return savedArch_;
2862 }
2863
2864 bool PCProcess::multithread_ready(bool ignoreIfMtNotSet) {
2865     // Since ProcControlAPI has taken over handling thread creation
2866     // and destruction from the RT library, as soon as the process reaches
2867     // the initialized state, the process is multithread ready if it
2868     // is multithread capable.
2869
2870     if( !hasReachedBootstrapState(bs_initialized) ) return false;
2871     if( !multithread_capable(ignoreIfMtNotSet) ) return false;
2872
2873     return true;
2874 }
2875
2876 bool PCProcess::needsPIC() {
2877     return false;
2878 }
2879
2880 bool PCProcess::isInDebugSuicide() const {
2881     return isInDebugSuicide_;
2882 }
2883
2884 PCProcess::processState_t PCProcess::getDesiredProcessState() const {
2885     return processState_;
2886 }
2887
2888 void PCProcess::setDesiredProcessState(PCProcess::processState_t pc) {
2889     processState_ = pc;
2890 }
2891
2892 bool PCProcess::walkStack(pdvector<Frame> &stackWalk,
2893                           PCThread *thread)
2894 {
2895   if( stackwalker_ == NULL ) return false;
2896
2897   vector<Dyninst::Stackwalker::Frame> swWalk;
2898
2899   if (!stackwalker_->walkStack(swWalk, thread->getLWP()))
2900   {
2901     return false;
2902   }
2903
2904   for (vector<Dyninst::Stackwalker::Frame>::iterator SWB = swWalk.begin(),
2905        SWI = SWB,
2906        SWE = swWalk.end();
2907        SWI != SWE;
2908        ++SWI)
2909   {
2910     stackWalk.push_back(Frame(*SWI, this, thread, (SWI == SWB)));
2911   }
2912
2913   return true;
2914 }
2915
2916 bool PCProcess::getActiveFrame(Frame &frame, PCThread *thread)
2917 {
2918   Dyninst::Stackwalker::Frame swFrame;
2919   if (!stackwalker_->getInitialFrame(swFrame, thread->getLWP()))
2920   {
2921     return false;
2922   }
2923
2924   frame = Frame(swFrame, this, thread, true);
2925   return true;
2926 }
2927
2928 /* This is the simple version
2929  * 1. Need three pieces of information:
2930  * 1a. The instrumentation point that triggered the stopThread event (pointAddress)
2931  * 1b. The ID of the callback function given at the registration
2932  *     of the stopThread snippet
2933  * 1c. The result of the snippet calculation that was given by the user,
2934  *     if the point is a return instruction, read the return address
2935  * 2. If the calculation is an address that is meant to be interpreted, do that
2936  * 3. Invoke the callback
2937  */
2938 bool PCProcess::triggerStopThread(Address pointAddress, int callbackID, void *calculation) {
2939     AddressSpace::RelocInfo ri;
2940     if( !getRelocInfo(pointAddress, ri) ) {
2941         assert(0);
2942         return false;
2943     }
2944
2945     // get instPoint from point address
2946     func_instance *pointfunc = ri.func;
2947     if (!pointfunc) {
2948         mal_printf("%s[%d]: failed to find active function at 0x%lx\n",
2949                 FILE__, __LINE__, pointAddress);
2950         return false;
2951     }
2952
2953     instPoint *intPoint = ri.bt->point();
2954     if (!intPoint) {
2955         mal_printf("%s[%d]: failed to find inst point at 0x%lx\n",
2956                 FILE__, __LINE__, pointAddress);
2957         return false;
2958     }
2959
2960     mal_printf("handling stopThread %lx[%lx]=>%lx %s[%d]\n",
2961             ri.reloc, pointAddress, (long)calculation, FILE__, __LINE__);
2962
2963     /* 2. If the callbackID is negative, the calculation is meant to be
2964       interpreted as the address of code, so we call stopThreadCtrlTransfer
2965       to translate the target to an unrelocated address */
2966     if (callbackID < 0) {
2967         callbackID *= -1;
2968         calculation = (void*)
2969             stopThreadCtrlTransfer(intPoint, (Address)calculation);
2970     }
2971
2972     /* 3. Trigger the callback for the stopThread
2973       using the correct snippet instance ID & event type */
2974     ((BPatch_process*)up_ptr())->triggerStopThread
2975         (intPoint, pointfunc, callbackID, (void*)calculation);
2976
2977     return true;
2978 }
2979
2980 /*    If calculation is a relocated address, translate it to the original addr
2981  *    case 1: The point is at a return instruction
2982  *    case 2: The point is a control transfer into the runtime library
2983  *    Mark returning functions as returning
2984  *    Save the targets of indirect control transfers (not regular returns)
2985  */
2986 Address PCProcess::stopThreadCtrlTransfer (instPoint* intPoint, 
2987                                          Address target)
2988 {
2989    Address pointAddr = intPoint->addr_compat();
2990
2991     // if the point is a real return instruction and its target is a stack 
2992     // address, get the return address off of the stack 
2993     if (intPoint->type() == instPoint::FuncExit &&
2994         intPoint->block()->isFuncExit() &&
2995         !intPoint->func()->isSignalHandler()) 
2996     {
2997         mal_printf("%s[%d]: return address is %lx\n", FILE__,
2998                     __LINE__,target);
2999     }
3000
3001     Address unrelocTarget = target;
3002
3003     if ( isRuntimeHeapAddr( target ) ) {
3004         // get unrelocated target address, there are three possibilities
3005         // a. We're in post-call padding, and targBBI is the call block
3006         // b. We're in an analyzed fallthrough block
3007         // c. The stack was tampered with and we need the (mod_pc - pc) 
3008         //    offset to figure out where we should be
3009         malware_cerr << "Looking for matches to incoming address " 
3010             << hex << target << dec << endl;
3011         std::pair<func_instance*,Address> tmp;
3012
3013         if ( reverseDefensiveMap_.find(target,tmp) ) {
3014             // a. 
3015            std::set<block_instance*> callBs;
3016            tmp.first->getBlocks(tmp.second, callBs);
3017            block_instance *callB = (*callBs.begin());
3018            edge_instance *fallthrough = callB->getFallthrough();
3019            if (fallthrough) {
3020               unrelocTarget = fallthrough->trg()->start();
3021            } else {
3022               unrelocTarget = callB->end();
3023            }
3024         }
3025         else {
3026             // b. 
3027             // if we're in the fallthrough block, match to call block, 
3028             // and if necessary, add fallthrough edge
3029            AddressSpace::RelocInfo ri;
3030            bool hasFT = getRelocInfo(target, ri);
3031            assert(hasFT); // otherwise we should be in the defensive map
3032            if (ri.pad) {
3033                unrelocTarget = ri.block->end();
3034            } else {
3035                unrelocTarget = ri.block->start();
3036            }
3037         }
3038         mal_printf("translated target %lx to %lx %s[%d]\n",
3039             target, unrelocTarget, FILE__, __LINE__);
3040     }
3041     else { // target is not relocated, nothing to do but find the 
3042            // mapped_object, creating one if necessary, for transfers
3043            // into memory regions that are allocated at runtime
3044         mapped_object *obj = findObject(target);
3045         if (!obj) {
3046
3047 #if 0           
3048            Frame activeFrame = threads[0]->get_lwp()->getActiveFrame();
3049            for (unsigned i = 0; i < 0x100; ++i) {
3050                           Address stackTOP = activeFrame.esp;
3051                           Address stackTOPVAL =0;
3052                 readDataSpace((void *) (stackTOP + 4*i), 
3053                               sizeof(getAddressWidth()), 
3054                               &stackTOPVAL, false);
3055                           malware_cerr << "\tSTACK[" << hex << stackTOP+4*i << "]=" 
3056                              << stackTOPVAL << dec << endl;
3057            }
3058 #endif
3059
3060             obj = createObjectNoFile(target);
3061             if (!obj) {
3062                 fprintf(stderr,"ERROR, point %lx has target %lx that responds "
3063                         "to no object %s[%d]\n", pointAddr, target, 
3064                         FILE__,__LINE__);
3065                 assert(0 && "stopThread snippet has an invalid target");
3066                 return 0;
3067             }
3068         }
3069     }
3070
3071 #if 0
3072            Frame activeFrame = threads[0]->get_lwp()->getActiveFrame();
3073            Address stackTOP = activeFrame.esp;
3074            Address stackTOPVAL =0;
3075            for (unsigned i = 0; 
3076                 i < 0x100 && 0 != ((stackTOP + 4*i) % memoryPageSize_); 
3077                 ++i) 
3078            {
3079                 readDataSpace((void *) (stackTOP + 4*i), 
3080                               sizeof(getAddressWidth()), 
3081                               &stackTOPVAL, false);
3082                           malware_cerr << "\tSTACK[" << hex << stackTOP+4*i << "]=" 
3083                              << stackTOPVAL << dec << endl;
3084            }
3085 #endif
3086
3087     return unrelocTarget;
3088 }
3089
3090 void PCProcess::triggerNormalExit(int exitcode) {
3091     for(std::map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
3092             i != threadsByTid_.end(); ++i)
3093     {
3094         if( i->second != initialThread_ ) 
3095             BPatch::bpatch->registerThreadExit(this, i->second);
3096     }
3097     BPatch::bpatch->registerNormalExit(this, exitcode);
3098
3099     // Let the event handler know that the process should be moved to
3100     // an exited state
3101     setExiting(true);
3102 }
3103
3104 // Debugging only
3105 bool PCProcess::setBreakpoint(Address addr) {
3106     Breakpoint::ptr brkPt = Breakpoint::newBreakpoint();
3107     if( !pcProc_->addBreakpoint(addr, brkPt) ) {
3108         proccontrol_printf("%s[%d]: failed to set breakpoint at 0x%lx\n",
3109                 FILE__, __LINE__, addr);
3110         return false;
3111     }
3112
3113     return true;
3114 }
3115
3116 bool PCProcess::launchDebugger() {
3117     // Stop the process on detach 
3118     pdvector<func_instance *> breakpointFuncs;
3119     if( !findFuncsByAll("DYNINSTsafeBreakPoint", breakpointFuncs) ) {
3120         fprintf(stderr, "Failed to find function DYNINSTsafeBreakPoint\n");
3121         return false;
3122     }
3123
3124     func_instance *safeBreakpoint = breakpointFuncs[0];
3125     for(map<dynthread_t, PCThread *>::iterator i = threadsByTid_.begin();
3126             i != threadsByTid_.end(); ++i)
3127     {
3128         if( !i->second->pcThr_->setRegister(MachRegister::getPC(getArch()),
3129                     safeBreakpoint->addr()) )
3130         {
3131             fprintf(stderr, "Failed to set PC to 0x%lx\n", 
3132                     safeBreakpoint->addr());
3133             return false;
3134         }
3135     }
3136
3137     // Detach the process
3138     if( !detachProcess(true) ) {
3139         fprintf(stderr, "Failed to detach from process %d\n", getPid());
3140         return false;
3141     }
3142
3143     if( !startDebugger() ) {
3144         fprintf(stderr, "Failed to start debugger on process %d\n", getPid());
3145         return false;
3146     }
3147
3148     return true;
3149 }
3150
3151 // End debugging
3152
3153 Address getVarAddr(PCProcess *proc, std::string str) {
3154     Address retAddr = 0;
3155
3156     pdvector<int_variable *> vars;
3157     if( proc->findVarsByAll(str, vars) ) {
3158         if( vars.size() != 1 ) {
3159             proccontrol_printf("%s[%d]: WARNING: multiple copies of %s found\n",
3160                     FILE__, __LINE__, str.c_str());
3161         }else{
3162             retAddr = vars[0]->getAddress();
3163         }
3164     }else{
3165         proccontrol_printf("%s[%d]: failed to find variable %s\n",
3166                 FILE__, __LINE__, str.c_str());
3167     }
3168     return retAddr;
3169 }
3170
3171 Address PCProcess::getRTEventBreakpointAddr() {
3172     if( sync_event_breakpoint_addr_ == 0 ) {
3173         sync_event_breakpoint_addr_ = getVarAddr(this, "DYNINST_break_point_event");
3174     }
3175
3176     return sync_event_breakpoint_addr_;
3177 }
3178
3179 Address PCProcess::getRTEventIdAddr() {
3180     if( sync_event_id_addr_ == 0 ) {
3181         sync_event_id_addr_ = getVarAddr(this, "DYNINST_synch_event_id");
3182     }
3183
3184     return sync_event_id_addr_;
3185 }
3186
3187 Address PCProcess::getRTEventArg1Addr() {
3188     if( sync_event_arg1_addr_ == 0 ) {
3189         sync_event_arg1_addr_ = getVarAddr(this, "DYNINST_synch_event_arg1");
3190     }
3191
3192     return sync_event_arg1_addr_;
3193 }
3194
3195 Address PCProcess::getRTEventArg2Addr() {
3196     if( sync_event_arg2_addr_ == 0 ) {
3197         sync_event_arg2_addr_ = getVarAddr(this, "DYNINST_synch_event_arg2");
3198     }
3199
3200     return sync_event_arg2_addr_;
3201 }
3202
3203 Address PCProcess::getRTEventArg3Addr() {
3204     if( sync_event_arg3_addr_ == 0 ) {
3205         sync_event_arg3_addr_ = getVarAddr(this, "DYNINST_synch_event_arg3");
3206     }
3207
3208     return sync_event_arg3_addr_;
3209 }
3210
3211 bool PCProcess::hasPendingEvents() {
3212    // Go to the muxer as a final arbiter
3213    return PCEventMuxer::muxer().hasPendingEvents(this);
3214 }
3215
3216 bool PCProcess::hasRunningSyncRPC() const {
3217     return (syncRPCThreads_.size() > 0);
3218 }
3219
3220 void PCProcess::addSyncRPCThread(Thread::ptr thr) {
3221    proccontrol_printf("%s[%d]: added sync rpc thread %d/%d\n",
3222                       FILE__, __LINE__, getPid(), thr ? thr->getLWP() : 0);
3223     syncRPCThreads_.insert(thr);
3224 }
3225
3226 void PCProcess::removeSyncRPCThread(Thread::ptr thr) {
3227     proccontrol_printf("%s[%d]: removed sync rpc thread %d/%d\n",
3228                 FILE__, __LINE__, getPid(), thr ? thr->getLWP() : 0);
3229     syncRPCThreads_.erase(thr);
3230 }
3231
3232 bool PCProcess::continueSyncRPCThreads() {
3233         for(set<Thread::ptr>::iterator i = syncRPCThreads_.begin();
3234             i != syncRPCThreads_.end(); ++i)
3235     {
3236                 if(!(*i)) {
3237                         if(!pcProc_->continueProc())
3238                         {
3239                                 proccontrol_printf("%s[%d]: failed to continue entire process %d for sync RPC\n",
3240                                                 FILE__, __LINE__, getPid());
3241                                 return false;
3242                         }
3243                 } else if( !(*i)->continueThread() ) {
3244             proccontrol_printf("%s[%d]: failed to continue thread %d/%d for sync RPC\n",
3245                     FILE__, __LINE__, getPid(), (*i)->getLWP());
3246             return false;
3247         }
3248     }
3249
3250     return true;
3251 }
3252
3253 void PCProcess::addTrap(Address from, Address to, codeGen &gen) {
3254     map<Address, Breakpoint::ptr>::iterator breakIter =
3255        installedCtrlBrkpts.find(from);
3256
3257     if( breakIter != installedCtrlBrkpts.end() ) {
3258         if( !pcProc_->rmBreakpoint(from, breakIter->second) ) {
3259           // Oops? 
3260         }
3261         installedCtrlBrkpts.erase(breakIter);
3262     }
3263     
3264     Breakpoint::ptr newBreak = Breakpoint::newTransferBreakpoint(to);
3265     newBreak->setSuppressCallbacks(true);
3266
3267     if( !pcProc_->addBreakpoint(from, newBreak) ) {
3268       // Oops? 
3269     }
3270
3271     installedCtrlBrkpts.insert(make_pair(from, newBreak));
3272     gen.invalidate();
3273 }
3274
3275 void PCProcess::removeTrap(Address from) {
3276     map<Address, Breakpoint::ptr>::iterator breakIter = 
3277         installedCtrlBrkpts.find(from);
3278     if( breakIter == installedCtrlBrkpts.end() ) return;
3279
3280     if( !pcProc_->rmBreakpoint(from, breakIter->second) ) {
3281         proccontrol_printf("%s[%d]: failed to remove ctrl transfer breakpoint from 0x%lx\n",
3282                 FILE__, __LINE__, from);
3283     }
3284
3285     installedCtrlBrkpts.erase(breakIter);
3286 }
3287
3288 void PCProcess::invalidateMTCache() {
3289     mt_cache_result_ = not_cached;
3290 }
3291
3292
3293 StackwalkSymLookup::StackwalkSymLookup(PCProcess *p)
3294   : proc_(p)
3295 {}
3296
3297 StackwalkSymLookup::~StackwalkSymLookup()
3298 {}
3299
3300 bool StackwalkSymLookup::lookupAtAddr(Dyninst::Address addr, std::string &out_name, void* &out_value)
3301 {
3302   func_instance *func = proc_->findOneFuncByAddr(addr);
3303   if( func == NULL ) return false;
3304
3305   // set out_name to the name of the function at this addr
3306   // set out_value to NULL, this value is no longer used
3307
3308   out_value = NULL;
3309
3310   if (func)
3311   {
3312     out_name = func->prettyName();
3313   }
3314   else
3315   {
3316     out_name = string("[UNKNOWN]");
3317   }
3318   
3319   return true;
3320 }
3321
3322 StackwalkInstrumentationHelper::StackwalkInstrumentationHelper(PCProcess *p)
3323   : proc_(p)
3324 {}
3325
3326 StackwalkInstrumentationHelper::~StackwalkInstrumentationHelper()
3327 {}
3328
3329 DynFrameHelper::DynFrameHelper(PCProcess *p)
3330   : FrameFuncHelper(NULL),
3331   proc_(p)
3332 {}
3333
3334 DynFrameHelper::~DynFrameHelper()
3335 {}
3336
3337 DynWandererHelper::DynWandererHelper(PCProcess *p)
3338   : WandererHelper(NULL),
3339   proc_(p)
3340 {}
3341
3342 DynWandererHelper::~DynWandererHelper()
3343 {}
3344
3345
3346