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