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