A first pass at implementing thread stop and continue on FreeBSD.
[dyninst.git] / proccontrol / src / event.C
1 #include "dynutil/h/dyntypes.h"
2 #include "proccontrol/src/int_process.h"
3 #include "proccontrol/src/int_handler.h"
4 #include "proccontrol/src/procpool.h"
5 #include "proccontrol/src/irpc.h"
6 #include "proccontrol/h/Event.h"
7 #include "proccontrol/h/Process.h"
8 #include "proccontrol/h/PCErrors.h"
9 #include <assert.h>
10 #include <stdlib.h>
11
12 ArchEvent::ArchEvent(std::string name_) :
13    name(name_)
14 {
15 }
16
17 ArchEvent::~ArchEvent()
18 {
19 }
20
21 std::string ArchEvent::getName()
22 {
23    return name;
24 }
25
26 Event::Event(EventType etype_, Thread::ptr thread_) :
27    etype(etype_),
28    thread(thread_),
29    proc(thread ? thread->getProcess() : Process::ptr()),
30    stype(unset),
31    master_event(Event::ptr())
32 {
33 }
34
35 EventType Event::getEventType() const {
36    return etype;
37 }
38
39 Thread::const_ptr Event::getThread() const {
40    return thread;
41 }
42
43 Process::const_ptr Event::getProcess() const {
44    return proc;
45 }
46
47 void Event::setThread(Thread::const_ptr t) {
48    thread = t;
49 }
50
51 void Event::setProcess(Process::const_ptr p) {
52    proc = p;
53 }
54
55 bool Event::canFastHandle() const
56 {
57    return false;
58 }
59
60 void Event::setSyncType(SyncType s)
61 {
62    stype = s;
63 }
64
65 bool Event::suppressCB() const
66 {
67    return false;
68 }
69
70 bool Event::triggersCB() const
71 {
72    HandleCallbacks *cbhandler = HandleCallbacks::getCB();
73    if (cbhandler->requiresCB(shared_from_this()))
74      return true;
75    std::vector<Event::ptr>::const_iterator i = subservient_events.begin();
76    for (; i != subservient_events.end(); i++) {
77       if ((*i)->triggersCB())
78          return true;
79    }
80    return false;
81 }
82
83 Event::SyncType Event::getSyncType() const
84 {
85    return stype;
86 }
87
88 std::string Event::name() const
89 {
90    return etype.name();
91 }
92
93 Event::weak_ptr Event::subservientTo() const
94 {
95    return master_event;
96 }
97
98 void Event::addSubservientEvent(Event::ptr ev)
99 {
100    subservient_events.push_back(ev);
101    ev->master_event = shared_from_this();
102 }
103
104 std::string EventType::name() const
105 {
106    std::string prefix;
107    if (etime == Pre)
108       prefix = "pre-";
109    if (etime == Post)
110       prefix = "post-";
111
112 #define STR_CASE(ET) case ET: return prefix + std::string(#ET)
113    switch (ecode) {
114       STR_CASE(Error);
115       STR_CASE(Unset);
116       STR_CASE(Exit);
117       STR_CASE(Crash);
118       STR_CASE(Fork);
119       STR_CASE(Exec);
120       STR_CASE(ThreadCreate);
121       STR_CASE(ThreadDestroy);
122       STR_CASE(Stop);
123       STR_CASE(Signal);
124       STR_CASE(LibraryLoad);
125       STR_CASE(LibraryUnload);
126       STR_CASE(Bootstrap);
127       STR_CASE(Breakpoint);
128       STR_CASE(RPC);
129       STR_CASE(SingleStep);
130       STR_CASE(Library);
131       STR_CASE(BreakpointClear);
132       STR_CASE(Continue);
133       default: return prefix + std::string("Unknown");
134    }
135 }
136
137 bool Event::procStopper() const
138 {
139    return false;
140 }
141
142 Event::~Event()
143 {
144 }
145
146 EventTerminate::EventTerminate(EventType type_) :
147    Event(type_)
148 {
149 }
150
151 EventTerminate::~EventTerminate()
152 {
153 }
154
155 EventExit::EventExit(EventType::Time eventtime, int exitcode_) :
156    EventTerminate(EventType(eventtime, EventType::Exit)),
157    exitcode(exitcode_)
158 {
159 }
160
161 int EventExit::getExitCode() const
162 {
163    return exitcode;
164 }
165
166 EventExit::~EventExit()
167 {
168 }
169
170 EventCrash::EventCrash(int termsig_) :
171    EventTerminate(EventType(EventType::None, EventType::Crash)),
172    termsig(termsig_)
173 {
174 }
175
176 int EventCrash::getTermSignal() const
177 {
178    return termsig;
179 }
180          
181 EventCrash::~EventCrash()
182 {
183 }
184
185 EventContinue::EventContinue(int contsig) :
186     Event(EventType(EventType::None, EventType::Continue)),
187     continueSignal(contsig)
188 {
189 }
190
191 int EventContinue::getContinueSignal() const {
192     return continueSignal;
193 }
194
195 EventContinue::~EventContinue()
196 {
197 }
198
199 EventExec::EventExec(EventType::Time etime_, std::string path) :
200    Event(EventType(etime_, EventType::Exec)),
201    execpath(path)
202 {
203 }
204
205 EventExec::~EventExec()
206 {
207 }
208
209 std::string EventExec::getExecPath() const
210 {
211    return execpath;
212 }
213
214 void EventExec::setExecPath(std::string e)
215 {
216    execpath = e;
217 }
218
219 EventStop::EventStop() :
220    Event(EventType(EventType::None, EventType::Stop))
221 {
222 }
223
224 EventStop::~EventStop()
225 {
226 }
227
228
229 EventBreakpoint::EventBreakpoint(Dyninst::Address addr_, installed_breakpoint *ibp_) :
230    Event(EventType(EventType::None, EventType::Breakpoint)),
231    ibp(ibp_),
232    addr(addr_)
233 {
234 }
235
236 EventBreakpoint::~EventBreakpoint()
237 {
238 }
239
240 Dyninst::Address EventBreakpoint::getAddress() const
241 {
242   return addr;
243 }
244
245 bool EventBreakpoint::procStopper() const
246 {
247    return true;
248 }
249
250 void EventBreakpoint::getBreakpoints(std::vector<Breakpoint::const_ptr> &bps) const
251 {
252    if (!ibp)
253       return;
254    std::set<Breakpoint::ptr>::iterator i;
255    for (i = ibp->hl_bps.begin(); i != ibp->hl_bps.end(); i++) {
256       bps.push_back(*i);
257    }
258 }
259
260 installed_breakpoint *EventBreakpoint::installedbp() const
261 {
262   return ibp;
263 }
264
265 bool EventBreakpoint::suppressCB() const
266 {
267    return ibp->hl_bps.empty();
268 }
269
270 EventSignal::EventSignal(int sig_) :
271    Event(EventType(EventType::None, EventType::Signal)),
272    sig(sig_)
273 {
274 }
275
276 EventSignal::~EventSignal()
277 {
278 }
279
280 int EventSignal::getSignal() const
281 {
282    return sig;
283 }
284
285 EventBootstrap::EventBootstrap() :
286    Event(EventType(EventType::None, EventType::Bootstrap))
287 {
288 }
289
290 EventBootstrap::~EventBootstrap()
291 {
292 }
293
294 EventNewThread::EventNewThread(Dyninst::LWP lwp_) :
295    Event(EventType(EventType::None, EventType::ThreadCreate)),
296    lwp(lwp_)
297 {
298 }
299
300 EventNewThread::~EventNewThread()
301 {
302 }
303
304 Dyninst::LWP EventNewThread::getLWP() const
305 {
306    return lwp;
307 }
308
309 Thread::const_ptr EventNewThread::getNewThread() const
310 {
311    int_thread *thr = getProcess()->llproc()->threadPool()->findThreadByLWP(lwp);
312    assert(thr);
313    return thr->thread();
314 }
315
316 EventThreadDestroy::EventThreadDestroy(EventType::Time time_) :
317    Event(EventType(time_, EventType::ThreadDestroy))
318 {
319 }
320
321 EventThreadDestroy::~EventThreadDestroy()
322 {
323 }
324
325 EventFork::EventFork(Dyninst::PID pid_) :
326    Event(EventType(EventType::Post, EventType::Fork)),
327    pid(pid_)
328 {
329 }
330
331 EventFork::~EventFork()
332 {
333 }
334
335 Dyninst::PID EventFork::getPID() const
336 {
337    return pid;
338 }
339
340 Process::const_ptr EventFork::getChildProcess() const
341 {
342    int_process *iproc = ProcPool()->findProcByPid(pid);
343    assert(iproc);
344    return iproc->proc();
345 }
346
347 EventRPC::EventRPC(rpc_wrapper *wrapper_) :
348    Event(EventType(EventType::None, EventType::RPC)),
349    wrapper(wrapper_)
350 {
351 }
352
353 EventRPC::~EventRPC()
354 {
355    if (wrapper->rpc->getIRPC().lock() == IRPC::ptr()) {
356       delete wrapper;
357       wrapper = NULL;
358    }
359 }
360
361 IRPC::const_ptr EventRPC::getIRPC() const
362
363    return wrapper->rpc->getIRPC().lock();
364 }
365
366 bool EventRPC::suppressCB() const
367 {
368    return (wrapper->rpc->getIRPC().lock() == IRPC::ptr());
369 }
370
371 rpc_wrapper *EventRPC::getllRPC()
372 {
373    return wrapper;
374 }
375
376 EventSingleStep::EventSingleStep() :
377    Event(EventType(EventType::None, EventType::SingleStep))
378 {
379 }
380
381 EventSingleStep::~EventSingleStep()
382 {
383 }
384
385 EventBreakpointClear::EventBreakpointClear(installed_breakpoint *bp) :
386   Event(EventType(EventType::None, EventType::BreakpointClear)),
387   bp_(bp)
388 {
389 }
390
391 EventBreakpointClear::~EventBreakpointClear()
392 {
393 }
394
395 installed_breakpoint *EventBreakpointClear::bp()
396 {
397   return bp_;
398 }
399
400 EventLibrary::EventLibrary(const std::set<Library::ptr> &added_libs_,
401                            const std::set<Library::ptr> &rmd_libs_) :
402    Event(EventType(EventType::None, EventType::Library)),
403    added_libs(added_libs_),
404    rmd_libs(rmd_libs_)
405 {
406 }
407
408 EventLibrary::EventLibrary() :
409    Event(EventType(EventType::None, EventType::Library))
410 {
411 }
412
413 EventLibrary::~EventLibrary()
414 {
415 }
416
417 void EventLibrary::setLibs(const std::set<Library::ptr> &added_libs_,
418                            const std::set<Library::ptr> &rmd_libs_)
419 {
420    added_libs = added_libs_;
421    rmd_libs = rmd_libs_;
422 }
423
424 const std::set<Library::ptr> &EventLibrary::libsAdded() const
425 {
426    return added_libs;
427 }
428
429 const std::set<Library::ptr> &EventLibrary::libsRemoved() const
430 {
431    return rmd_libs;
432 }
433
434 #define DEFN_EVENT_CAST(NAME, TYPE) \
435    NAME::ptr Event::get ## NAME() {  \
436      if (etype.code() != EventType::TYPE) return NAME::ptr();  \
437      return dyn_detail::boost::static_pointer_cast<NAME>(shared_from_this()); \
438    } \
439    NAME::const_ptr Event::get ## NAME() const { \
440      if (etype.code() != EventType::TYPE) return NAME::const_ptr();  \
441      return dyn_detail::boost::static_pointer_cast<const NAME>(shared_from_this()); \
442    }
443
444 #define DEFN_EVENT_CAST2(NAME, TYPE, TYPE2) \
445    NAME::ptr Event::get ## NAME() {  \
446      if (etype.code() != EventType::TYPE && etype.code() != EventType::TYPE2) return NAME::ptr(); \
447      return dyn_detail::boost::static_pointer_cast<NAME>(shared_from_this()); \
448    } \
449    NAME::const_ptr Event::get ## NAME() const { \
450      if (etype.code() != EventType::TYPE && etype.code() != EventType::TYPE2) return NAME::const_ptr(); \
451      return dyn_detail::boost::static_pointer_cast<const NAME>(shared_from_this()); \
452    }
453
454 DEFN_EVENT_CAST2(EventTerminate, Exit, Crash)
455 DEFN_EVENT_CAST(EventExit, Exit)
456 DEFN_EVENT_CAST(EventCrash, Crash)
457 DEFN_EVENT_CAST(EventExec, Exec)
458 DEFN_EVENT_CAST(EventStop, Stop)
459 DEFN_EVENT_CAST(EventContinue, Continue)
460 DEFN_EVENT_CAST(EventBreakpoint, Breakpoint)
461 DEFN_EVENT_CAST(EventNewThread, ThreadCreate)
462 DEFN_EVENT_CAST(EventThreadDestroy, ThreadDestroy)
463 DEFN_EVENT_CAST(EventFork, Fork)
464 DEFN_EVENT_CAST(EventSignal, Signal)
465 DEFN_EVENT_CAST(EventBootstrap, Bootstrap)
466 DEFN_EVENT_CAST(EventRPC, RPC)
467 DEFN_EVENT_CAST(EventSingleStep, SingleStep)
468 DEFN_EVENT_CAST(EventBreakpointClear, BreakpointClear)
469 DEFN_EVENT_CAST(EventLibrary, Library)