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