A first pass at implementing thread stop and continue on FreeBSD.
[dyninst.git] / proccontrol / src / int_thread_db.C
1 /*
2  * Copyright (c) 1996-2009 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 <proc_service.h>
33 #include <thread_db.h>
34
35 #include <cassert>
36 #include <cerrno>
37 #include <set>
38 using std::set;
39
40 #include "common/h/dthread.h"
41 #include "int_thread_db.h"
42
43 /* 
44  * proc_service interface implementation, needed by libthread_db
45  */
46
47 ps_err_e ps_pglobal_lookup(struct ps_prochandle *handle, const char *objName, 
48         const char *symName, psaddr_t *symbolAddr)
49 {
50     return handle->thread_db_proc->getSymbolAddr(objName, symName, symbolAddr);
51 }
52
53 ps_err_e ps_pread(struct ps_prochandle *handle, psaddr_t remote, void *local, size_t size) {
54     pthrd_printf("thread_db reading from %#lx to %#lx, size = %d on %d\n",
55             (unsigned long)remote, (unsigned long)local, size, handle->thread_db_proc->getPid());
56     if( !handle->thread_db_proc->plat_readProcMem(local, (Dyninst::Address)remote, size) )  {
57         pthrd_printf("Failed to read from %#lx to %#lx, size = %d on %d: %s\n",
58                     (unsigned long)remote, (unsigned long)local, size, handle->thread_db_proc->getPid(),
59                     strerror(errno));
60         return PS_ERR;
61     }
62
63     return PS_OK;
64 }
65
66 ps_err_e ps_pwrite(struct ps_prochandle *handle, psaddr_t remote, const void *local, size_t size) {
67     pthrd_printf("thread_db writing to %#lx write %#lx, size = %d on %d\n",
68             (unsigned long)remote, (unsigned long)local, size, handle->thread_db_proc->getPid());
69     if( !handle->thread_db_proc->plat_writeProcMem(const_cast<void *>(local), (Dyninst::Address)remote, size) ) {
70         pthrd_printf("Failed to write to %#lx write %#lx, size = %d on %d: %s\n",
71                 (unsigned long)remote, (unsigned long)local, size, handle->thread_db_proc->getPid(),
72                 strerror(errno));
73         return PS_ERR;
74     }
75
76     return PS_OK;
77 }
78
79 ps_err_e ps_linfo(struct ps_prochandle *handle, lwpid_t lwp, void *lwpInfo) {
80     if( !handle->thread_db_proc->plat_getLWPInfo(lwp, lwpInfo) )
81         return PS_ERR;
82
83     return PS_OK;
84 }
85
86 ps_err_e ps_lstop(struct ps_prochandle *handle, lwpid_t lwp) {
87     if( !handle->thread_db_proc->plat_stopThread(lwp) ) {
88         return PS_ERR;
89     }
90
91     return PS_OK;
92 }
93
94 ps_err_e ps_lcontinue(struct ps_prochandle *handle, lwpid_t lwp) {
95     if( !handle->thread_db_proc->plat_contThread(lwp) ) {
96         return PS_ERR;
97     }
98
99     return PS_OK;
100 }
101
102 void     ps_plog(const char *format, ...) {
103     if( !dyninst_debug_proccontrol ) return;
104     if( NULL == format ) return;
105
106     va_list va;
107     va_start(va, format);
108     vfprintf(pctrl_err_out, format, va);
109     va_end(va);
110 }
111
112 #define NA_IMPLEMENTED "This function is not implemented"
113
114 ps_err_e ps_lgetfpregs(struct ps_prochandle *, lwpid_t, prfpregset_t *) {
115     assert(!NA_IMPLEMENTED);
116     return PS_ERR;
117 }
118
119 ps_err_e ps_lgetregs(struct ps_prochandle *, lwpid_t, prgregset_t) {
120     assert(!NA_IMPLEMENTED);
121     return PS_ERR;
122 }
123
124 ps_err_e ps_lsetfpregs(struct ps_prochandle *, lwpid_t, const prfpregset_t *) {
125     assert(!NA_IMPLEMENTED);
126     return PS_ERR;
127 }
128
129 ps_err_e ps_lsetregs(struct ps_prochandle *, lwpid_t, const prgregset_t) {
130     assert(!NA_IMPLEMENTED);
131     return PS_ERR;
132 }
133
134 ps_err_e ps_lgetxmmregs (struct ps_prochandle *, lwpid_t, char *) {
135     assert(!NA_IMPLEMENTED);
136     return PS_ERR;
137 }
138
139 ps_err_e ps_lsetxmmregs (struct ps_prochandle *, lwpid_t, const char *) {
140     assert(!NA_IMPLEMENTED);
141     return PS_ERR;
142 }
143
144 ps_err_e ps_pcontinue(struct ps_prochandle *) {
145     assert(!NA_IMPLEMENTED);
146     return PS_ERR;
147 }
148
149 ps_err_e ps_pdmodel(struct ps_prochandle *, int *) {
150     assert(!NA_IMPLEMENTED);
151     return PS_ERR;
152 }
153
154 ps_err_e ps_pstop(struct ps_prochandle *) {
155     assert(!NA_IMPLEMENTED);
156     return PS_ERR;
157 }
158
159 #ifndef CASE_RETURN_STR
160 #define CASE_RETURN_STR(x) case x: return #x;
161 #endif
162
163 static const char *tdErr2Str(td_err_e errVal) {
164     switch(errVal) {
165         CASE_RETURN_STR(TD_ERR)
166         CASE_RETURN_STR(TD_OK)
167         CASE_RETURN_STR(TD_BADKEY)
168         CASE_RETURN_STR(TD_BADPH)
169         CASE_RETURN_STR(TD_BADSH)
170         CASE_RETURN_STR(TD_BADTA)
171         CASE_RETURN_STR(TD_BADTH)
172         CASE_RETURN_STR(TD_DBERR)
173         CASE_RETURN_STR(TD_MALLOC)
174         CASE_RETURN_STR(TD_NOAPLIC)
175         CASE_RETURN_STR(TD_NOCAPAB)
176         CASE_RETURN_STR(TD_NOEVENT)
177         CASE_RETURN_STR(TD_NOFPREGS)
178         CASE_RETURN_STR(TD_NOLIBTHREAD)
179         CASE_RETURN_STR(TD_NOLWP)
180         CASE_RETURN_STR(TD_NOMSG)
181         CASE_RETURN_STR(TD_NOSV)
182         CASE_RETURN_STR(TD_NOTHR)
183         CASE_RETURN_STR(TD_NOTSD)
184         CASE_RETURN_STR(TD_NOXREGS)
185         CASE_RETURN_STR(TD_PARTIALREG)
186         default:
187             return "?";
188     }
189 }
190
191 static
192 Event::ptr decodeThreadEvent(td_event_msg_t *eventMsg) {
193     td_thrinfo_t threadInfo;
194     td_err_e errVal;
195     if( TD_OK != (errVal = td_thr_get_info(eventMsg->th_p, &threadInfo)) ) {
196         perr_printf("Failed to get thread event info from event msg: %s(%d)\n",
197                 tdErr2Str(errVal), errVal);
198         return Event::ptr();
199     }
200
201     switch(eventMsg->event) {
202         case TD_CREATE:
203             if( TD_OK != (errVal = td_thr_dbsuspend(eventMsg->th_p)) ) {
204                 perr_printf("Failed suspend new thread via thread_db: %s(%d)\n",
205                         tdErr2Str(errVal), errVal);
206                 return Event::ptr();
207             }
208             return Event::ptr(new EventNewThread((Dyninst::LWP)threadInfo.ti_lid));
209             break;
210         case TD_DEATH:
211             return Event::ptr(new EventThreadDestroy(EventType::Pre));
212             break;
213         default:
214             pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
215             break;
216     }
217
218     return Event::ptr();
219 }
220
221 volatile bool thread_db_process::thread_db_initialized = false;
222 Mutex thread_db_process::thread_db_init_lock;
223
224 thread_db_process::thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a)
225     : sysv_process(p, e, a), threadAgent(NULL)
226 {
227     self = new ps_prochandle();
228     assert(self);
229     self->thread_db_proc = this;
230 }
231
232 thread_db_process::thread_db_process(Dyninst::PID pid_, int_process *p) 
233     : sysv_process(pid_, p), threadAgent(NULL)
234 {
235     self = new ps_prochandle();
236     assert(self);
237     self->thread_db_proc = this;
238 }
239
240 thread_db_process::~thread_db_process() 
241 {
242     // Free the breakpoints allocated for events
243     map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator brkptIter;
244     for(brkptIter = addr2Event.begin(); brkptIter != addr2Event.end(); ++brkptIter) {
245         delete brkptIter->second.first;
246     }
247
248     // Close all the symbol readers used
249     map<string, pair<LoadedLib *, SymReader *> >::iterator symReaderIter;
250     for(symReaderIter = symReaders.begin(); symReaderIter != symReaders.end(); 
251             ++symReaderIter)
252     {
253         symreader_factory->closeSymbolReader(symReaderIter->second.second);
254     }
255
256     delete self;
257 }
258
259 bool thread_db_process::initThreadDB() {
260     // Q: Why isn't this in the constructor? 
261     // A: This function depends on the corresponding thread library being loaded
262     // and this event occurs some time after process creation.
263
264     // Make sure thread_db is initialized - only once for all instances
265     if( !thread_db_initialized ) {
266         thread_db_init_lock.lock();
267         if( !thread_db_initialized ) {
268             td_err_e errVal;
269             if( TD_OK != (errVal = td_init()) ) {
270                 perr_printf("Failed to initialize libthread_db: %s(%d)\n",
271                         tdErr2Str(errVal), errVal);
272                 setLastError(err_internal, "libthread_db initialization failed");
273                 return false;
274             }
275             pthrd_printf("Sucessfully initialized thread_db\n");
276             thread_db_initialized = true;
277         }
278         thread_db_init_lock.unlock();
279     }
280
281     // Create the thread agent
282     td_err_e errVal = td_ta_new(self, &threadAgent);
283     switch(errVal) {
284         case TD_OK:
285             break;
286         case TD_NOLIBTHREAD:
287             pthrd_printf("Debuggee isn't multithreaded at this point, libthread_db not enabled\n");
288             return true;
289         default:
290             perr_printf("Failed to create thread agent: %s(%d)\n",
291                     tdErr2Str(errVal), errVal);
292             setLastError(err_internal, "Failed to create libthread_db agent");
293             return false;
294     }
295
296     // Enable all events
297     td_thr_events_t eventMask;
298     td_event_fillset(&eventMask);
299
300     errVal = td_ta_set_event(threadAgent, &eventMask);
301     if( TD_OK != errVal ) {
302         perr_printf("Failed to enable events: %s(%d)\n",
303                 tdErr2Str(errVal), errVal);
304         setLastError(err_internal, "Failed to enable libthread_db events");
305         return false;
306     }
307
308     // Determine the addresses for all events
309     td_event_e allEvents[] = { TD_CATCHSIG, TD_CONCURRENCY, TD_CREATE,
310         TD_DEATH, TD_IDLE, TD_LOCK_TRY, TD_PREEMPT, TD_PRI_INHERIT,
311         TD_READY, TD_REAP, TD_SLEEP, TD_SWITCHFROM, TD_SWITCHTO,
312         TD_TIMEOUT };
313
314     for(unsigned i = 0; i < (sizeof(allEvents)/sizeof(td_event_e)); ++i) {
315         td_notify_t notifyResult;
316         errVal = td_ta_event_addr(threadAgent, allEvents[i], &notifyResult);
317
318         // This indicates that the event isn't supported
319         if( TD_OK != errVal ) continue;
320
321         assert( notifyResult.type == NOTIFY_BPT && "Untested notify type" );
322
323         EventType newEvent;
324         switch(allEvents[i]) {
325             case TD_CREATE:
326                 newEvent = EventType(EventType::Post, EventType::ThreadCreate);
327                 pthrd_printf("Installing breakpoint for thread creation events\n");
328                 break;
329             case TD_DEATH:
330                 newEvent = EventType(EventType::Post, EventType::ThreadDestroy);
331                 pthrd_printf("Installing breakpoint for thread destroy events\n");
332                 break;
333             default:
334                 pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
335                 continue;
336         }
337
338         int_breakpoint *newEventBrkpt = new int_breakpoint(Breakpoint::ptr());
339         if( !addBreakpoint((Dyninst::Address)notifyResult.u.bptaddr,
340                     newEventBrkpt))
341         {
342             perr_printf("Failed to install new event breakpoint\n");
343             setLastError(err_internal, "Failed to install new thread_db event breakpoint");
344             delete newEventBrkpt;
345
346             return false;
347         }
348
349         pair<map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator, bool> insertIter;
350         insertIter = addr2Event.insert(make_pair((Dyninst::Address)notifyResult.u.bptaddr,
351                     make_pair(newEventBrkpt, newEvent)));
352
353         assert( insertIter.second && "event breakpoint address not unique" );
354     }
355
356     return true;
357 }
358
359 void thread_db_process::freeThreadDBAgent() {
360     // XXX
361     // This code cannot be in the destructor because it makes use of
362     // the proc_service interface and this makes calls to functions
363     // that are pure virtual in this class.
364     //
365     // A possible, better solution would be to make the functions static
366     // but we lose all the convenience of pure virtual functions
367     //
368     // At any rate, this function should be called from a derived class' 
369     // destructor.
370
371     if( thread_db_initialized && threadAgent ) {
372         td_err_e errVal = td_ta_delete(threadAgent);
373         if( TD_OK != errVal ) {
374             perr_printf("Failed to delete thread agent: %s(%d)\n",
375                     tdErr2Str(errVal), errVal);
376         }
377         assert( TD_OK == errVal && "Failed to delete thread agent" );
378         threadAgent = NULL;
379     }
380 }
381
382 bool thread_db_process::getEventsAtAddr(Dyninst::Address addr, 
383         thread_db_thread *eventThread, vector<Event::ptr> &threadEvents) 
384 {
385     unsigned oldSize = threadEvents.size();
386
387     // Determine what type event occurs at the specified address
388     map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator addrIter;
389     addrIter = addr2Event.find(addr);
390     if( addrIter == addr2Event.end() ) return false;
391
392     switch(addrIter->second.second.code()) {
393         case EventType::ThreadCreate: 
394         {
395             pthrd_printf("Address 0x%lx corresponds to a thread create event.\n",
396                     addr);
397             // Need to ask via the thread_db agent for creation events. This
398             // could result in getting information about other events.  All of
399             // these events need to be handled.
400             td_event_msg_t threadMsg;
401             td_err_e msgErr = TD_OK;
402             while(msgErr == TD_OK) {
403                 msgErr = td_ta_event_getmsg(threadAgent, &threadMsg);
404                 if( msgErr == TD_OK ) {
405                     Event::ptr threadEvent = decodeThreadEvent(&threadMsg);
406                     if( threadEvent ) {
407                         threadEvents.push_back(threadEvent);
408                     }
409                 }
410             }
411
412             if( msgErr != TD_NOMSG ) {
413                 perr_printf("Failed to retrieve thread event: %s(%d)\n",
414                         tdErr2Str(msgErr), msgErr);
415             }
416             break;
417         }
418         case EventType::ThreadDestroy:
419         {
420             pthrd_printf("Address 0x%lx corresponds to a thread destroy event.\n",
421                     addr);
422             assert(eventThread);
423             Event::ptr threadEvent = eventThread->getThreadEvent();
424             if( threadEvent ) {
425                 threadEvents.push_back(threadEvent);
426             }else{
427                 perr_printf("Failed to retrieve thread event for LWP %d\n",
428                         eventThread->getLWP());
429             }
430             break;
431         }
432         default:
433             pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
434             break;
435     }
436
437     return oldSize != threadEvents.size();
438 }
439
440 td_thragent_t *thread_db_process::getThreadDBAgent() {
441     return threadAgent;
442 }
443
444 ps_err_e thread_db_process::getSymbolAddr(const char *objName, const char *symName,
445         psaddr_t *symbolAddr)
446 {
447     SymReader *objSymReader = NULL;
448     LoadedLib *lib = NULL;
449
450     // For static executables, we need to search the executable instead of the
451     // thread library. 
452
453     // For static executables, breakpoint_addr isn't set
454     if( !breakpoint_addr ) {
455         lib = translator->getExecutable();
456         if( NULL == lib ) {
457             perr_printf("Failed to get loaded version of executable\n");
458             setLastError(err_internal, "Failed to get loaded version of executable");
459             return PS_ERR;
460         }
461
462         map<string, pair<LoadedLib *, SymReader *> >::iterator symReaderIter;
463         symReaderIter = symReaders.find(lib->getName());
464         if( symReaderIter == symReaders.end() ) {
465             objSymReader = symreader_factory->openSymbolReader(lib->getName());
466             if( NULL == objSymReader ) {
467                 perr_printf("Failed to open symbol reader for %s\n",
468                         lib->getName().c_str());
469                 setLastError(err_internal, "Failed to open executable for symbol reading");
470                 return PS_ERR;
471             }
472             symReaders.insert(make_pair(lib->getName(), make_pair(lib, objSymReader)));
473         }else{
474             objSymReader = symReaderIter->second.second;
475         }
476     }else{
477         // FreeBSD implementation doesn't set objName
478         string objNameStr;
479         if( NULL == objName ) {
480             objNameStr = getThreadLibName(symName);
481         }else{
482             objNameStr = objName;
483         }
484
485         map<string, pair<LoadedLib *, SymReader *> >::iterator symReaderIter;
486         symReaderIter = symReaders.find(objNameStr);
487         if( symReaderIter == symReaders.end() ) {
488             vector<LoadedLib *> libs;
489             if( !translator->getLibs(libs) ) {
490                 perr_printf("Failed to retrieve loaded libraries\n");
491                 setLastError(err_internal, "Failed to retrieve loaded libraries");
492                 return PS_ERR;
493             }
494
495             vector<LoadedLib *>::iterator loadedLibIter;
496             for(loadedLibIter = libs.begin(); loadedLibIter != libs.end();
497                     ++loadedLibIter)
498             {
499                 if( (*loadedLibIter)->getName().find(objNameStr) != string::npos ) {
500                     lib = (*loadedLibIter);
501                     break;
502                 }
503             }
504
505             if( NULL == lib ) {
506                 perr_printf("Failed to find loaded library for %s\n", objNameStr.c_str());
507                 setLastError(err_internal, "Failed to find loaded library");
508                 return PS_ERR;
509             }
510
511             objSymReader = symreader_factory->openSymbolReader(lib->getName());
512
513             if( NULL == objSymReader ) {
514                 perr_printf("Failed to open symbol reader for %s\n", objNameStr.c_str());
515                 setLastError(err_internal, "Failed to open library for symbol reading");
516                 return PS_ERR;
517             }
518
519             symReaders.insert(make_pair(objNameStr, make_pair(lib, objSymReader)));
520         }else{
521             lib = symReaderIter->second.first;
522             objSymReader = symReaderIter->second.second;
523         }
524     }
525
526     Symbol_t lookupSym = objSymReader->getSymbolByName(string(symName));
527
528     if( !objSymReader->isValidSymbol(lookupSym) ) {
529         return PS_NOSYM;
530     }
531
532     *symbolAddr = (psaddr_t)lib->offToAddress(
533             objSymReader->getSymbolOffset(lookupSym));
534
535     return PS_OK;
536 }
537
538 bool thread_db_process::post_create() {
539     if( !int_process::post_create() ) return false;
540
541     return initThreadDB();
542 }
543
544 bool thread_db_process::post_attach() {
545     if( !int_process::post_attach() ) return false;
546
547     return initThreadDB();
548 }
549
550 bool thread_db_process::getPostDestroyEvents(vector<Event::ptr> &events) {
551     unsigned oldSize = events.size();
552
553     int_threadPool::iterator i;
554     for(i = threadPool()->begin(); i != threadPool()->end(); ++i) {
555         thread_db_thread *tmpThread = static_cast<thread_db_thread *>(*i);
556         if( tmpThread->isDestroyed() ) {
557             pthrd_printf("Generating post-ThreadDestroy for %d/%d\n",
558                          getPid(), tmpThread->getLWP());
559
560             Event::ptr destroyEvent = Event::ptr(new EventThreadDestroy(EventType::Post));
561             destroyEvent->setThread(tmpThread->thread());
562             destroyEvent->setProcess(proc());
563             events.push_back(destroyEvent);
564         }
565     }
566
567     return events.size() != oldSize;
568 }
569
570 void thread_db_process::addThreadDBHandlers(HandlerPool *hpool) {
571     static bool initialized = false;
572     static ThreadDBLibHandler *libHandler = NULL;
573     static ThreadDBCreateHandler *createHandler = NULL;
574     static ThreadDBDestroyHandler *destroyHandler = NULL;
575     if( !initialized ) {
576         libHandler = new ThreadDBLibHandler();
577         createHandler = new ThreadDBCreateHandler();
578         destroyHandler = new ThreadDBDestroyHandler();
579         initialized = true;
580     }
581     hpool->addHandler(libHandler);
582     hpool->addHandler(createHandler);
583     hpool->addHandler(destroyHandler);
584 }
585
586 ThreadDBLibHandler::ThreadDBLibHandler() :
587     Handler("thread_db Library Handler")
588 {
589 }
590
591 ThreadDBLibHandler::~ThreadDBLibHandler() 
592 {
593 }
594
595 bool ThreadDBLibHandler::handleEvent(Event::ptr ev) {
596     EventLibrary::const_ptr libEv = ev->getEventLibrary();
597
598     thread_db_process *proc = static_cast<thread_db_process *>(ev->getProcess()->llproc());
599
600     const set<Library::ptr> &addLibs = libEv->libsAdded();
601
602     set<Library::ptr>::iterator libIter;
603     for( libIter = addLibs.begin(); libIter != addLibs.end(); ++libIter ) {
604         if( proc->isSupportedThreadLib((*libIter)->getName()) ) {
605             pthrd_printf("Enabling thread_db support for pid %d\n",
606                     proc->getPid());
607             if( !proc->initThreadDB() ) {
608                 pthrd_printf("Failed to initialize thread_db for pid %d\n",
609                         proc->getPid());
610                 return false;
611             }
612             break;
613         }
614     }
615
616     return true;
617 }
618
619 int ThreadDBLibHandler::getPriority() const {
620     return PostPlatformPriority;
621 }
622
623 void ThreadDBLibHandler::getEventTypesHandled(vector<EventType> &etypes) {
624     etypes.push_back(EventType(EventType::None, EventType::Library));
625 }
626
627 ThreadDBCreateHandler::ThreadDBCreateHandler() :
628     Handler("thread_db New Thread Handler")
629 {
630 }
631
632 ThreadDBCreateHandler::~ThreadDBCreateHandler() 
633 {
634 }
635
636 bool ThreadDBCreateHandler::handleEvent(Event::ptr ev) {
637     EventNewThread::const_ptr threadEv = ev->getEventNewThread();
638
639     thread_db_thread *thread = static_cast<thread_db_thread *>(threadEv->getNewThread()->llthrd());
640
641     assert(thread && "Thread was not initialized before calling this handler");
642
643     // Because the new thread was created during a Breakpoint, it is already of
644     // out of sync with the user state
645     thread->desyncInternalState();
646
647     // Explicitly ignore errors here
648     thread->setEventReporting(true);
649
650     // The initial generator state is stopped
651     thread->suspend();
652
653     return true;
654 }
655
656 int ThreadDBCreateHandler::getPriority() const {
657     return PostPlatformPriority;
658 }
659
660 void ThreadDBCreateHandler::getEventTypesHandled(vector<EventType> &etypes) {
661     etypes.push_back(EventType(EventType::None, EventType::ThreadCreate));
662 }
663
664 ThreadDBDestroyHandler::ThreadDBDestroyHandler() :
665     Handler("thread_db Destroy Handler")
666 {
667 }
668
669 ThreadDBDestroyHandler::~ThreadDBDestroyHandler()
670 {
671 }
672
673 bool ThreadDBDestroyHandler::handleEvent(Event::ptr ev) {
674     thread_db_thread *thrd = static_cast<thread_db_thread *>(ev->getThread()->llthrd());
675     if( ev->getEventType().time() == EventType::Pre) {
676         pthrd_printf("Marking LWP %d destroyed\n", thrd->getLWP());
677         thrd->markDestroyed();
678     }else if( ev->getEventType().time() == EventType::Post) {
679         thrd->setGeneratorState(int_thread::exited);
680
681         // Need to make sure that the thread actually finishes at this point
682         thrd->resume();
683     }
684
685     return true;
686 }
687
688 int ThreadDBDestroyHandler::getPriority() const {
689     return PrePlatformPriority;
690 }
691
692 void ThreadDBDestroyHandler::getEventTypesHandled(vector<EventType> &etypes) {
693     etypes.push_back(EventType(EventType::Any, EventType::ThreadDestroy));
694 }
695
696 thread_db_thread::thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l)
697     : int_thread(p, t, l), threadHandle(NULL), destroyed(false)
698 {
699 }
700
701 thread_db_thread::~thread_db_thread() 
702 {
703     delete threadHandle;
704 }
705
706 bool thread_db_thread::initThreadHandle() {
707     if( NULL != threadHandle ) return true;
708
709     threadHandle = new td_thrhandle_t;
710
711     thread_db_process *lproc = static_cast<thread_db_process *>(proc_);
712
713     td_err_e errVal = td_ta_map_lwp2thr(lproc->getThreadDBAgent(),
714             lwp, threadHandle);
715     if( TD_OK != errVal ) {
716         perr_printf("Failed to map LWP %d to thread_db thread: %s(%d)\n",
717                 lwp, tdErr2Str(errVal), errVal);
718         setLastError(err_internal, "Failed to get thread_db thread handle");
719         return false;
720     }
721
722     return true;
723 }
724
725 Event::ptr thread_db_thread::getThreadEvent() {
726     if( !initThreadHandle() ) return Event::ptr();
727
728     td_event_msg_t eventMsg;
729
730     td_err_e errVal = td_thr_event_getmsg(threadHandle, &eventMsg);
731
732     if( TD_NOMSG == errVal ) {
733         pthrd_printf("No message available for LWP %d via thread_db\n", lwp);
734         return Event::ptr();
735     }
736
737     if( TD_OK != errVal ) {
738         perr_printf("Failed to get thread event message: %s(%d)\n",
739                 tdErr2Str(errVal), errVal);
740         setLastError(err_internal, "Failed to get thread event message");
741         return Event::ptr();
742     }
743
744     return decodeThreadEvent(&eventMsg);
745 }
746
747 bool thread_db_thread::setEventReporting(bool on) {
748     if( !initThreadHandle() ) return false;
749
750     td_err_e errVal = td_thr_event_enable(threadHandle, (on ? 1 : 0 ));
751
752     if( TD_OK != errVal ) {
753         perr_printf("Failed to enable events for LWP %d: %s(%d)\n",
754                 lwp, tdErr2Str(errVal), errVal);
755         setLastError(err_internal, "Failed to enable thread_db events");
756         return false;
757     }
758
759     pthrd_printf("Enabled thread_db events for LWP %d\n", lwp);
760
761     return true;
762 }
763
764 bool thread_db_thread::resume() {
765     if( !initThreadHandle() ) return false;
766
767     td_err_e errVal = td_thr_dbresume(threadHandle);
768
769     if( TD_OK != errVal ) {
770         perr_printf("Failed to resume LWP %d: %s(%d)\n",
771                 lwp, tdErr2Str(errVal), errVal);
772         setLastError(err_internal, "Failed to resume LWP");
773         return false;
774     }
775
776     pthrd_printf("Resumed LWP %d via thread_db\n", lwp);
777
778     return true;
779 }
780
781 bool thread_db_thread::suspend() {
782     if( !initThreadHandle() ) return false;
783
784     td_err_e errVal = td_thr_dbsuspend(threadHandle);
785
786     if( TD_OK != errVal ) {
787         perr_printf("Failed to suspend LWP %d: %s(%d)\n",
788                 lwp, tdErr2Str(errVal), errVal);
789         setLastError(err_internal, "Failed to suspend LWP");
790         return false;
791     }
792
793     pthrd_printf("Suspended LWP %d via thread_db\n", lwp);
794
795     return true;
796 }
797
798 void thread_db_thread::markDestroyed() {
799     destroyed = true;
800 }
801
802 bool thread_db_thread::isDestroyed() {
803     return destroyed;
804 }