thread_db.c revision 132332
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 132332 2004-07-18 04:17:15Z marcel $"); 29132332Smarcel 30132332Smarcel#include <proc_service.h> 31132332Smarcel#include <stddef.h> 32132332Smarcel#include <thread_db.h> 33132332Smarcel#include <unistd.h> 34132332Smarcel 35132332Smarcel#include "thread_db_int.h" 36132332Smarcel 37132332Smarcelstruct td_thragent 38132332Smarcel{ 39132332Smarcel TD_THRAGENT_FIELDS; 40132332Smarcel}; 41132332Smarcel 42132332Smarcelstatic TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); 43132332Smarcel 44132332Smarcelextern struct ta_ops libc_r_db_ops; 45132332Smarcelextern struct ta_ops libpthread_db_ops; 46132332Smarcelextern struct ta_ops libthr_db_ops; 47132332Smarcel 48132332Smarcelstatic struct ta_ops *ops[] = { 49132332Smarcel &libpthread_db_ops, 50132332Smarcel &libthr_db_ops, 51132332Smarcel &libc_r_db_ops 52132332Smarcel}; 53132332Smarcel 54132332Smarceltd_err_e 55132332Smarceltd_init(void) 56132332Smarcel{ 57132332Smarcel td_err_e ret, tmp; 58132332Smarcel size_t i; 59132332Smarcel 60132332Smarcel ret = 0; 61132332Smarcel for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { 62132332Smarcel if (ops[i]->to_init != NULL) { 63132332Smarcel tmp = ops[i]->to_init(); 64132332Smarcel if (tmp != TD_OK) 65132332Smarcel ret = tmp; 66132332Smarcel } 67132332Smarcel } 68132332Smarcel return (ret); 69132332Smarcel} 70132332Smarcel 71132332Smarceltd_err_e 72132332Smarceltd_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 73132332Smarcel{ 74132332Smarcel return (ta->ta_ops->to_ta_clear_event(ta, events)); 75132332Smarcel} 76132332Smarcel 77132332Smarceltd_err_e 78132332Smarceltd_ta_delete(td_thragent_t *ta) 79132332Smarcel{ 80132332Smarcel TAILQ_REMOVE(&proclist, ta, ta_next); 81132332Smarcel return (ta->ta_ops->to_ta_delete(ta)); 82132332Smarcel} 83132332Smarcel 84132332Smarceltd_err_e 85132332Smarceltd_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 86132332Smarcel{ 87132332Smarcel return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); 88132332Smarcel} 89132332Smarcel 90132332Smarceltd_err_e 91132332Smarceltd_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 92132332Smarcel{ 93132332Smarcel return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); 94132332Smarcel} 95132332Smarcel 96132332Smarceltd_err_e 97132332Smarceltd_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 98132332Smarcel{ 99132332Smarcel return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); 100132332Smarcel} 101132332Smarcel 102132332Smarceltd_err_e 103132332Smarceltd_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) 104132332Smarcel{ 105132332Smarcel return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); 106132332Smarcel} 107132332Smarcel 108132332Smarceltd_err_e 109132332Smarceltd_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 110132332Smarcel{ 111132332Smarcel size_t i; 112132332Smarcel 113132332Smarcel for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { 114132332Smarcel if (ops[i]->to_ta_new(ph, pta) == TD_OK) { 115132332Smarcel TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); 116132332Smarcel (*pta)->ta_ops = ops[i]; 117132332Smarcel return (TD_OK); 118132332Smarcel } 119132332Smarcel } 120132332Smarcel return (TD_NOLIBTHREAD); 121132332Smarcel} 122132332Smarcel 123132332Smarceltd_err_e 124132332Smarceltd_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 125132332Smarcel{ 126132332Smarcel return (ta->ta_ops->to_ta_set_event(ta, events)); 127132332Smarcel} 128132332Smarcel 129132332Smarceltd_err_e 130132332Smarceltd_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 131132332Smarcel void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, 132132332Smarcel unsigned int ti_user_flags) 133132332Smarcel{ 134132332Smarcel return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, 135132332Smarcel ti_pri, ti_sigmask_p, ti_user_flags)); 136132332Smarcel} 137132332Smarcel 138132332Smarceltd_err_e 139132332Smarceltd_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, 140132332Smarcel void *cbdata_p) 141132332Smarcel{ 142132332Smarcel return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); 143132332Smarcel} 144132332Smarcel 145132332Smarceltd_err_e 146132332Smarceltd_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) 147132332Smarcel{ 148132332Smarcel const td_thragent_t *ta = th->th_ta; 149132332Smarcel return (ta->ta_ops->to_thr_clear_event(th, events)); 150132332Smarcel} 151132332Smarcel 152132332Smarceltd_err_e 153132332Smarceltd_thr_dbresume(const td_thrhandle_t *th) 154132332Smarcel{ 155132332Smarcel const td_thragent_t *ta = th->th_ta; 156132332Smarcel return (ta->ta_ops->to_thr_dbresume(th)); 157132332Smarcel} 158132332Smarcel 159132332Smarceltd_err_e 160132332Smarceltd_thr_dbsuspend(const td_thrhandle_t *th) 161132332Smarcel{ 162132332Smarcel const td_thragent_t *ta = th->th_ta; 163132332Smarcel return (ta->ta_ops->to_thr_dbsuspend(th)); 164132332Smarcel} 165132332Smarcel 166132332Smarceltd_err_e 167132332Smarceltd_thr_event_enable(const td_thrhandle_t *th, int en) 168132332Smarcel{ 169132332Smarcel const td_thragent_t *ta = th->th_ta; 170132332Smarcel return (ta->ta_ops->to_thr_event_enable(th, en)); 171132332Smarcel} 172132332Smarcel 173132332Smarceltd_err_e 174132332Smarceltd_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 175132332Smarcel{ 176132332Smarcel const td_thragent_t *ta = th->th_ta; 177132332Smarcel return (ta->ta_ops->to_thr_event_getmsg(th, msg)); 178132332Smarcel} 179132332Smarcel 180132332Smarceltd_err_e 181132332Smarceltd_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 182132332Smarcel{ 183132332Smarcel const td_thragent_t *ta = th->th_ta; 184132332Smarcel return (ta->ta_ops->to_thr_get_info(th, info)); 185132332Smarcel} 186132332Smarcel 187132332Smarceltd_err_e 188132332Smarceltd_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) 189132332Smarcel{ 190132332Smarcel const td_thragent_t *ta = th->th_ta; 191132332Smarcel return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); 192132332Smarcel} 193132332Smarcel 194132332Smarceltd_err_e 195132332Smarceltd_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 196132332Smarcel{ 197132332Smarcel const td_thragent_t *ta = th->th_ta; 198132332Smarcel return (ta->ta_ops->to_thr_getgregs(th, gregs)); 199132332Smarcel} 200132332Smarcel 201132332Smarceltd_err_e 202132332Smarceltd_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) 203132332Smarcel{ 204132332Smarcel const td_thragent_t *ta = th->th_ta; 205132332Smarcel return (ta->ta_ops->to_thr_set_event(th, events)); 206132332Smarcel} 207132332Smarcel 208132332Smarceltd_err_e 209132332Smarceltd_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 210132332Smarcel{ 211132332Smarcel const td_thragent_t *ta = th->th_ta; 212132332Smarcel return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); 213132332Smarcel} 214132332Smarcel 215132332Smarceltd_err_e 216132332Smarceltd_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 217132332Smarcel{ 218132332Smarcel const td_thragent_t *ta = th->th_ta; 219132332Smarcel return (ta->ta_ops->to_thr_setgregs(th, gregs)); 220132332Smarcel} 221132332Smarcel 222132332Smarceltd_err_e 223132332Smarceltd_thr_validate(const td_thrhandle_t *th) 224132332Smarcel{ 225132332Smarcel const td_thragent_t *ta = th->th_ta; 226132332Smarcel return (ta->ta_ops->to_thr_validate(th)); 227132332Smarcel} 228132332Smarcel 229132332Smarcel/* FreeBSD specific extensions. */ 230132332Smarcel 231132332Smarceltd_err_e 232132332Smarceltd_thr_sstep(const td_thrhandle_t *th, int step) 233132332Smarcel{ 234132332Smarcel const td_thragent_t *ta = th->th_ta; 235132332Smarcel return (ta->ta_ops->to_thr_sstep(th, step)); 236132332Smarcel} 237