2 * Copyright (c) 1996-2009 Barton P. Miller
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.
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.
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.
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.
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
32 #include <proc_service.h>
33 #include <thread_db.h>
39 #include "common/h/dthread.h"
40 #include "int_thread_db.h"
43 * proc_service interface implementation, needed by libthread_db
46 ps_err_e ps_pglobal_lookup(struct ps_prochandle *handle, const char *objName,
47 const char *symName, psaddr_t *symbolAddr)
49 return handle->thread_db_proc->getSymbolAddr(objName, symName, symbolAddr);
52 ps_err_e ps_pread(struct ps_prochandle *handle, psaddr_t remote, void *local, size_t size) {
53 if( !handle->thread_db_proc->plat_readProcMem(local, (Dyninst::Address)remote, size) )
59 ps_err_e ps_pwrite(struct ps_prochandle *handle, psaddr_t remote, const void *local, size_t size) {
60 if( !handle->thread_db_proc->plat_writeProcMem(const_cast<void *>(local), (Dyninst::Address)remote, size) )
66 ps_err_e ps_linfo(struct ps_prochandle *handle, lwpid_t lwp, void *lwpInfo) {
67 if( !handle->thread_db_proc->plat_getLWPInfo(lwp, lwpInfo) )
73 ps_err_e ps_lstop(struct ps_prochandle *handle, lwpid_t lwp) {
74 if( !handle->thread_db_proc->plat_stopThread(lwp) ) {
81 ps_err_e ps_lcontinue(struct ps_prochandle *handle, lwpid_t lwp) {
82 if( !handle->thread_db_proc->plat_contThread(lwp) ) {
89 void ps_plog(const char *format, ...) {
90 if( !dyninst_debug_proccontrol ) return;
91 if( NULL == format ) return;
95 vfprintf(pctrl_err_out, format, va);
99 #define NA_IMPLEMENTED "This function is not implemented"
101 ps_err_e ps_lgetfpregs(struct ps_prochandle *, lwpid_t, prfpregset_t *) {
102 assert(!NA_IMPLEMENTED);
106 ps_err_e ps_lgetregs(struct ps_prochandle *, lwpid_t, prgregset_t) {
107 assert(!NA_IMPLEMENTED);
111 ps_err_e ps_lsetfpregs(struct ps_prochandle *, lwpid_t, const prfpregset_t *) {
112 assert(!NA_IMPLEMENTED);
116 ps_err_e ps_lsetregs(struct ps_prochandle *, lwpid_t, const prgregset_t) {
117 assert(!NA_IMPLEMENTED);
121 ps_err_e ps_lgetxmmregs (struct ps_prochandle *, lwpid_t, char *) {
122 assert(!NA_IMPLEMENTED);
126 ps_err_e ps_lsetxmmregs (struct ps_prochandle *, lwpid_t, const char *) {
127 assert(!NA_IMPLEMENTED);
131 ps_err_e ps_pcontinue(struct ps_prochandle *) {
132 assert(!NA_IMPLEMENTED);
136 ps_err_e ps_pdmodel(struct ps_prochandle *, int *) {
137 assert(!NA_IMPLEMENTED);
141 ps_err_e ps_pstop(struct ps_prochandle *) {
142 assert(!NA_IMPLEMENTED);
146 #ifndef CASE_RETURN_STR
147 #define CASE_RETURN_STR(x) case x: return #x;
150 static const char *tdErr2Str(td_err_e errVal) {
152 CASE_RETURN_STR(TD_ERR)
153 CASE_RETURN_STR(TD_OK)
154 CASE_RETURN_STR(TD_BADKEY)
155 CASE_RETURN_STR(TD_BADPH)
156 CASE_RETURN_STR(TD_BADSH)
157 CASE_RETURN_STR(TD_BADTA)
158 CASE_RETURN_STR(TD_BADTH)
159 CASE_RETURN_STR(TD_DBERR)
160 CASE_RETURN_STR(TD_MALLOC)
161 CASE_RETURN_STR(TD_NOAPLIC)
162 CASE_RETURN_STR(TD_NOCAPAB)
163 CASE_RETURN_STR(TD_NOEVENT)
164 CASE_RETURN_STR(TD_NOFPREGS)
165 CASE_RETURN_STR(TD_NOLIBTHREAD)
166 CASE_RETURN_STR(TD_NOLWP)
167 CASE_RETURN_STR(TD_NOMSG)
168 CASE_RETURN_STR(TD_NOSV)
169 CASE_RETURN_STR(TD_NOTHR)
170 CASE_RETURN_STR(TD_NOTSD)
171 CASE_RETURN_STR(TD_NOXREGS)
172 CASE_RETURN_STR(TD_PARTIALREG)
179 Event::ptr decodeThreadEvent(td_event_msg_t *eventMsg) {
180 td_thrinfo_t threadInfo;
182 if( TD_OK != (errVal = td_thr_get_info(eventMsg->th_p, &threadInfo)) ) {
183 perr_printf("Failed to get thread event info from event msg: %s(%d)\n",
184 tdErr2Str(errVal), errVal);
188 switch(eventMsg->event) {
190 return Event::ptr(new EventNewThread((Dyninst::LWP)threadInfo.ti_lid));
193 return Event::ptr(new EventThreadDestroy(EventType::Pre));
196 pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
203 volatile bool thread_db_process::thread_db_initialized = false;
205 thread_db_process::thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a)
206 : sysv_process(p, e, a), threadAgent(NULL)
208 self = new ps_prochandle();
209 self->thread_db_proc = this;
213 thread_db_process::thread_db_process(Dyninst::PID pid_, int_process *p)
214 : sysv_process(pid_, p), threadAgent(NULL)
216 self = new ps_prochandle();
217 self->thread_db_proc = this;
221 thread_db_process::~thread_db_process()
225 if( thread_db_initialized && threadAgent ) {
226 td_err_e errVal = td_ta_delete(threadAgent);
227 if( TD_OK != errVal ) {
228 perr_printf("Failed to delete thread agent: %s(%d)\n",
229 tdErr2Str(errVal), errVal);
231 assert( TD_OK == errVal && "Failed to delete thread agent" );
234 // Free the breakpoints allocated for events
235 map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator brkptIter;
236 for(brkptIter = addr2Event.begin(); brkptIter != addr2Event.end(); ++brkptIter) {
237 delete brkptIter->second.first;
240 // Close all the symbol readers used
241 map<string, pair<LoadedLib *, SymReader *> >::iterator symReaderIter;
242 for(symReaderIter = symReaders.begin(); symReaderIter != symReaders.end();
245 symreader_factory->closeSymbolReader(symReaderIter->second.second);
249 bool thread_db_process::initThreadDB() {
250 // Q: Why isn't this in the constructor?
251 // A: This function depends on the corresponding thread library being loaded
252 // and this event occurs some time after process creation.
254 // Make sure thread_db is initialized
255 if( !thread_db_initialized ) {
257 if( TD_OK != (errVal = td_init()) ) {
258 perr_printf("Failed to initialize libthread_db: %s(%d)\n",
259 tdErr2Str(errVal), errVal);
260 setLastError(err_internal, "libthread_db initialization failed");
263 pthrd_printf("Sucessfully initialized thread_db\n");
264 thread_db_initialized = true;
267 // Create the thread agent
268 td_err_e errVal = td_ta_new(self, &threadAgent);
273 pthrd_printf("Debuggee isn't multithreaded at this point, libthread_db not enabled\n");
276 perr_printf("Failed to create thread agent: %s(%d)\n",
277 tdErr2Str(errVal), errVal);
278 setLastError(err_internal, "Failed to create libthread_db agent");
283 td_thr_events_t eventMask;
284 td_event_fillset(&eventMask);
286 errVal = td_ta_set_event(threadAgent, &eventMask);
287 if( TD_OK != errVal ) {
288 perr_printf("Failed to enable events: %s(%d)\n",
289 tdErr2Str(errVal), errVal);
290 setLastError(err_internal, "Failed to enable libthread_db events");
294 // Determine the addresses for all events
295 td_event_e allEvents[] = { TD_CATCHSIG, TD_CONCURRENCY, TD_CREATE,
296 TD_DEATH, TD_IDLE, TD_LOCK_TRY, TD_PREEMPT, TD_PRI_INHERIT,
297 TD_READY, TD_REAP, TD_SLEEP, TD_SWITCHFROM, TD_SWITCHTO,
300 for(unsigned i = 0; i < (sizeof(allEvents)/sizeof(td_event_e)); ++i) {
301 td_notify_t notifyResult;
302 errVal = td_ta_event_addr(threadAgent, allEvents[i], ¬ifyResult);
304 // This indicates that the event isn't supported
305 if( TD_OK != errVal ) continue;
307 assert( notifyResult.type == NOTIFY_BPT && "Untested notify type" );
310 switch(allEvents[i]) {
312 newEvent = EventType(EventType::Post, EventType::ThreadCreate);
313 pthrd_printf("Installing breakpoint for thread creation events\n");
316 newEvent = EventType(EventType::Post, EventType::ThreadDestroy);
317 pthrd_printf("Installing breakpoint for thread destroy events\n");
320 pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
324 int_breakpoint *newEventBrkpt = new int_breakpoint(Breakpoint::ptr());
325 if( !addBreakpoint((Dyninst::Address)notifyResult.u.bptaddr,
328 perr_printf("Failed to install new event breakpoint\n");
329 setLastError(err_internal, "Failed to install new thread_db event breakpoint");
330 delete newEventBrkpt;
335 pair<map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator, bool> insertIter;
336 insertIter = addr2Event.insert(make_pair((Dyninst::Address)notifyResult.u.bptaddr,
337 make_pair(newEventBrkpt, newEvent)));
339 assert( insertIter.second && "event breakpoint address not unique" );
345 bool thread_db_process::getEventsAtAddr(Dyninst::Address addr,
346 thread_db_thread *eventThread, vector<Event::ptr> &threadEvents)
348 unsigned oldSize = threadEvents.size();
350 // Determine what type event occurs at the specified address
351 map<Dyninst::Address, pair<int_breakpoint *, EventType> >::iterator addrIter;
352 addrIter = addr2Event.find(addr);
353 if( addrIter == addr2Event.end() ) return false;
355 switch(addrIter->second.second.code()) {
356 case EventType::ThreadCreate:
358 pthrd_printf("Address 0x%lx corresponds to a thread create event.\n",
360 // Need to ask via the thread_db agent for creation events. This
361 // could result in getting information about other events. All of
362 // these events need to be handled.
363 td_event_msg_t threadMsg;
364 td_err_e msgErr = TD_OK;
365 while(msgErr == TD_OK) {
366 msgErr = td_ta_event_getmsg(threadAgent, &threadMsg);
367 if( msgErr == TD_OK ) {
368 Event::ptr threadEvent = decodeThreadEvent(&threadMsg);
370 threadEvents.push_back(threadEvent);
375 if( msgErr != TD_NOMSG ) {
376 perr_printf("Failed to retrieve thread event: %s(%d)\n",
377 tdErr2Str(msgErr), msgErr);
381 case EventType::ThreadDestroy:
383 pthrd_printf("Address 0x%lx corresponds to a thread destroy event.\n",
386 Event::ptr threadEvent = eventThread->getThreadEvent();
388 threadEvents.push_back(threadEvent);
390 perr_printf("Failed to retrieve thread event for LWP %d\n",
391 eventThread->getLWP());
396 pthrd_printf("Unimplemented libthread_db event encountered. Skipping for now.\n");
400 return oldSize != threadEvents.size();
403 td_thragent_t *thread_db_process::getThreadDBAgent() {
407 ps_err_e thread_db_process::getSymbolAddr(const char *objName, const char *symName,
408 psaddr_t *symbolAddr)
410 SymReader *objSymReader = NULL;
411 LoadedLib *lib = NULL;
413 // For static executables, we need to search the executable instead of the
416 // For static executables, breakpoint_addr isn't set
417 if( !breakpoint_addr ) {
418 lib = translator->getExecutable();
420 perr_printf("Failed to get loaded version of executable\n");
421 setLastError(err_internal, "Failed to get loaded version of executable");
425 map<string, pair<LoadedLib *, SymReader *> >::iterator symReaderIter;
426 symReaderIter = symReaders.find(lib->getName());
427 if( symReaderIter == symReaders.end() ) {
428 objSymReader = symreader_factory->openSymbolReader(lib->getName());
429 if( NULL == objSymReader ) {
430 perr_printf("Failed to open symbol reader for %s\n",
431 lib->getName().c_str());
432 setLastError(err_internal, "Failed to open executable for symbol reading");
435 symReaders.insert(make_pair(lib->getName(), make_pair(lib, objSymReader)));
437 objSymReader = symReaderIter->second.second;
440 // FreeBSD implementation doesn't set objName
442 if( NULL == objName ) {
443 objNameStr = getThreadLibName(symName);
445 objNameStr = objName;
448 map<string, pair<LoadedLib *, SymReader *> >::iterator symReaderIter;
449 symReaderIter = symReaders.find(objNameStr);
450 if( symReaderIter == symReaders.end() ) {
451 vector<LoadedLib *> libs;
452 if( !translator->getLibs(libs) ) {
453 perr_printf("Failed to retrieve loaded libraries\n");
454 setLastError(err_internal, "Failed to retrieve loaded libraries");
458 vector<LoadedLib *>::iterator loadedLibIter;
459 for(loadedLibIter = libs.begin(); loadedLibIter != libs.end();
462 if( (*loadedLibIter)->getName().find(objNameStr) != string::npos ) {
463 lib = (*loadedLibIter);
469 perr_printf("Failed to find loaded library for %s\n", objNameStr.c_str());
470 setLastError(err_internal, "Failed to find loaded library");
474 objSymReader = symreader_factory->openSymbolReader(lib->getName());
476 if( NULL == objSymReader ) {
477 perr_printf("Failed to open symbol reader for %s\n", objNameStr.c_str());
478 setLastError(err_internal, "Failed to open library for symbol reading");
482 symReaders.insert(make_pair(objNameStr, make_pair(lib, objSymReader)));
484 lib = symReaderIter->second.first;
485 objSymReader = symReaderIter->second.second;
489 Symbol_t lookupSym = objSymReader->getSymbolByName(string(symName));
491 if( !objSymReader->isValidSymbol(lookupSym) ) {
495 *symbolAddr = (psaddr_t)lib->offToAddress(
496 objSymReader->getSymbolOffset(lookupSym));
501 bool thread_db_process::post_create() {
502 if( !int_process::post_create() ) return false;
504 return initThreadDB();
507 bool thread_db_process::post_attach() {
508 if( !int_process::post_attach() ) return false;
510 return initThreadDB();
513 void thread_db_process::addThreadDBHandlers(HandlerPool *hpool) {
514 static bool initialized = false;
515 static ThreadDBLibHandler *libHandler = NULL;
516 static ThreadDBHandleNewThr *thrHandler = NULL;
518 libHandler = new ThreadDBLibHandler();
519 thrHandler = new ThreadDBHandleNewThr();
522 hpool->addHandler(libHandler);
523 hpool->addHandler(thrHandler);
526 ThreadDBLibHandler::ThreadDBLibHandler() :
527 Handler("thread_db Library Handler")
531 ThreadDBLibHandler::~ThreadDBLibHandler()
535 bool ThreadDBLibHandler::handleEvent(Event::ptr ev) {
536 EventLibrary::const_ptr libEv = ev->getEventLibrary();
538 thread_db_process *proc = static_cast<thread_db_process *>(ev->getProcess()->llproc());
540 const set<Library::ptr> &addLibs = libEv->libsAdded();
542 set<Library::ptr>::iterator libIter;
543 for( libIter = addLibs.begin(); libIter != addLibs.end(); ++libIter ) {
544 if( proc->isSupportedThreadLib((*libIter)->getName()) ) {
545 pthrd_printf("Enabling thread_db support for pid %d\n",
547 if( !proc->initThreadDB() ) {
548 pthrd_printf("Failed to initialize thread_db for pid %d\n",
559 int ThreadDBLibHandler::getPriority() const {
560 return PostPlatformPriority;
563 void ThreadDBLibHandler::getEventTypesHandled(vector<EventType> &etypes) {
564 etypes.push_back(EventType(EventType::None, EventType::Library));
567 ThreadDBHandleNewThr::ThreadDBHandleNewThr() :
568 Handler("thread_db New Thread Handler")
572 ThreadDBHandleNewThr::~ThreadDBHandleNewThr()
576 bool ThreadDBHandleNewThr::handleEvent(Event::ptr ev) {
577 EventNewThread::const_ptr threadEv = ev->getEventNewThread();
579 thread_db_thread *thread = static_cast<thread_db_thread *>(threadEv->getNewThread()->llthrd());
581 assert(thread && "Thread was not initialized before calling this handler");
583 // Explicitly ignore errors here
584 thread->setEventReporting(true);
589 int ThreadDBHandleNewThr::getPriority() const {
590 return PostPlatformPriority;
593 void ThreadDBHandleNewThr::getEventTypesHandled(vector<EventType> &etypes) {
594 etypes.push_back(EventType(EventType::None, EventType::ThreadCreate));
597 thread_db_thread::thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l)
598 : int_thread(p, t, l)
602 thread_db_thread::~thread_db_thread()
606 Event::ptr thread_db_thread::getThreadEvent() {
607 thread_db_process *lproc = static_cast<thread_db_process *>(proc_);
608 td_thrhandle_t threadHandle;
610 // Get the thread handle
611 td_err_e errVal = td_ta_map_lwp2thr(lproc->getThreadDBAgent(),
613 if( TD_OK != errVal ) {
614 perr_printf("Failed to map lwp to thread_db thread: %s(%d)\n",
615 tdErr2Str(errVal), errVal);
616 setLastError(err_internal, "Failed to get thread_db thread handle");
620 td_event_msg_t eventMsg;
622 errVal = td_thr_event_getmsg(&threadHandle, &eventMsg);
624 if( TD_NOMSG == errVal ) {
625 pthrd_printf("No message available for LWP %d via thread_db\n", lwp);
629 if( TD_OK != errVal ) {
630 perr_printf("Failed to get thread event message: %s(%d)\n",
631 tdErr2Str(errVal), errVal);
632 setLastError(err_internal, "Failed to get thread event message");
636 return decodeThreadEvent(&eventMsg);
639 bool thread_db_thread::setEventReporting(bool on) {
640 thread_db_process *lproc = static_cast<thread_db_process *>(proc_);
641 td_thrhandle_t threadHandle;
643 // Get the thread handle
644 td_err_e errVal = td_ta_map_lwp2thr(lproc->getThreadDBAgent(),
646 if( TD_OK != errVal ) {
647 perr_printf("Failed to map lwp to thread_db thread: %s(%d)\n",
648 tdErr2Str(errVal), errVal);
649 setLastError(err_internal, "Failed to get thread_db thread handle");
653 errVal = td_thr_event_enable(&threadHandle, (on ? 1 : 0 ));
655 if( TD_OK != errVal ) {
656 perr_printf("Failed to enable events for LWP %d: %s(%d)\n",
657 lwp, tdErr2Str(errVal), errVal);
658 setLastError(err_internal, "Failed to enable thread_db events");
662 pthrd_printf("Enabled thread_db events for LWP %d\n", lwp);