Merge branch 'master' into bgq_ramdisk_io
[dyninst.git] / proccontrol / src / int_thread_db.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "common/h/Types.h"
32 #include "proccontrol/src/int_thread_db.h"
33
34
35 #include <cassert>
36 #include <cerrno>
37 #include <cstdarg>
38 #include <cstring>
39 #include <set>
40 #include <dlfcn.h>
41 #include <iostream>
42
43 #include "common/h/dthread.h"
44 #include "dynutil/h/SymReader.h"
45 #include "proccontrol/src/int_event.h"
46 #include "proccontrol/h/Mailbox.h"
47
48 using namespace std;
49
50 #if defined(cap_thread_db)
51
52 /* 
53  * proc_service interface implementation, needed by libthread_db
54  */
55
56 ps_err_e ps_pglobal_lookup(struct ps_prochandle *handle, const char *objName, 
57         const char *symName, psaddr_t *symbolAddr)
58 {
59     pthrd_printf("Looking up symbol %s in %s\n", symName, objName);
60     return handle->thread_db_proc->getSymbolAddr(objName, symName, symbolAddr);
61 }
62
63 ps_err_e ps_pread(struct ps_prochandle *handle, psaddr_t remote, void *local, size_t size) {
64    thread_db_process *llproc = handle->thread_db_proc;
65    pthrd_printf("thread_db reading from %#lx to %#lx, size = %d on %d\n",
66                 (unsigned long)remote, (unsigned long)local, (int)size, llproc->getPid());
67
68    llproc->resps.clear();
69    async_ret_t result = llproc->getMemCache()->readMemory(local, (Address) remote, size,
70                                                           llproc->resps,
71                                                           llproc->triggerThread());
72    
73
74    switch (result) {
75       case aret_success:
76          llproc->hasAsyncPending = false;
77          return PS_OK;
78       case aret_async:
79          llproc->hasAsyncPending = true;
80          pthrd_printf("Incomplete async read in thread_db read\n");
81          return PS_ERR;
82       case aret_error:
83          llproc->hasAsyncPending = false;
84          pthrd_printf("Unexpected read error in thread_db read\n");
85          return PS_ERR;
86    }
87    assert(0);
88    return PS_ERR;
89 }
90
91 ps_err_e ps_pdread(struct ps_prochandle *handle, psaddr_t remote, void *local, size_t size) {
92    return ps_pread(handle, remote, local, size);
93 }
94
95 ps_err_e ps_ptread(struct ps_prochandle *handle, psaddr_t remote, void *local, size_t size) {
96    return ps_pread(handle, remote, local, size);
97 }
98
99 ps_err_e ps_pwrite(struct ps_prochandle *handle, psaddr_t remote, const void *local, size_t size) {
100     pthrd_printf("thread_db writing to %#lx from %#lx, size = %d on %d\n",
101             (unsigned long)remote, (unsigned long)local, (int)size, handle->thread_db_proc->getPid());
102
103     thread_db_process *proc = handle->thread_db_proc;
104
105     async_ret_t result = proc->getMemCache()->writeMemory((Address) remote, 
106                                                           const_cast<void *>(local), 
107                                                           size, 
108                                                           proc->res_resps, 
109                                                           proc->triggerThread());
110     switch (result) {
111       case aret_success:
112          proc->hasAsyncPending = false;
113          return PS_OK;
114       case aret_async:
115          proc->hasAsyncPending = true;
116          pthrd_printf("Incomplete async write in thread_db write\n");
117          return PS_ERR;
118       case aret_error:
119          proc->hasAsyncPending = false;
120          pthrd_printf("Unexpected read error in thread_db write\n");
121          return PS_ERR;
122     }
123     assert(0);
124     return PS_ERR;
125 }
126
127 ps_err_e ps_pdwrite(struct ps_prochandle *handle, psaddr_t remote, const void *local, size_t size) {
128    return ps_pwrite(handle, remote, local, size);
129 }
130
131 ps_err_e ps_ptwrite(struct ps_prochandle *handle, psaddr_t remote, const void *local, size_t size) {
132    return ps_pwrite(handle, remote, local, size);
133 }
134
135 ps_err_e ps_linfo(struct ps_prochandle *handle, lwpid_t lwp, void *lwpInfo) {
136    if( !handle->thread_db_proc->plat_getLWPInfo(lwp, lwpInfo) ) {
137       pthrd_printf("thread_db called ps_linfo, returning error\n");
138       return PS_ERR;
139    }
140    pthrd_printf("thread_db called ps_linfo, returning info\n");
141    return PS_OK;
142 }
143
144 ps_err_e ps_lstop(struct ps_prochandle *handle, lwpid_t lwp) {
145    int_process *proc = handle->thread_db_proc;
146    int_threadPool *tp = proc->threadPool();
147    assert(tp);
148    int_thread *thr = tp->findThreadByLWP((Dyninst::LWP) lwp);
149    if (!thr) {
150       perr_printf("ps_lstop is unable to find LWP %d in process %d\n",
151                   lwp, proc->getPid());
152       return PS_ERR;
153    }
154    pthrd_printf("ps_lstop on %d/%d\n", proc->getPid(), thr->getLWP());
155    
156    if (thr->getInternalState().getState() == int_thread::stopped) {
157       return PS_OK;
158    }
159    else if (thr->getInternalState().getState() != int_thread::running) {
160       perr_printf("Error, ps_lstop on thread in bad state\n");
161       return PS_ERR;
162    }
163
164    thr->getInternalState().setState(int_thread::stopped);
165    
166    return PS_OK;
167 }
168
169 ps_err_e ps_lcontinue(struct ps_prochandle *handle, lwpid_t lwp) {
170    int_process *proc = handle->thread_db_proc;
171    int_threadPool *tp = proc->threadPool();
172    assert(tp);
173    int_thread *thr = tp->findThreadByLWP((Dyninst::LWP) lwp);
174    if (!thr) {
175       perr_printf("ps_lcontinue is unable to find LWP %d in process %d\n",
176                   lwp, proc->getPid());
177       return PS_ERR;
178    }
179    pthrd_printf("ps_lcontinue on %d/%d\n", proc->getPid(), thr->getLWP());
180    
181    if (thr->getInternalState().getState() == int_thread::running) {
182       return PS_OK;
183    }
184    else if (thr->getInternalState().getState() != int_thread::stopped) {
185       perr_printf("Error, ps_lcontinue on thread in bad state\n");
186       return PS_ERR;
187    }
188    
189    thr->getInternalState().setState(int_thread::stopped);
190    return PS_OK;
191 }
192
193 ps_err_e ps_lgetregs(struct ps_prochandle *handle, lwpid_t lwp, prgregset_t regs) {
194    thread_db_process *proc = handle->thread_db_proc;
195    int_threadPool *tp = proc->threadPool();
196    assert(tp);
197    int_thread *llthr = tp->findThreadByLWP((Dyninst::LWP) lwp);
198    if (!llthr) {
199       perr_printf("ps_lgetregs is unable to find LWP %d in process %d\n",
200                   lwp, proc->getPid());
201       return PS_ERR;
202    }
203
204    thread_db_thread *thr = dynamic_cast<thread_db_thread *>(llthr);
205    
206    pthrd_printf("thread_db reading registers on thread %d/%d\n",
207                 proc->getPid(), thr->getLWP());
208    
209    int_registerPool pool;
210    async_ret_t result = proc->getMemCache()->getRegisters(llthr, pool);
211    if (result == aret_async) {
212       pthrd_printf("Async return during get reg\n");
213       return PS_ERR;
214    }
215    if (result == aret_error) {
216       pthrd_printf("Error return during get reg\n");
217       return PS_ERR;
218    }
219
220    bool bresult = thr->plat_convertToSystemRegs(pool, (unsigned char *) regs, true);
221    if (!bresult) {
222       pthrd_printf("Error convering to system regs\n");
223       return PS_ERR;
224    }
225    return PS_OK;
226 }
227
228 pid_t ps_getpid (struct ps_prochandle *ph)
229 {
230    int pid = ph->thread_db_proc->threaddb_getPid();
231    pthrd_printf("thread_db called ps_getpid.  Returning %d\n", pid);
232    return pid;
233 }
234
235 void ps_plog(const char *format, ...) {
236    pthrd_printf("thread_db called ps_plog\n");
237     if( !dyninst_debug_proccontrol ) return;
238     if( NULL == format ) return;
239
240     va_list va;
241     va_start(va, format);
242     vfprintf(pctrl_err_out, format, va);
243     va_end(va);
244 }
245
246 #define NA_IMPLEMENTED "This function is not implemented"
247
248 ps_err_e ps_lgetfpregs(struct ps_prochandle *, lwpid_t, prfpregset_t *) {
249     assert(!NA_IMPLEMENTED);
250     return PS_ERR;
251 }
252
253 ps_err_e ps_lsetfpregs(struct ps_prochandle *, lwpid_t, const prfpregset_t *) {
254     assert(!NA_IMPLEMENTED);
255     return PS_ERR;
256 }
257
258 ps_err_e ps_lsetregs(struct ps_prochandle *, lwpid_t, const prgregset_t) {
259     assert(!NA_IMPLEMENTED);
260     return PS_ERR;
261 }
262
263 ps_err_e ps_lgetxmmregs (struct ps_prochandle *, lwpid_t, char *) {
264     assert(!NA_IMPLEMENTED);
265     return PS_ERR;
266 }
267
268 ps_err_e ps_lsetxmmregs (struct ps_prochandle *, lwpid_t, const char *) {
269     assert(!NA_IMPLEMENTED);
270     return PS_ERR;
271 }
272
273 ps_err_e ps_pcontinue(struct ps_prochandle *) {
274     assert(!NA_IMPLEMENTED);
275     return PS_ERR;
276 }
277
278 ps_err_e ps_pdmodel(struct ps_prochandle *, int *) {
279     assert(!NA_IMPLEMENTED);
280     return PS_ERR;
281 }
282
283 ps_err_e ps_pstop(struct ps_prochandle *) {
284     assert(!NA_IMPLEMENTED);
285     return PS_ERR;
286 }
287
288 ps_err_e ps_get_thread_area(const struct ps_prochandle *phandle, lwpid_t lwp, int val, psaddr_t *addr)
289 {
290    thread_db_process *tdb_proc = phandle->thread_db_proc;
291    thread_db_thread *tdb_thread = dynamic_cast<thread_db_thread *>(tdb_proc->threadPool()->findThreadByLWP(lwp));
292
293    Dyninst::Address daddr = 0;
294    bool result = tdb_thread->thrdb_getThreadArea(val, daddr);
295    if (addr && result)
296       *addr = (psaddr_t) daddr;
297       
298    pthrd_printf("thread_db called ps_get_thread_area.  Returning %s\n", result ? "PS_OK" : "PS_ERR");
299    return result ? PS_OK : PS_ERR;
300 }
301
302 #if defined(THREAD_DB_STATIC)
303 #define TDB_BIND(SYM) \
304    p_ ## SYM = SYM
305 #else
306 #define TDB_BIND(SYM) \
307    do { \
308      p_ ## SYM = (SYM ## _t) dlsym(libhandle, #SYM); \
309      if (!p_ ## SYM) { \
310        const char *errmsg = dlerror();                                       \
311        perr_printf("Error looking up %s in threaddb.so: %s\n", #SYM, errmsg); \
312        return false; \
313      } \
314    } while (0)
315 #endif
316
317 #if defined(THREAD_DB_PATH)
318 #define THREAD_DB_PATH_STR THREAD_DB_PATH
319 #else
320 #define THREAD_DB_PATH_STR NULL
321 #endif
322
323 thread_db_process::td_init_t thread_db_process::p_td_init;
324 thread_db_process::td_ta_new_t thread_db_process::p_td_ta_new;
325 thread_db_process::td_ta_delete_t thread_db_process::p_td_ta_delete;
326 thread_db_process::td_ta_event_addr_t thread_db_process::p_td_ta_event_addr;
327 thread_db_process::td_ta_set_event_t thread_db_process::p_td_ta_set_event;
328 thread_db_process::td_ta_map_lwp2thr_t thread_db_process::p_td_ta_map_lwp2thr;
329 thread_db_process::td_ta_event_getmsg_t thread_db_process::p_td_ta_event_getmsg;
330 thread_db_process::td_thr_get_info_t thread_db_process::p_td_thr_get_info;
331 thread_db_process::td_thr_event_enable_t thread_db_process::p_td_thr_event_enable;
332 thread_db_process::td_thr_set_event_t thread_db_process::p_td_thr_set_event;
333 thread_db_process::td_thr_event_getmsg_t thread_db_process::p_td_thr_event_getmsg;
334 thread_db_process::td_thr_dbsuspend_t thread_db_process::p_td_thr_dbsuspend;
335 thread_db_process::td_thr_dbresume_t thread_db_process::p_td_thr_dbresume;
336
337 bool thread_db_process::tdb_loaded = false;
338 bool thread_db_process::tdb_loaded_result = false;
339
340 #if !defined(THREAD_DB_STATIC)
341 static void *dlopenThreadDB(char *path)
342 {
343    std::string filename;
344    std::string alt_filename;
345    if (path) {
346       filename = std::string(path);
347       if (*filename.rend() != '/') {
348          filename += std::string("/");
349       }
350       filename += std::string("libthread_db.so");
351 #if !defined(os_bg)
352       //On BG alt_filename would try to load /lib/libthread_db.so, which is
353       // for the IO node.
354       alt_filename = std::string("libthread_db.so");
355 #endif
356
357    }
358    else {
359       filename = std::string("libthread_db.so");
360    }
361
362 #if defined(os_bgq)
363    alt_filename = filename;
364    filename = std::string("/bgsys/drivers/ppcfloor/gnu-linux/powerpc64-bgq-linux/lib/libthread_db.so.1");
365 #endif
366
367    pthrd_printf("Opening thread_db with %s\n", filename.c_str());
368    void *libhandle = dlopen(filename.c_str(), RTLD_LAZY);
369    if (!libhandle && !alt_filename.empty()) {
370    pthrd_printf("Opening thread_db with %s\n", alt_filename.c_str());
371       libhandle = dlopen(alt_filename.c_str(), RTLD_LAZY);
372    }
373    if (!libhandle) {
374       const char *errmsg = dlerror();
375       perr_printf("Error loading libthread_db.so: %s\n", errmsg);
376       return NULL;
377    }
378    return libhandle;
379 }
380
381 #else
382 static void *dlopenThreadDB(char *)
383 {
384    return (void *) 0x1;  //Return anything non-NULL
385 }
386 #endif
387
388 bool thread_db_process::loadedThreadDBLibrary()
389 {
390    if (tdb_loaded)
391       return tdb_loaded_result;
392    tdb_loaded = true;
393    
394    void *libhandle = dlopenThreadDB(THREAD_DB_PATH_STR);
395    if (!libhandle)
396       return false;
397
398    TDB_BIND(td_init);
399    TDB_BIND(td_ta_new);
400    TDB_BIND(td_ta_delete);
401    TDB_BIND(td_ta_event_addr);
402    TDB_BIND(td_ta_set_event);
403    TDB_BIND(td_ta_event_getmsg);
404    TDB_BIND(td_ta_map_lwp2thr);
405    TDB_BIND(td_thr_get_info);
406    TDB_BIND(td_thr_event_enable);
407    TDB_BIND(td_thr_set_event);
408    TDB_BIND(td_thr_event_getmsg);
409    TDB_BIND(td_thr_dbsuspend);
410    TDB_BIND(td_thr_dbresume);
411
412    pthrd_printf("Successfully loaded thread_db.so library\n");
413    tdb_loaded_result = true;
414    return true;
415 }
416
417 #ifndef CASE_RETURN_STR
418 #define CASE_RETURN_STR(x) case x: return #x;
419 #endif
420
421 static const char *tdErr2Str(td_err_e errVal) {
422     switch(errVal) {
423         CASE_RETURN_STR(TD_ERR)
424         CASE_RETURN_STR(TD_OK)
425         CASE_RETURN_STR(TD_BADKEY)
426         CASE_RETURN_STR(TD_BADPH)
427         CASE_RETURN_STR(TD_BADSH)
428         CASE_RETURN_STR(TD_BADTA)
429         CASE_RETURN_STR(TD_BADTH)
430         CASE_RETURN_STR(TD_DBERR)
431         CASE_RETURN_STR(TD_MALLOC)
432         CASE_RETURN_STR(TD_NOAPLIC)
433         CASE_RETURN_STR(TD_NOCAPAB)
434         CASE_RETURN_STR(TD_NOEVENT)
435         CASE_RETURN_STR(TD_NOFPREGS)
436         CASE_RETURN_STR(TD_NOLIBTHREAD)
437         CASE_RETURN_STR(TD_NOLWP)
438         CASE_RETURN_STR(TD_NOMSG)
439         CASE_RETURN_STR(TD_NOSV)
440         CASE_RETURN_STR(TD_NOTHR)
441         CASE_RETURN_STR(TD_NOTSD)
442         CASE_RETURN_STR(TD_NOXREGS)
443         CASE_RETURN_STR(TD_PARTIALREG)
444         default:
445             return "?";
446     }
447 }
448
449 Event::ptr thread_db_process::decodeThreadEvent(td_event_msg_t *eventMsg, bool &async)
450 {
451    td_thrinfo_t info;
452    async = false;
453    td_thrhandle_t *handle = const_cast<td_thrhandle_t *>(eventMsg->th_p);
454    pthrd_printf("Decoding thread event on %u\n", getPid());
455    async_ret_t result = ll_fetchThreadInfo(handle, &info);
456    if (result == aret_error) {
457       pthrd_printf("Failed to fetch thread info\n");
458       return Event::ptr();
459    }
460    if (result == aret_async) {
461       async = true;
462       pthrd_printf("Returning async from decodeThreadEvent\n");
463       return Event::ptr();
464    }
465    Dyninst::LWP lwp = (Dyninst::LWP) info.ti_lid;
466    int_thread *thr = threadPool()->findThreadByLWP(lwp); //thr may be NULL if OS doesn't support LWP events (BG/P) 
467    switch(eventMsg->event) {
468       case TD_CREATE:
469       {
470          pthrd_printf("Decoded to user thread create of %d/%d\n", getPid(), lwp);
471
472          EventNewUserThread::ptr new_ev = EventNewUserThread::ptr(new EventNewUserThread());
473          new_ev->setProcess(proc());
474          new_ev->setThread(thr ? thr->thread() : Thread::ptr());
475          new_ev->setSyncType(Event::sync_process);
476          int_eventNewUserThread *iev = new_ev->getInternalEvent();
477
478          new_thread_data_t *thrdata = (new_thread_data_t *) malloc(sizeof(new_thread_data_t));
479          thrdata->thr_handle = new td_thrhandle_t(*handle);
480          thrdata->thr_info = info;
481          thrdata->threadHandle_alloced = true;
482
483          iev->raw_data = (void *) thrdata;
484          iev->lwp = lwp;
485
486          if (threadPool()->initialThread() == thr)
487             initialThreadEventCreated = true;
488
489          return new_ev;
490       }
491       case TD_DEATH: {
492          pthrd_printf("Decoded to user thread death of %d/%d\n", getPid(), lwp);
493          if (!thr) {
494             perr_printf("Error.  Got thread delete event for unknown LWP\n");
495             return Event::ptr();
496          }
497
498          EventUserThreadDestroy::ptr new_ev = EventUserThreadDestroy::ptr(new EventUserThreadDestroy(EventType::Pre));
499          new_ev->setProcess(proc());
500          new_ev->setThread(thr->thread());
501          new_ev->setSyncType(Event::sync_process);
502
503          return new_ev;
504       }
505       default: {
506          pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
507          break;
508       }
509    }
510
511    return Event::ptr();
512 }
513
514 volatile bool thread_db_process::thread_db_initialized = false;
515 Mutex thread_db_process::thread_db_init_lock;
516
517 thread_db_process::thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> envp, std::vector<std::string> a, std::map<int, int> f) :
518   int_process(p, e, a, envp, f),
519   int_threadTracking(p, e, a, envp, f),
520   thread_db_proc_initialized(false),
521   threadAgent(NULL),
522   createdThreadAgent(false),
523   self(NULL),
524   trigger_thread(NULL),
525   hasAsyncPending(false),
526   initialThreadEventCreated(false),
527   setEventSet(false),
528   completed_post(false),
529   track_threads(ThreadTracking::getDefaultTrackThreads())
530 {
531    if (!loadedThreadDBLibrary())
532       return;
533    self = new ps_prochandle();
534    assert(self);
535    self->thread_db_proc = this;
536 }
537
538 thread_db_process::thread_db_process(Dyninst::PID pid_, int_process *p) :
539   int_process(pid_, p),
540   int_threadTracking(pid_, p), 
541   thread_db_proc_initialized(false),
542   threadAgent(NULL),
543   createdThreadAgent(false),
544   self(NULL),
545   trigger_thread(NULL),
546   hasAsyncPending(false),
547   initialThreadEventCreated(false),
548   setEventSet(false),
549   completed_post(false),
550   track_threads(ThreadTracking::getDefaultTrackThreads())
551 {
552    if (!loadedThreadDBLibrary())
553       return;
554    self = new ps_prochandle();
555    assert(self);
556    self->thread_db_proc = this;
557 }
558
559 thread_db_process::~thread_db_process() 
560 {
561     // Free the breakpoints allocated for events
562     map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator brkptIter;
563     for(brkptIter = addr2Event.begin(); brkptIter != addr2Event.end(); ++brkptIter) {
564         delete brkptIter->second.first;
565     }
566
567     if (self)
568        delete self;
569 }
570
571 async_ret_t thread_db_process::initThreadWithHandle(td_thrhandle_t *thr, td_thrinfo_t *info, LWP lwp)
572 {
573    pthrd_printf("initThreadWithHandle on %d/%d\n", getPid(), lwp);
574
575    td_thrinfo_t tinfo;
576    if (!info) {
577       async_ret_t result = ll_fetchThreadInfo(thr, &tinfo);
578       if (result == aret_error) {
579          pthrd_printf("Error calling ll_fetchThreadInfo from initThreadWithHandle\n");
580          return aret_error;
581       }
582       if (result == aret_async) {
583          pthrd_printf("Returning async from initThreadWithHandle\n");
584          return aret_async;
585       }
586       info = &tinfo;
587    }
588
589    if (lwp == NULL_LWP) {
590       lwp = (Dyninst::LWP) info->ti_lid;
591       pthrd_printf("initThreadWithHandle found thread %d/%d\n", getPid(), lwp);
592    }
593    thread_db_thread *tdb_thread = dynamic_cast<thread_db_thread *>(threadPool()->findThreadByLWP(lwp));
594    if (!tdb_thread) {
595       perr_printf("Error.  Thread_db reports thread %d/%d, but couldn't find existing LWP\n",
596                   getPid(), lwp);
597       return aret_error;
598    }
599    if (tdb_thread->thread_initialized) {
600       return aret_success;
601    }
602    pthrd_printf("thread_db handling thread create for %d/%d\n", getPid(), lwp);
603    tdb_thread->threadHandle = thr;
604    tdb_thread->tinfo = *info;
605    if (info->ti_tid)
606       tdb_thread->tinfo_initialized = true;
607
608    getMemCache()->markToken(token_seteventreporting);
609    async_ret_t result = tdb_thread->setEventReporting(true);
610    if (result == aret_error) {
611       pthrd_printf("Error in setEventReporting for %d/%d\n", getPid(), tdb_thread->getLWP());
612       return aret_error;
613    }
614    if (result == aret_async) {
615       pthrd_printf("Async return in setEventReporting for %d/%d\n", getPid(), tdb_thread->getLWP());
616       return aret_async;
617    }
618    getMemCache()->condense();
619    tdb_thread->thread_initialized = true;
620    return aret_success;
621 }
622
623
624 async_ret_t thread_db_process::handleThreadAttach(td_thrhandle_t *thr, Dyninst::LWP lwp)
625 {
626    return initThreadWithHandle(thr, NULL, lwp);
627 }
628
629 async_ret_t thread_db_process::initThreadDB() {
630     // Q: Why isn't this in the constructor? 
631     // A: This function depends on the corresponding thread library being loaded
632     // and this event occurs some time after process creation.
633
634    if (!track_threads) {
635       return aret_success;
636    }
637     // Make sure thread_db is initialized - only once for all instances
638    if( !thread_db_initialized ) {
639       pthrd_printf("Initializing thread_db library\n");
640       thread_db_init_lock.lock();
641       if( !thread_db_initialized ) {
642          if (!loadedThreadDBLibrary()) {
643             setLastError(err_internal, "libthread_db was not loaded");
644             thread_db_init_lock.unlock();
645             return aret_error;
646          }
647          td_err_e errVal;
648          if( TD_OK != (errVal = p_td_init()) ) {
649             perr_printf("Failed to initialize libthread_db: %s(%d)\n",
650                         tdErr2Str(errVal), errVal);
651             setLastError(err_internal, "libthread_db initialization failed");
652             thread_db_init_lock.unlock();
653             return aret_error;
654           }
655          pthrd_printf("Sucessfully initialized thread_db\n");
656          thread_db_initialized = true;
657       }
658       thread_db_init_lock.unlock();
659    }
660    if (thread_db_proc_initialized) {
661       return aret_success;
662    }
663
664    getMemCache()->markToken(token_init);   
665    // Create the thread agent
666    td_err_e errVal;
667    if (!createdThreadAgent)
668    {
669       pthrd_printf("Creating threadAgent\n");
670       errVal = p_td_ta_new(self, &threadAgent);
671       switch(errVal) {
672          case TD_OK:
673             pthrd_printf("Retrieved thread agent from thread_db\n");
674             break;
675          case TD_NOLIBTHREAD:
676             pthrd_printf("Debuggee isn't multithreaded at this point, libthread_db not enabled\n");
677             return aret_success;
678          case TD_ERR:
679             if (getMemCache()->hasPendingAsync()) {
680                pthrd_printf("Postponing thread_db initialization for async\n");
681                return aret_async;
682             }
683          default:
684             perr_printf("Failed to create thread agent: %s(%d)\n",
685                         tdErr2Str(errVal), errVal);
686             thread_db_proc_initialized = true;
687             setLastError(err_internal, "Failed to create libthread_db agent");
688             return aret_error;
689       }
690       createdThreadAgent = true;
691    }
692
693    bool hasAsync = false;
694    set<pair<td_thrhandle_t *, LWP> > all_handles;
695    for (int_threadPool::iterator i = threadPool()->begin(); i != threadPool()->end(); i++) {
696       thread_db_thread *tdb_thread = dynamic_cast<thread_db_thread *>(*i);
697       
698       if (tdb_thread->threadHandle_alloced) {
699          all_handles.insert(pair<td_thrhandle_t *, LWP>(tdb_thread->threadHandle, tdb_thread->getLWP()));
700          continue;
701       }
702       
703       if (!tdb_thread->threadHandle) {
704          tdb_thread->threadHandle = new td_thrhandle_t;
705          memset(tdb_thread->threadHandle, 0, sizeof(td_thrhandle_t));
706       }
707       
708       pthrd_printf("lwp2thr on %d/%d\n", getPid(), tdb_thread->getLWP());
709       errVal = p_td_ta_map_lwp2thr(getThreadDBAgent(), tdb_thread->getLWP(), tdb_thread->threadHandle);
710       if (errVal != TD_OK) {
711          if (getMemCache()->hasPendingAsync()) {
712             pthrd_printf("Hit async during lwp2thr\n");
713             hasAsync = true;
714             continue;
715          }
716          perr_printf("Failed to map LWP %d to thread_db thread: %s(%d)\n",
717                      tdb_thread->getLWP(), tdErr2Str(errVal), errVal);
718          setLastError(err_internal, "Failed to get thread_db thread handle");
719          delete tdb_thread->threadHandle;
720          tdb_thread->threadHandle = NULL;
721          continue;
722       }
723       pthrd_printf("Successful lwp2thr on %d/%d\n", getPid(), tdb_thread->getLWP());
724       tdb_thread->threadHandle_alloced = true;
725       all_handles.insert(pair<td_thrhandle_t *, LWP>(tdb_thread->threadHandle, tdb_thread->getLWP()));
726    }
727    if (hasAsync) {
728       pthrd_printf("Postponing lwp2thr for async\n");
729       return aret_async;
730    }
731
732    pthrd_printf("handleThreadAttach for %d threads\n", (int) all_handles.size());
733    for (set<pair<td_thrhandle_t *, LWP> >::iterator i = all_handles.begin(); i != all_handles.end(); i++)
734    {
735       async_ret_t result = handleThreadAttach(i->first, i->second);
736       if (result == aret_error) {
737          perr_printf("Error handling thread_db attach\n");
738          return aret_error;
739       }
740       if (result == aret_async) {
741          pthrd_printf("handleThreadAttach returned async in initThreadDB\n");
742          return aret_async;
743       }
744    }
745    
746    // Enable all events
747    td_thr_events_t eventMask;
748 #if defined(td_event_fillset)
749    //Macro on GNU libc
750    td_event_fillset(&eventMask);
751 #elif defined(os_freebsd)
752    //Inline header file function on FreeBSD
753    td_event_fillset(&eventMask);
754 #else
755 //Need to make td_event_fillset a function pointer if this hits
756 #error td_event_fillset is not a macro on this platform
757 #endif
758
759    if (!setEventSet) {
760       getMemCache()->markToken(token_setevent);
761       errVal = p_td_ta_set_event(threadAgent, &eventMask);
762       if( errVal != TD_OK && getMemCache()->hasPendingAsync()) {
763          pthrd_printf("Async return from td_ta_set_event in initThreadDB\n");
764          return aret_async;
765       }
766       setEventSet = true;
767       getMemCache()->condense();
768       if (errVal != TD_OK) {
769          perr_printf("Failed to enable events: %s(%d)\n",
770                      tdErr2Str(errVal), errVal);
771          setLastError(err_internal, "Failed to enable libthread_db events");
772          thread_db_proc_initialized = true;
773          return aret_error;
774       }
775    }
776
777     // Determine the addresses for all events
778    td_event_e allEvents[] = { TD_CATCHSIG, TD_CONCURRENCY, TD_CREATE,
779                               TD_DEATH, TD_IDLE, TD_LOCK_TRY, TD_PREEMPT, TD_PRI_INHERIT,
780                               TD_READY, TD_REAP, TD_SLEEP, TD_SWITCHFROM, TD_SWITCHTO,
781                               TD_TIMEOUT };
782
783    for(unsigned i = 0; i < (sizeof(allEvents)/sizeof(td_event_e)); ++i) {
784       td_notify_t notifyResult;
785       errVal = p_td_ta_event_addr(threadAgent, allEvents[i], &notifyResult);
786       
787       // This indicates that the event isn't supported
788       if( TD_OK != errVal ) continue;
789       
790       assert( notifyResult.type == NOTIFY_BPT && "Untested notify type" );
791       
792       EventType newEvent;
793       switch(allEvents[i]) {
794          case TD_CREATE:
795             newEvent = EventType(EventType::Post, EventType::ThreadCreate);
796             pthrd_printf("Installing breakpoint for thread creation events\n");
797             break;
798          case TD_DEATH:
799             newEvent = EventType(EventType::Post, EventType::ThreadDestroy);
800             pthrd_printf("Installing breakpoint for thread destroy events\n");
801             break;
802          default:
803             pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
804             continue;
805       }
806       
807       Address addr = (Address) notifyResult.u.bptaddr;
808       pthrd_printf("Received address of 0x%lx for breakpoint, checking platform conversion\n",
809                    addr);
810       if( !plat_convertToBreakpointAddress(addr, triggerThread()) ) {
811          perr_printf("Failed to determine breakpoint address\n");
812          setLastError(err_internal, "Failed to install new thread_db event breakpoint");
813          thread_db_proc_initialized = true;
814          return aret_error;
815       }
816       pthrd_printf("Post-conversion, using address of 0x%lx\n", addr);
817 #if defined(os_freebsd)
818       notifyResult.u.bptaddr = (psaddr_t) addr;
819 #else
820       notifyResult.u.bptaddr = (void *) addr;
821 #endif 
822       int_breakpoint *newEventBrkpt = new int_breakpoint(Breakpoint::ptr());
823       newEventBrkpt->setProcessStopper(true);
824       if( !addBreakpoint(addr, newEventBrkpt))
825       {
826          perr_printf("Failed to install new event breakpoint\n");
827          setLastError(err_internal, "Failed to install new thread_db event breakpoint");
828          delete newEventBrkpt;
829          thread_db_proc_initialized = true;
830          return aret_error;
831          }
832       
833       pair<map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator, bool> insertIter;
834       insertIter = addr2Event.insert(make_pair(addr, make_pair(newEventBrkpt, newEvent)));
835
836       assert( insertIter.second && "event breakpoint address not unique" );
837    }
838    
839    thread_db_proc_initialized = true;
840    return aret_success;
841 }
842
843 void thread_db_process::freeThreadDBAgent() {
844     // This code cannot be in the destructor because it makes use of
845     // the proc_service interface and this makes calls to functions
846     // that are pure virtual in this class.
847     //
848     // A possible, better solution would be to make the functions static
849     // but we lose all the convenience of pure virtual functions
850     //
851     // At any rate, this function should be called from a derived class' 
852     // destructor for the time being.
853
854     if( thread_db_initialized && threadAgent ) {
855         td_err_e errVal = p_td_ta_delete(threadAgent);
856         if( TD_OK != errVal ) {
857             perr_printf("Failed to delete thread agent: %s(%d)\n",
858                     tdErr2Str(errVal), errVal);
859         }
860         assert( TD_OK == errVal && "Failed to delete thread agent" );
861         threadAgent = NULL;
862     }
863 }
864
865 const char *thread_db_process::getThreadLibName(const char *)
866 {
867    return "";
868 }
869
870 bool thread_db_process::decodeTdbLWPExit(EventLWPDestroy::ptr lwp_ev)
871 {
872    thread_db_thread *db_thread = dynamic_cast<thread_db_thread *>(lwp_ev->getThread()->llthrd());
873    assert(db_thread);
874    
875    if (db_thread->destroyed || !db_thread->thread_initialized)
876       return false;
877
878    pthrd_printf("Decoded LWP exit without thread exit on %d/%d.  Faking thread exit event\n",
879                 db_thread->llproc()->getPid(), db_thread->getLWP());
880
881    EventUserThreadDestroy::ptr new_ev = EventUserThreadDestroy::ptr(new EventUserThreadDestroy(EventType::Post));
882    new_ev->setProcess(db_thread->llproc()->proc());
883    new_ev->setThread(db_thread->thread());
884    new_ev->setSyncType(Event::async);
885    lwp_ev->addSubservientEvent(new_ev);
886
887    return true;
888 }
889
890 async_ret_t thread_db_process::decodeTdbBreakpoint(EventBreakpoint::ptr bp)
891
892     // Decoding thread_db events needs to be a two-step process:
893     // 1) Create events depending on the breakpoint address
894     //    Don't get events from thread_db as this can write to memory
895     //    and threads could currently be running -- introduces some race
896     //    conditions where the running threads could be modifying data
897     //    structures thread_db is accessing
898     //    Just create placeholder events that can later be filled in with
899     //    more information
900     // 2) Get events from thread_db in the handler for the event, at this
901     //    point all threads are stopped and it is safe to make changes to
902     //    memory because the parent event is a breakpoint and requires
903     //    that all threads are stopped
904     Dyninst::Address addr = bp->getAddress();
905     
906     // Determine what type of event occurs at the specified address
907     map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator addrIter;
908     addrIter = addr2Event.find(addr);
909     if (addrIter == addr2Event.end()) 
910        return aret_error;
911
912     vector<Event::ptr> threadEvents;
913
914     EventType::Code ecode = addrIter->second.second.code();
915     pthrd_printf("Address 0x%lx corresponds to a thread %s breakpoint.\n",
916                  addr, ecode == EventType::ThreadCreate ? "create" : "destroy");
917     switch(ecode) {
918        case EventType::ThreadCreate:
919        case EventType::ThreadDestroy:
920           threadEvents.push_back(EventThreadDB::ptr(new EventThreadDB()));
921           break;
922        default:
923           pthrd_printf("Failed to decode any thread events due to the breakpoint\n");
924           return aret_error;
925     }
926
927     for (vector<Event::ptr>::iterator i = threadEvents.begin(); i != threadEvents.end(); i++) {
928        Event::ptr ev = *i;
929        if (!ev->getThread()) 
930           ev->setThread(bp->getThread());
931        if (!ev->getProcess()) 
932           ev->setProcess(proc());
933        if (ev->getSyncType() == Event::unset)
934           ev->setSyncType(Event::sync_process);
935        bp->addSubservientEvent(ev);
936     }
937     bp->setSuppressCB(true);
938     return aret_success;
939 }
940
941 td_thragent_t *thread_db_process::getThreadDBAgent() {
942     return threadAgent;
943 }
944
945 static string stripLibraryName(const char *libname)
946 {
947    const char *filename_c = strrchr(libname, '/');
948    if (!filename_c)
949       filename_c = strrchr(libname, '\\');
950    if (!filename_c) 
951       filename_c = libname;
952    else 
953       filename_c++;
954    
955    const char *lesser_ext = NULL;
956    const char *dot_ext = strchr(filename_c, '.');
957    if (dot_ext)
958       lesser_ext = dot_ext;
959    const char *dash_ext = strchr(filename_c, '-');
960    if (dash_ext && (!lesser_ext || dash_ext < lesser_ext))
961       lesser_ext = dash_ext;
962
963    if (!lesser_ext) {
964       return std::string(filename_c);
965    }
966    return std::string(filename_c, lesser_ext - filename_c);
967 }
968
969 ps_err_e thread_db_process::getSymbolAddr(const char *objName, const char *symName,
970         psaddr_t *symbolAddr)
971 {
972     SymReader *objSymReader = NULL;
973     int_library *lib = NULL;
974     
975     if (plat_isStaticBinary()) {
976        // For static executables, we need to search the executable instead of the
977        // thread library. 
978        assert(memory()->libs.size() == 1);
979        lib = *memory()->libs.begin();
980     }
981     else
982     {
983        // FreeBSD implementation doesn't set objName
984        const char *name_c = objName ? objName : getThreadLibName(symName);
985        std::string name = stripLibraryName(name_c);
986        
987        for (set<int_library *>::iterator i = memory()->libs.begin(); i != memory()->libs.end(); i++) {
988           int_library *l = *i;
989           if (strstr(l->getName().c_str(), name.c_str())) {
990              lib = l;
991              break;
992           }
993        }
994     }
995
996     if( NULL == lib ) {
997        pthrd_printf("Didn't yet find loaded thread library\n");
998        return PS_ERR;
999     }
1000
1001     objSymReader = getSymReader()->openSymbolReader(lib->getName());
1002     if( NULL == objSymReader ) {
1003         perr_printf("Failed to open symbol reader for %s\n",
1004                     lib->getName().c_str());
1005         setLastError(err_internal, "Failed to open executable for symbol reading");
1006         return PS_ERR;
1007     }
1008
1009     Symbol_t lookupSym = objSymReader->getSymbolByName(string(symName));
1010
1011     if( !objSymReader->isValidSymbol(lookupSym) ) {
1012        pthrd_printf("thread_db getSymbolAddr(%s, %s) = none\n", objName ? objName : "NULL", 
1013                     symName ? symName : "NULL");
1014        return PS_NOSYM;
1015     }
1016     
1017     Address tmp = lib->getAddr() + objSymReader->getSymbolOffset(lookupSym);
1018     if (getAddressWidth() == 4) {
1019        tmp &= 0xffffffff;
1020     }
1021     
1022     *symbolAddr = (psaddr_t) tmp;
1023
1024     pthrd_printf("thread_db getSymbolAddr(%s, %s) = %p\n", objName ? objName : "NULL", 
1025                  symName ? symName : "NULL", (void *) *symbolAddr);
1026     return PS_OK;
1027 }
1028
1029
1030 async_ret_t thread_db_process::post_create(std::set<response::ptr> &async_responses)
1031 {
1032    async_ret_t result;
1033    if (!completed_post) {
1034       result = int_process::post_create(async_responses);
1035       if (result != aret_success)
1036          return result;
1037       completed_post = true;
1038    }
1039
1040    err_t last_error = getLastError();
1041    const char *last_err_msg = getLastErrorMsg();
1042
1043    getMemCache()->setSyncHandling(true);
1044    for (;;) {
1045       result = initThreadDB();
1046       if (result != aret_async)
1047          break;
1048       getMemCache()->getPendingAsyncs(async_responses);
1049       return aret_async;
1050    }
1051    getMemCache()->setSyncHandling(false);
1052
1053    setLastError(last_error, last_err_msg);
1054    return aret_success; //Swallow these errors, thread_db failure does not bring down rest of startup
1055 }
1056
1057 async_ret_t thread_db_process::post_attach(bool wasDetached, set<response::ptr> &aresps) {
1058    async_ret_t result;
1059    if (!completed_post) {
1060       result = int_process::post_attach(wasDetached, aresps);
1061       if (result != aret_success)
1062          return result;
1063       completed_post = true;
1064    }
1065    
1066    err_t last_error = getLastError();
1067    const char *last_err_msg = getLastErrorMsg();
1068
1069    getMemCache()->setSyncHandling(true);
1070    for (;;) {
1071       result = initThreadDB();
1072       if (result != aret_async)
1073          break;
1074       getMemCache()->getPendingAsyncs(aresps);
1075       return aret_async;
1076    }
1077    getMemCache()->setSyncHandling(false);
1078
1079    setLastError(last_error, last_err_msg);
1080    return aret_success; //Swallow these errors, thread_db failure does not bring down rest of startup
1081 }
1082
1083 #if 0
1084 #warning TODO fix detach part in post attach rewrite
1085 bool thread_db_process::post_attach(bool wasDetached) {
1086     if( !int_process::post_attach(wasDetached) ) return false;
1087
1088     if( !wasDetached ) {
1089         return initThreadDB();
1090     }else{
1091         // Need to initialize all new threads
1092         bool success = true;
1093         td_err_e errVal;
1094         for (int_threadPool::iterator i = threadPool()->begin(); i != threadPool()->end(); i++) {
1095            thread_db_thread *tdb_thread = static_cast<thread_db_thread *>(*i);
1096            if( tdb_thread->thread_initialized ) continue;
1097
1098            tdb_thread->threadHandle = new td_thrhandle_t;
1099
1100            errVal = td_ta_map_lwp2thr(getThreadDBAgent(), tdb_thread->getLWP(), tdb_thread->threadHandle);
1101            if (errVal != TD_OK) {
1102               perr_printf("Failed to map LWP %d to thread_db thread: %s(%d)\n",
1103                           tdb_thread->getLWP(), tdErr2Str(errVal), errVal);
1104               setLastError(err_internal, "Failed to get thread_db thread handle");
1105               delete tdb_thread->threadHandle;
1106               tdb_thread->threadHandle = NULL;
1107               success = false;
1108               continue;
1109            }
1110            tdb_thread->threadHandle_alloced = true;
1111
1112            if( !handleThreadAttach(tdb_thread->threadHandle) ) {
1113                perr_printf("Error handling thread_db attach\n");
1114                success = false;
1115            }
1116         }
1117
1118         return success;
1119     }
1120 }
1121 #endif
1122
1123 bool thread_db_process::isSupportedThreadLib(string libName) {
1124    return (libName.find("libpthread") != string::npos);
1125 }
1126
1127 void thread_db_process::addThreadDBHandlers(HandlerPool *hpool) {
1128    static bool initialized = false;
1129    static ThreadDBLibHandler *libHandler = NULL;
1130    static ThreadDBCreateHandler *createHandler = NULL;
1131    static ThreadDBDestroyHandler *destroyHandler = NULL;
1132    static ThreadDBDispatchHandler *dispatchHandler = NULL;
1133    if( !initialized ) {
1134       libHandler = new ThreadDBLibHandler();
1135       createHandler = new ThreadDBCreateHandler();
1136       destroyHandler = new ThreadDBDestroyHandler();
1137       dispatchHandler = new ThreadDBDispatchHandler();
1138       initialized = true;
1139    }
1140    hpool->addHandler(libHandler);
1141    hpool->addHandler(createHandler);
1142    hpool->addHandler(destroyHandler);
1143    hpool->addHandler(dispatchHandler);
1144 }
1145
1146 bool thread_db_process::plat_getLWPInfo(lwpid_t, void *) 
1147 {
1148    perr_printf("Attempt to use unsupported plat_getLWPInfo\n");
1149    return false;
1150 }
1151
1152 bool thread_db_process::plat_supportThreadEvents()
1153 {
1154    if (!loadedThreadDBLibrary()) {
1155       return false;
1156    }
1157    return true;
1158 }
1159
1160 bool thread_db_thread::plat_convertToSystemRegs(const int_registerPool &,
1161                                                 unsigned char *, bool)
1162 {
1163     return true;
1164 }
1165
1166 int_thread *thread_db_process::triggerThread() const
1167 {
1168    return trigger_thread;
1169 }
1170
1171 async_ret_t thread_db_process::ll_fetchThreadInfo(td_thrhandle_t *th, td_thrinfo_t *info)
1172 {
1173    td_err_e result = thread_db_process::p_td_thr_get_info(th, info);
1174    if (result != TD_OK) {
1175       if (getMemCache()->hasPendingAsync()) {
1176          pthrd_printf("Async return from td_thr_get_info in ll_fetchThreadInfo\n");
1177          return aret_async;
1178       }
1179       perr_printf("Error calling td_thr_get_info: %s (%d)\n", tdErr2Str(result), (int) result);
1180       return aret_error;
1181    }
1182    pthrd_printf("Successful ll_fetchThreadInfo for handle %p - tid = %lu, lid = %lu\n", th, (unsigned long) info->ti_tid, (unsigned long) info->ti_lid);
1183    return aret_success;
1184 }
1185
1186 ThreadDBDispatchHandler::ThreadDBDispatchHandler() :
1187    Handler("thread_db Dispatch Handler")
1188 {
1189 }
1190
1191 ThreadDBDispatchHandler::~ThreadDBDispatchHandler()
1192 {
1193 }
1194
1195 int ThreadDBDispatchHandler::getPriority() const
1196 {
1197    return Handler::PostPlatformPriority;
1198 }
1199
1200 Handler::handler_ret_t ThreadDBDispatchHandler::handleEvent(Event::ptr ev)
1201 {
1202    /**
1203     * All we know is that we got a thread_db breakpoint, but we don't
1204     * know whether that was a thread create/destroy, or any information
1205     * about those events.  We'll collect that info here, then add
1206     * UserThreadCreate or UserThreadDestroy events as 'late' events 
1207     * (means they were generated at handle time) to this event.
1208     **/
1209    pthrd_printf("At top of ThreadDB Dispatch handler\n");
1210    EventThreadDB::ptr etdb = ev->getEventThreadDB();
1211    assert(etdb);
1212    int_eventThreadDB *int_ev = etdb->getInternal();
1213    assert(int_ev);
1214
1215    thread_db_process *proc = dynamic_cast<thread_db_process *>(etdb->getProcess()->llproc());
1216    assert(proc);
1217
1218    if (proc->dispatch_event && proc->dispatch_event != etdb) {
1219       //We don't need to handle a new dispatch event if another is in
1220       //progress.  We'll drop the second.
1221       pthrd_printf("Dropping dispatch event, another is in progress\n");
1222       return ret_success;
1223    }
1224    proc->dispatch_event = etdb;
1225
1226    if (!int_ev->completed_new_evs) {
1227       async_ret_t result = proc->getEventForThread(int_ev->new_evs);
1228       if (result == aret_async) {
1229          pthrd_printf("getEventForThread returned async\n");
1230          return ret_async;
1231       }
1232       int_ev->completed_new_evs = true;
1233       if (result == aret_error) {
1234          pthrd_printf("getEventForThread returned error\n");
1235          proc->dispatch_event = EventThreadDB::ptr();
1236          return ret_error;
1237       }
1238    }
1239
1240    thread_db_thread *main_thread = dynamic_cast<thread_db_thread *>(proc->threadPool()->initialThread());
1241    if (main_thread->tinfo_initialized)
1242       proc->initialThreadEventCreated = true;
1243
1244    if (!proc->initialThreadEventCreated) {
1245       pthrd_printf("Creating thread event for main thread\n");
1246
1247       if (!main_thread->threadHandle) {
1248          main_thread->threadHandle = new td_thrhandle_t;
1249          main_thread->threadHandle_alloced = true;
1250       }
1251
1252       int td_result = thread_db_process::p_td_ta_map_lwp2thr(proc->getThreadDBAgent(), main_thread->getLWP(), main_thread->threadHandle);
1253       if (td_result == TD_ERR && proc->getMemCache()->hasPendingAsync()) {
1254          pthrd_printf("async return from td_ta_map_lwp2thr while creating event for main thread\n");
1255          std::set<response::ptr> resps;
1256          proc->getMemCache()->getPendingAsyncs(resps);
1257          proc->handlerPool()->notifyOfPendingAsyncs(resps, ev);
1258          return Handler::ret_async;
1259       }
1260       else if (td_result == TD_ERR) {
1261          perr_printf("Error return from td_ta_map_lwp2thr while creating event for main thread\n");
1262          proc->dispatch_event = EventThreadDB::ptr();
1263          return ret_error;
1264       }
1265
1266       td_thrinfo_t tinfo;
1267       bzero(&tinfo, sizeof(td_thrinfo_t));
1268       async_ret_t result = proc->ll_fetchThreadInfo(main_thread->threadHandle, &tinfo);
1269       if (result == aret_async) {
1270          pthrd_printf("Async return during ll_fetchThreadInfo for main thread\n");
1271          std::set<response::ptr> resps;
1272          proc->getMemCache()->getPendingAsyncs(resps);
1273          proc->handlerPool()->notifyOfPendingAsyncs(resps, ev);
1274          return Handler::ret_async;         
1275       }
1276       if (result == aret_error) {
1277          pthrd_printf("Error return during ll_fetchThreadInfo for main thread\n");
1278          proc->dispatch_event = EventThreadDB::ptr();
1279          return Handler::ret_error;
1280       }
1281       if (tinfo.ti_tid) {
1282          new_thread_data_t *thrdata = (new_thread_data_t *) malloc(sizeof(new_thread_data_t));
1283          thrdata->thr_handle = main_thread->threadHandle;
1284          thrdata->thr_info = tinfo;
1285          thrdata->threadHandle_alloced = main_thread->threadHandle_alloced;
1286          
1287          EventNewUserThread::ptr new_ev = EventNewUserThread::ptr(new EventNewUserThread());
1288          new_ev->setProcess(proc->proc());
1289          new_ev->setThread(main_thread->thread());
1290          new_ev->setSyncType(Event::sync_process);
1291          new_ev->getInternalEvent()->thr = main_thread;
1292          new_ev->getInternalEvent()->lwp = main_thread->getLWP();
1293          new_ev->getInternalEvent()->raw_data = (void *) thrdata;
1294          proc->initialThreadEventCreated = true;
1295          int_ev->new_evs.insert(new_ev);
1296          pthrd_printf("Success creating event for main thread\n");
1297       }
1298       else {
1299          pthrd_printf("TID info for main thread not ready yet\n");
1300       }
1301    }
1302    pthrd_printf("Got %u events, adding as late events\n", (unsigned int) int_ev->new_evs.size());
1303    for (set<Event::ptr>::iterator i = int_ev->new_evs.begin(); i != int_ev->new_evs.end(); i++) {
1304       proc->handlerPool()->addLateEvent(*i);
1305    }
1306    proc->dispatch_event = EventThreadDB::ptr();
1307    return ret_success;
1308 }
1309
1310 void ThreadDBDispatchHandler::getEventTypesHandled(std::vector<EventType> &etypes)
1311 {
1312    etypes.push_back(EventType(EventType::None, EventType::ThreadDB));
1313 }
1314
1315 ThreadDBLibHandler::ThreadDBLibHandler() :
1316     Handler("thread_db Library Handler")
1317 {
1318 }
1319
1320 ThreadDBLibHandler::~ThreadDBLibHandler() 
1321 {
1322 }
1323
1324 Handler::handler_ret_t ThreadDBLibHandler::handleEvent(Event::ptr ev) {
1325    if (!thread_db_process::loadedThreadDBLibrary()) {
1326       pthrd_printf("Failed to load thread_db.  Not running handlers\n");
1327       return Handler::ret_success;
1328    }
1329
1330    EventLibrary::const_ptr libEv = ev->getEventLibrary();
1331    thread_db_process *proc = dynamic_cast<thread_db_process *>(ev->getProcess()->llproc());
1332    const set<Library::ptr> &addLibs = libEv->libsAdded();
1333
1334    set<Library::ptr>::iterator libIter;
1335    for( libIter = addLibs.begin(); libIter != addLibs.end(); ++libIter ) {
1336       if( ! proc->isSupportedThreadLib((*libIter)->getName()) )
1337          continue;
1338       
1339       pthrd_printf("Enabling thread_db support for pid %d\n",
1340                    proc->getPid());
1341       async_ret_t ret = proc->initThreadDB();
1342  
1343       if (ret == aret_error) {
1344          pthrd_printf("Failed to initialize thread_db for pid %d\n",
1345                       proc->getPid());
1346          return Handler::ret_error;
1347       }
1348       else if (ret == aret_success) {
1349          return Handler::ret_success;
1350       }
1351       else if (ret == aret_async) {
1352          std::set<response::ptr> resps;
1353          proc->getMemCache()->getPendingAsyncs(resps);
1354          proc->handlerPool()->notifyOfPendingAsyncs(resps, ev);
1355          return Handler::ret_async;
1356       }
1357    }
1358    
1359    return Handler::ret_success;
1360 }
1361
1362 int ThreadDBLibHandler::getPriority() const {
1363     return PostPlatformPriority;
1364 }
1365
1366 void ThreadDBLibHandler::getEventTypesHandled(vector<EventType> &etypes) {
1367     etypes.push_back(EventType(EventType::None, EventType::Library));
1368 }
1369
1370 ThreadDBCreateHandler::ThreadDBCreateHandler() :
1371     Handler("thread_db New Thread Handler")
1372 {
1373 }
1374
1375 ThreadDBCreateHandler::~ThreadDBCreateHandler() 
1376 {
1377 }
1378
1379 int ThreadDBCreateHandler::getPriority() const
1380 {
1381    //After dispatch handler, which runs at PostPlatformPriority
1382    return Handler::PostPlatformPriority + 1;
1383 }
1384
1385 Handler::handler_ret_t ThreadDBCreateHandler::handleEvent(Event::ptr ev) {
1386   pthrd_printf("ThreadDBCreateHandler::handleEvent\n");
1387    if (!thread_db_process::loadedThreadDBLibrary()) {
1388       pthrd_printf("Failed to load thread_db.  Not running handlers");
1389       return Handler::ret_success;
1390    }
1391
1392    EventNewUserThread::ptr threadEv = ev->getEventNewUserThread();
1393    thread_db_process *tdb_proc = dynamic_cast<thread_db_process *>(threadEv->getProcess()->llproc());
1394    thread_db_thread *tdb_thread = dynamic_cast<thread_db_thread *>(threadEv->getNewThread()->llthrd());
1395
1396    pthrd_printf("ThreadDBCreateHandler::handleEvent for %d/%d\n", tdb_proc->getPid(), tdb_thread->getLWP());
1397    if (threadEv->getInternalEvent()->needs_update) {
1398       pthrd_printf("Updating user thread data for %d/%d in thread_db create handler\n",
1399                    tdb_proc->getPid(), tdb_thread->getLWP());
1400       assert(tdb_proc);
1401       new_thread_data_t *thrdata = (new_thread_data_t *) threadEv->getInternalEvent()->raw_data;
1402       
1403       async_ret_t result = tdb_proc->initThreadWithHandle(thrdata->thr_handle, &thrdata->thr_info, NULL_LWP);
1404       if (result == aret_error) {
1405          pthrd_printf("ThreadDBCreateHandler returning error\n");
1406          return Handler::ret_error;
1407       }
1408       if (result == aret_async) {
1409          pthrd_printf("ThreadDBCreateHandler returning async\n");
1410          return Handler::ret_async;
1411       }
1412       if (thrdata->threadHandle_alloced) tdb_thread->threadHandle_alloced = true;
1413    }
1414    
1415    return Handler::ret_success;
1416 }
1417
1418 void ThreadDBCreateHandler::getEventTypesHandled(vector<EventType> &etypes) {
1419    etypes.push_back(EventType(EventType::Any, EventType::UserThreadCreate));
1420 }
1421
1422 ThreadDBDestroyHandler::ThreadDBDestroyHandler() :
1423    Handler("thread_db Destroy Handler")
1424 {
1425 }
1426
1427 ThreadDBDestroyHandler::~ThreadDBDestroyHandler()
1428 {
1429 }
1430
1431 int ThreadDBDestroyHandler::getPriority() const
1432 {
1433    //After dispatch handler, which runs at PostPlatformPriority
1434    return Handler::PostPlatformPriority + 1;
1435 }
1436
1437 Handler::handler_ret_t ThreadDBDestroyHandler::handleEvent(Event::ptr ev) {
1438    if (!thread_db_process::loadedThreadDBLibrary()) {
1439       pthrd_printf("Failed to load thread_db.  Not running handlers\n");
1440       return Handler::ret_success;
1441    }
1442    thread_db_process *proc = dynamic_cast<thread_db_process *>(ev->getProcess()->llproc());
1443    thread_db_thread *thrd = dynamic_cast<thread_db_thread *>(ev->getThread()->llthrd());
1444    pthrd_printf("Running ThreadDBDestroyHandler on %d/%d\n", proc->getPid(), thrd->getLWP());
1445    thrd->markDestroyed();
1446
1447    return Handler::ret_success;
1448 }
1449
1450 void ThreadDBDestroyHandler::getEventTypesHandled(vector<EventType> &etypes) {
1451     etypes.push_back(EventType(EventType::Any, EventType::UserThreadDestroy));
1452 }
1453
1454 thread_db_thread::thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l) :
1455    int_thread(p, t, l),
1456    threadHandle(NULL),
1457    destroyed(false),
1458    tinfo_initialized(false),
1459    thread_initialized(false),
1460    threadHandle_alloced(false),
1461    enabled_event_reporting(false)
1462 {
1463    memset(&tinfo, 0, sizeof(tinfo));
1464 }
1465
1466 thread_db_thread::~thread_db_thread() 
1467 {
1468    if (threadHandle_alloced)
1469       delete threadHandle;
1470 }
1471
1472 bool thread_db_thread::initThreadHandle() {
1473     if( NULL != threadHandle ) return true;
1474
1475     thread_db_process *lproc = dynamic_cast<thread_db_process *>(llproc());
1476     if( NULL == lproc->getThreadDBAgent() ) return false;
1477
1478     threadHandle = new td_thrhandle_t;
1479
1480     td_err_e errVal = thread_db_process::p_td_ta_map_lwp2thr(lproc->getThreadDBAgent(),
1481                                           lwp, threadHandle);
1482     if( TD_OK != errVal ) {
1483         perr_printf("Failed to map LWP %d to thread_db thread: %s(%d)\n",
1484                 lwp, tdErr2Str(errVal), errVal);
1485         setLastError(err_internal, "Failed to get thread_db thread handle");
1486         delete threadHandle;
1487         threadHandle = NULL;
1488         return false;
1489     }
1490     threadHandle_alloced = true;
1491
1492     return true;
1493 }
1494
1495 async_ret_t thread_db_process::getEventForThread(set<Event::ptr> &new_ev_set) {
1496    // These specific calls into thread_db can modify the memory of the process
1497    // and can introduce some race conditions if the platform allows memory reads
1498    // while some threads are running
1499    assert( threadPool()->allHandlerStopped() );
1500   
1501    // We need to save thread_db generated events because we need to use the
1502    // process-level event retrieval call to get thread creation events (at
1503    // least on some platforms).
1504
1505    bool local_async = false;
1506    td_event_msg_t evMsg;
1507    td_err_e msgErr = TD_OK;
1508    for (;;) {
1509       getMemCache()->markToken(token_getmsg);
1510       msgErr = p_td_ta_event_getmsg(threadAgent, &evMsg);
1511       if (msgErr != TD_OK) {
1512          if (getMemCache()->hasPendingAsync()) {
1513             pthrd_printf("Async return in getEventForThread from td_ta_event_getmsg\n");
1514             return aret_async;
1515          }
1516          else if (msgErr == TD_DBERR) {
1517             pthrd_printf("No more messages ready in thread_db\n");
1518             return aret_success;
1519          }
1520          else
1521             break;
1522       }
1523       Event::ptr newEvent = decodeThreadEvent(&evMsg, local_async);
1524       if (local_async) {
1525          pthrd_printf("Async return from decodeThreadEvent\n");
1526          return aret_async;
1527       }
1528       if (newEvent)
1529          new_ev_set.insert(newEvent);
1530       getMemCache()->condense();
1531    }
1532   
1533    if( msgErr != TD_NOMSG ) {
1534       perr_printf("Failed to retrieve thread event: %s(%d)\n",
1535                   tdErr2Str(msgErr), msgErr);
1536       return aret_error;
1537    }
1538   
1539    return aret_success;
1540 }
1541
1542 bool thread_db_process::setTrackThreads(bool b, std::set<std::pair<int_breakpoint *, Address> > &bps,
1543                                                  bool &add_bp)
1544 {
1545    if (b == track_threads) {
1546       pthrd_printf("User wants to %s thread_db on %d, which is already done.  Leaving in same state\n",
1547                    b ? "enable" : "disable", getPid());
1548       return true;
1549    }
1550    track_threads = b;
1551    
1552    std::map<Address, pair<int_breakpoint *, EventType> >::iterator i;
1553    for (i = addr2Event.begin(); i != addr2Event.end(); i++) {
1554       Address addr = i->first;
1555       int_breakpoint *bp = i->second.first;
1556       bps.insert(make_pair(bp, addr));
1557    }
1558
1559    add_bp = b;
1560    return true;
1561 }
1562
1563 bool thread_db_process::isTrackingThreads()
1564 {
1565    return track_threads;
1566 }
1567
1568 bool thread_db_process::refreshThreads()
1569 {
1570    EventThreadDB::ptr ev = EventThreadDB::ptr(new EventThreadDB());
1571    ev->setSyncType(Event::async);
1572    ev->setProcess(proc());
1573    ev->setThread(threadPool()->initialThread()->thread());
1574    mbox()->enqueue(ev);
1575    return true;
1576 }
1577
1578 int thread_db_process::threaddb_getPid()
1579 {
1580    return getPid();
1581 }
1582
1583 async_ret_t thread_db_thread::setEventReporting(bool on) {
1584     if( !initThreadHandle() ) return aret_error;
1585     if (enabled_event_reporting == on) return aret_success;
1586
1587     pthrd_printf("Enabled thread_db events for LWP %d\n", lwp);
1588     td_err_e errVal = thread_db_process::p_td_thr_event_enable(threadHandle, (on ? 1 : 0 ));
1589     if (errVal != TD_OK && llproc()->getMemCache()->hasPendingAsync()) {
1590        pthrd_printf("td_thr_event_enable returned async in setEventReporting\n");
1591        return aret_async;
1592     }
1593     enabled_event_reporting = on;
1594     if (errVal != TD_OK) {
1595        perr_printf("Failed to enable events for LWP %d: %s(%d)\n",
1596                    lwp, tdErr2Str(errVal), errVal);
1597        setLastError(err_internal, "Failed to enable thread_db events");
1598        return aret_error;
1599     }
1600
1601     return aret_success;
1602 }
1603
1604 bool thread_db_thread::fetchThreadInfo() {
1605    if (!thread_db_process::loadedThreadDBLibrary()) {
1606       perr_printf("Failed to load thread_db.  Not fetching thread data.");
1607       setLastError(err_unsupported, "thread_db.so not loaded.  User-level thread data unavailable.");
1608       return false;
1609    }
1610    if (!thread_initialized) {
1611       perr_printf("Attempt to read user thread info of %d/%d before user thread create\n",
1612                   llproc()->getPid(), getLWP());
1613       setLastError(err_nouserthrd, "Attempted to read user thread info, but user thread has not been created.");
1614       return false;
1615    }
1616    if (tinfo_initialized) {
1617       return true;
1618    }
1619    if( !initThreadHandle() ) return false;
1620
1621    pthrd_printf("Calling td_thr_get_info on %d/%d\n", llproc()->getPid(), getLWP());
1622    thread_db_process *tdb_proc = dynamic_cast<thread_db_process *>(llproc());
1623    async_ret_t result = tdb_proc->ll_fetchThreadInfo(threadHandle, &tinfo);
1624    if (result == aret_error) {
1625       pthrd_printf("Returning error in fetchThreadInfo due to ll_fetchThreadInfo\n");
1626       return false;
1627    }
1628    while (result == aret_async) {
1629       std::set<response::ptr> resps;
1630       llproc()->getMemCache()->getPendingAsyncs(resps);
1631       llproc()->waitForAsyncEvent(resps);
1632       result = tdb_proc->ll_fetchThreadInfo(threadHandle, &tinfo);
1633       if (result == aret_error) {
1634          pthrd_printf("Returning error in fetchThreadInfo due to ll_fetchThreadInfo\n");
1635          return false;
1636       }
1637    }
1638
1639    if( tinfo.ti_tid ) tinfo_initialized = true;
1640    return true;
1641 }
1642
1643 void thread_db_thread::markDestroyed() {
1644     destroyed = true;
1645 }
1646
1647 bool thread_db_thread::isDestroyed() {
1648     return destroyed;
1649 }
1650
1651 bool thread_db_thread::thrdb_getThreadArea(int, Dyninst::Address &)
1652 {
1653    assert(0); //Unsupported.  Currently only known to be needed on linux/x86_64
1654    return false;
1655 }
1656
1657 bool thread_db_thread::haveUserThreadInfo()
1658 {
1659    pthrd_printf("haveUserThreadInfo (%d/%d): %d\n", (llproc() ? llproc()->getPid() : 0), lwp, thread_initialized);
1660    return thread_initialized;
1661 }
1662
1663 bool thread_db_thread::getTID(Dyninst::THR_ID &tid)
1664 {
1665    if (!fetchThreadInfo()) {
1666       return false;
1667    }
1668 #if defined(os_freebsd)
1669    tid = (Dyninst::THR_ID) tinfo.ti_thread;
1670 #else
1671    tid = (Dyninst::THR_ID) tinfo.ti_tid;
1672 #endif
1673    return true;
1674 }
1675
1676 bool thread_db_thread::getStartFuncAddress(Dyninst::Address &addr)
1677 {
1678    if (!fetchThreadInfo()) {
1679       return false;
1680    }
1681    addr = (Dyninst::Address) tinfo.ti_startfunc;
1682    return true;
1683 }
1684
1685 bool thread_db_thread::getStackBase(Dyninst::Address &addr)
1686 {
1687    if (!fetchThreadInfo()) {
1688       return false;
1689    }
1690    addr = (Dyninst::Address) tinfo.ti_stkbase;
1691    return true;
1692 }
1693
1694 bool thread_db_thread::getStackSize(unsigned long &size)
1695 {
1696    if (!fetchThreadInfo()) {
1697       return false;
1698    }
1699    size = (unsigned long) tinfo.ti_stksize;
1700    return true;
1701 }
1702
1703 bool thread_db_thread::getTLSPtr(Dyninst::Address &addr)
1704 {
1705    if (!fetchThreadInfo()) {
1706       return false;
1707    }
1708    addr = (Dyninst::Address) tinfo.ti_tls;
1709    return true;
1710 }
1711
1712 #else
1713
1714 //Empty place holder functions in-case we're built on a machine without libthread_db.so
1715
1716 thread_db_process::thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f) : 
1717    int_threadTracking(p, e, a, envp, f)
1718 {
1719   cerr << "Thread DB process constructor" << endl;
1720 }
1721
1722 thread_db_process::thread_db_process(Dyninst::PID pid_, int_process *p) :
1723    int_threadTracking(pid_, p)
1724 {
1725 }
1726
1727 thread_db_process::~thread_db_process()
1728 {
1729 }
1730
1731 bool thread_db_process::decodeTdbLWPExit(EventLWPDestroy::ptr)
1732 {
1733    return false;
1734 }
1735
1736 async_ret_t thread_db_process::decodeTdbBreakpoint(EventBreakpoint::ptr)
1737 {
1738    return aret_error;
1739 }
1740
1741 void thread_db_process::addThreadDBHandlers(HandlerPool *)
1742 {
1743 }
1744
1745 thread_db_thread::thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l) : 
1746    int_thread(p, t, l)
1747 {
1748 }
1749
1750 thread_db_thread::~thread_db_thread()
1751 {
1752 }
1753
1754 bool thread_db_thread::thrdb_getThreadArea(int, Dyninst::Address &)
1755 {
1756    assert(0); //Should not be called if there's no thread_db
1757    return false;
1758 }
1759
1760 bool thread_db_thread::haveUserThreadInfo()
1761 {
1762    return false;
1763 }
1764
1765 bool thread_db_thread::getTID(Dyninst::THR_ID &)
1766 {
1767    perr_printf("Error. thread_db not installed on this platform.\n");
1768    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1769    return false;
1770 }
1771
1772 bool thread_db_thread::getStartFuncAddress(Dyninst::Address &)
1773 {
1774    perr_printf("Error. thread_db not installed on this platform.\n");
1775    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1776    return false;
1777 }
1778
1779 bool thread_db_thread::getStackBase(Dyninst::Address &)
1780 {
1781    perr_printf("Error. thread_db not installed on this platform.\n");
1782    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1783    return false;
1784 }
1785
1786 bool thread_db_thread::getStackSize(unsigned long &)
1787 {
1788    perr_printf("Error. thread_db not installed on this platform.\n");
1789    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1790    return false;
1791 }
1792
1793 bool thread_db_thread::getTLSPtr(Dyninst::Address &)
1794 {
1795    perr_printf("Error. thread_db not installed on this platform.\n");
1796    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1797    return false;
1798 }
1799
1800 bool thread_db_thread::plat_convertToSystemRegs(const int_registerPool &,
1801                                                 unsigned char *, bool)
1802 {
1803    return true;
1804 }
1805
1806 async_ret_t thread_db_process::post_attach(bool, set<response::ptr> &) {
1807    return aret_success;
1808 }
1809
1810 async_ret_t thread_db_process::post_create(std::set<response::ptr> &) {
1811    return aret_success;
1812 }
1813
1814 bool thread_db_process::plat_getLWPInfo(lwpid_t, void *) {
1815    return false;
1816 }
1817
1818 const char *thread_db_process::getThreadLibName(const char *)
1819 {
1820    return "";
1821 }
1822
1823 void thread_db_process::freeThreadDBAgent() {
1824 }
1825
1826 async_ret_t thread_db_process::getEventForThread(set<Event::ptr> &) 
1827 {
1828    return aret_error;
1829 }
1830
1831 bool thread_db_process::isSupportedThreadLib(string) {
1832    return false;
1833 }
1834
1835 bool thread_db_process::plat_supportThreadEvents() {
1836    return false;
1837 }
1838
1839 bool thread_db_process::setTrackThreads(bool, std::set<std::pair<int_breakpoint *, Address> > &,
1840                                                  bool &)
1841 {
1842    perr_printf("Error. thread_db not installed on this platform.\n");
1843    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1844    return false;
1845 }
1846
1847 bool thread_db_process::isTrackingThreads()
1848 {
1849    perr_printf("Error. thread_db not installed on this platform.\n");
1850    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1851    return false;
1852 }
1853
1854 ThreadTracking *thread_db_process::threaddb_getThreadTracking() 
1855 {
1856    perr_printf("Error. thread_db not installed on this platform.\n");
1857    setLastError(err_unsupported, "Cannot perform thread operations without thread_db\n");
1858    return NULL;
1859 }
1860
1861 #endif