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