thread_db.c revision 177490
1132332Smarcel/* 2132332Smarcel * Copyright (c) 2004 David Xu <davidxu@freebsd.org> 3132332Smarcel * All rights reserved. 4132332Smarcel * 5132332Smarcel * Redistribution and use in source and binary forms, with or without 6132332Smarcel * modification, are permitted provided that the following conditions 7132332Smarcel * are met: 8132332Smarcel * 1. Redistributions of source code must retain the above copyright 9132332Smarcel * notice, this list of conditions and the following disclaimer. 10132332Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11132332Smarcel * notice, this list of conditions and the following disclaimer in the 12132332Smarcel * documentation and/or other materials provided with the distribution. 13132332Smarcel * 14132332Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132332Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132332Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132332Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132332Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132332Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132332Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132332Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22132332Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132332Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132332Smarcel * SUCH DAMAGE. 25132332Smarcel */ 26132332Smarcel 27132332Smarcel#include <sys/cdefs.h> 28132332Smarcel__FBSDID("$FreeBSD: head/lib/libthread_db/thread_db.c 177490 2008-03-22 05:40:44Z davidxu $"); 29132332Smarcel 30132332Smarcel#include <proc_service.h> 31132332Smarcel#include <stddef.h> 32132332Smarcel#include <thread_db.h> 33132332Smarcel#include <unistd.h> 34177490Sdavidxu#include <sys/cdefs.h> 35177490Sdavidxu#include <sys/linker_set.h> 36132332Smarcel 37132332Smarcel#include "thread_db_int.h" 38132332Smarcel 39132332Smarcelstruct td_thragent 40132332Smarcel{ 41132332Smarcel TD_THRAGENT_FIELDS; 42132332Smarcel}; 43132332Smarcel 44132332Smarcelstatic TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); 45132332Smarcel 46177490SdavidxuSET_DECLARE(__ta_ops, struct ta_ops); 47132332Smarcel 48132332Smarceltd_err_e 49132332Smarceltd_init(void) 50132332Smarcel{ 51132332Smarcel td_err_e ret, tmp; 52177490Sdavidxu struct ta_ops *ops_p, **ops_pp; 53132332Smarcel size_t i; 54132332Smarcel 55132332Smarcel ret = 0; 56177490Sdavidxu SET_FOREACH(ops_pp, __ta_ops) { 57177490Sdavidxu ops_p = *ops_pp; 58177490Sdavidxu if (ops_p->to_init != NULL) { 59177490Sdavidxu tmp = ops_p->to_init(); 60132332Smarcel if (tmp != TD_OK) 61132332Smarcel ret = tmp; 62132332Smarcel } 63132332Smarcel } 64132332Smarcel return (ret); 65132332Smarcel} 66132332Smarcel 67132332Smarceltd_err_e 68132332Smarceltd_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 69132332Smarcel{ 70132332Smarcel return (ta->ta_ops->to_ta_clear_event(ta, events)); 71132332Smarcel} 72132332Smarcel 73132332Smarceltd_err_e 74132332Smarceltd_ta_delete(td_thragent_t *ta) 75132332Smarcel{ 76132332Smarcel TAILQ_REMOVE(&proclist, ta, ta_next); 77132332Smarcel return (ta->ta_ops->to_ta_delete(ta)); 78132332Smarcel} 79132332Smarcel 80132332Smarceltd_err_e 81132332Smarceltd_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 82132332Smarcel{ 83132332Smarcel return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); 84132332Smarcel} 85132332Smarcel 86132332Smarceltd_err_e 87132332Smarceltd_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 88132332Smarcel{ 89132332Smarcel return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); 90132332Smarcel} 91132332Smarcel 92132332Smarceltd_err_e 93132332Smarceltd_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 94132332Smarcel{ 95132332Smarcel return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); 96132332Smarcel} 97132332Smarcel 98132332Smarceltd_err_e 99132332Smarceltd_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) 100132332Smarcel{ 101132332Smarcel return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); 102132332Smarcel} 103132332Smarcel 104132332Smarceltd_err_e 105132332Smarceltd_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 106132332Smarcel{ 107132332Smarcel size_t i; 108177490Sdavidxu struct ta_ops *ops_p, **ops_pp; 109132332Smarcel 110177490Sdavidxu SET_FOREACH(ops_pp, __ta_ops) { 111177490Sdavidxu ops_p = *ops_pp; 112177490Sdavidxu if (ops_p->to_ta_new(ph, pta) == TD_OK) { 113132332Smarcel TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); 114177490Sdavidxu (*pta)->ta_ops = ops_p; 115132332Smarcel return (TD_OK); 116132332Smarcel } 117132332Smarcel } 118132332Smarcel return (TD_NOLIBTHREAD); 119132332Smarcel} 120132332Smarcel 121132332Smarceltd_err_e 122132332Smarceltd_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 123132332Smarcel{ 124132332Smarcel return (ta->ta_ops->to_ta_set_event(ta, events)); 125132332Smarcel} 126132332Smarcel 127132332Smarceltd_err_e 128132332Smarceltd_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 129132332Smarcel void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, 130132332Smarcel unsigned int ti_user_flags) 131132332Smarcel{ 132132332Smarcel return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, 133132332Smarcel ti_pri, ti_sigmask_p, ti_user_flags)); 134132332Smarcel} 135132332Smarcel 136132332Smarceltd_err_e 137132332Smarceltd_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, 138132332Smarcel void *cbdata_p) 139132332Smarcel{ 140132332Smarcel return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); 141132332Smarcel} 142132332Smarcel 143132332Smarceltd_err_e 144132332Smarceltd_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) 145132332Smarcel{ 146132332Smarcel const td_thragent_t *ta = th->th_ta; 147132332Smarcel return (ta->ta_ops->to_thr_clear_event(th, events)); 148132332Smarcel} 149132332Smarcel 150132332Smarceltd_err_e 151132332Smarceltd_thr_dbresume(const td_thrhandle_t *th) 152132332Smarcel{ 153132332Smarcel const td_thragent_t *ta = th->th_ta; 154132332Smarcel return (ta->ta_ops->to_thr_dbresume(th)); 155132332Smarcel} 156132332Smarcel 157132332Smarceltd_err_e 158132332Smarceltd_thr_dbsuspend(const td_thrhandle_t *th) 159132332Smarcel{ 160132332Smarcel const td_thragent_t *ta = th->th_ta; 161132332Smarcel return (ta->ta_ops->to_thr_dbsuspend(th)); 162132332Smarcel} 163132332Smarcel 164132332Smarceltd_err_e 165132332Smarceltd_thr_event_enable(const td_thrhandle_t *th, int en) 166132332Smarcel{ 167132332Smarcel const td_thragent_t *ta = th->th_ta; 168132332Smarcel return (ta->ta_ops->to_thr_event_enable(th, en)); 169132332Smarcel} 170132332Smarcel 171132332Smarceltd_err_e 172132332Smarceltd_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 173132332Smarcel{ 174132332Smarcel const td_thragent_t *ta = th->th_ta; 175132332Smarcel return (ta->ta_ops->to_thr_event_getmsg(th, msg)); 176132332Smarcel} 177132332Smarcel 178132332Smarceltd_err_e 179132332Smarceltd_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 180132332Smarcel{ 181132332Smarcel const td_thragent_t *ta = th->th_ta; 182132332Smarcel return (ta->ta_ops->to_thr_get_info(th, info)); 183132332Smarcel} 184132332Smarcel 185146818Sdfr#ifdef __i386__ 186132332Smarceltd_err_e 187146818Sdfrtd_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 188146818Sdfr{ 189146818Sdfr const td_thragent_t *ta = th->th_ta; 190146818Sdfr return (ta->ta_ops->to_thr_getxmmregs(th, fxsave)); 191146818Sdfr} 192146818Sdfr#endif 193146818Sdfr 194146818Sdfr 195146818Sdfrtd_err_e 196132332Smarceltd_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) 197132332Smarcel{ 198132332Smarcel const td_thragent_t *ta = th->th_ta; 199132332Smarcel return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); 200132332Smarcel} 201132332Smarcel 202132332Smarceltd_err_e 203132332Smarceltd_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 204132332Smarcel{ 205132332Smarcel const td_thragent_t *ta = th->th_ta; 206132332Smarcel return (ta->ta_ops->to_thr_getgregs(th, gregs)); 207132332Smarcel} 208132332Smarcel 209132332Smarceltd_err_e 210132332Smarceltd_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) 211132332Smarcel{ 212132332Smarcel const td_thragent_t *ta = th->th_ta; 213132332Smarcel return (ta->ta_ops->to_thr_set_event(th, events)); 214132332Smarcel} 215132332Smarcel 216146818Sdfr#ifdef __i386__ 217132332Smarceltd_err_e 218146818Sdfrtd_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 219146818Sdfr{ 220146818Sdfr const td_thragent_t *ta = th->th_ta; 221146818Sdfr return (ta->ta_ops->to_thr_setxmmregs(th, fxsave)); 222146818Sdfr} 223146818Sdfr#endif 224146818Sdfr 225146818Sdfrtd_err_e 226132332Smarceltd_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 227132332Smarcel{ 228132332Smarcel const td_thragent_t *ta = th->th_ta; 229132332Smarcel return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); 230132332Smarcel} 231132332Smarcel 232132332Smarceltd_err_e 233132332Smarceltd_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 234132332Smarcel{ 235132332Smarcel const td_thragent_t *ta = th->th_ta; 236132332Smarcel return (ta->ta_ops->to_thr_setgregs(th, gregs)); 237132332Smarcel} 238132332Smarcel 239132332Smarceltd_err_e 240132332Smarceltd_thr_validate(const td_thrhandle_t *th) 241132332Smarcel{ 242132332Smarcel const td_thragent_t *ta = th->th_ta; 243132332Smarcel return (ta->ta_ops->to_thr_validate(th)); 244132332Smarcel} 245132332Smarcel 246133342Sdavidxutd_err_e 247133342Sdavidxutd_thr_tls_get_addr(const td_thrhandle_t *th, void *linkmap, size_t offset, 248133342Sdavidxu void **address) 249133342Sdavidxu{ 250133342Sdavidxu const td_thragent_t *ta = th->th_ta; 251133342Sdavidxu return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address)); 252133342Sdavidxu} 253133342Sdavidxu 254132332Smarcel/* FreeBSD specific extensions. */ 255132332Smarcel 256132332Smarceltd_err_e 257132332Smarceltd_thr_sstep(const td_thrhandle_t *th, int step) 258132332Smarcel{ 259132332Smarcel const td_thragent_t *ta = th->th_ta; 260132332Smarcel return (ta->ta_ops->to_thr_sstep(th, step)); 261132332Smarcel} 262