1 /* 2 * Copyright (c) 2004 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $DragonFly: src/lib/libthread_db/thread_db.c,v 1.1 2005/05/07 09:25:44 davidxu Exp $ 27 */ 28 29 #include <sys/cdefs.h> 30 #include <proc_service.h> 31 #include <stddef.h> 32 #include <thread_db.h> 33 #include <unistd.h> 34 35 #include "thread_db_int.h" 36 37 struct td_thragent 38 { 39 TD_THRAGENT_FIELDS; 40 }; 41 42 static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); 43 44 extern struct ta_ops libthread_xu_ops; 45 46 static struct ta_ops *ops[] = { 47 &libthread_xu_ops, 48 }; 49 50 td_err_e 51 td_init(void) 52 { 53 td_err_e ret, tmp; 54 size_t i; 55 56 ret = 0; 57 for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { 58 if (ops[i]->to_init != NULL) { 59 tmp = ops[i]->to_init(); 60 if (tmp != TD_OK) 61 ret = tmp; 62 } 63 } 64 return (ret); 65 } 66 67 td_err_e 68 td_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 69 { 70 return (ta->ta_ops->to_ta_clear_event(ta, events)); 71 } 72 73 td_err_e 74 td_ta_delete(td_thragent_t *ta) 75 { 76 TAILQ_REMOVE(&proclist, ta, ta_next); 77 return (ta->ta_ops->to_ta_delete(ta)); 78 } 79 80 td_err_e 81 td_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 82 { 83 return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); 84 } 85 86 td_err_e 87 td_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 88 { 89 return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); 90 } 91 92 td_err_e 93 td_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 94 { 95 return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); 96 } 97 98 td_err_e 99 td_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) 100 { 101 return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); 102 } 103 104 td_err_e 105 td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 106 { 107 size_t i; 108 109 for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { 110 if (ops[i]->to_ta_new(ph, pta) == TD_OK) { 111 TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); 112 (*pta)->ta_ops = ops[i]; 113 return (TD_OK); 114 } 115 } 116 return (TD_NOLIBTHREAD); 117 } 118 119 td_err_e 120 td_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 121 { 122 return (ta->ta_ops->to_ta_set_event(ta, events)); 123 } 124 125 td_err_e 126 td_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 127 void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, 128 unsigned int ti_user_flags) 129 { 130 return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, 131 ti_pri, ti_sigmask_p, ti_user_flags)); 132 } 133 134 td_err_e 135 td_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, 136 void *cbdata_p) 137 { 138 return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); 139 } 140 141 td_err_e 142 td_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) 143 { 144 const td_thragent_t *ta = th->th_ta; 145 return (ta->ta_ops->to_thr_clear_event(th, events)); 146 } 147 148 td_err_e 149 td_thr_dbresume(const td_thrhandle_t *th) 150 { 151 const td_thragent_t *ta = th->th_ta; 152 return (ta->ta_ops->to_thr_dbresume(th)); 153 } 154 155 td_err_e 156 td_thr_dbsuspend(const td_thrhandle_t *th) 157 { 158 const td_thragent_t *ta = th->th_ta; 159 return (ta->ta_ops->to_thr_dbsuspend(th)); 160 } 161 162 td_err_e 163 td_thr_event_enable(const td_thrhandle_t *th, int en) 164 { 165 const td_thragent_t *ta = th->th_ta; 166 return (ta->ta_ops->to_thr_event_enable(th, en)); 167 } 168 169 td_err_e 170 td_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 171 { 172 const td_thragent_t *ta = th->th_ta; 173 return (ta->ta_ops->to_thr_event_getmsg(th, msg)); 174 } 175 176 td_err_e 177 td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 178 { 179 const td_thragent_t *ta = th->th_ta; 180 return (ta->ta_ops->to_thr_get_info(th, info)); 181 } 182 183 td_err_e 184 td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) 185 { 186 const td_thragent_t *ta = th->th_ta; 187 return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); 188 } 189 190 td_err_e 191 td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 192 { 193 const td_thragent_t *ta = th->th_ta; 194 return (ta->ta_ops->to_thr_getgregs(th, gregs)); 195 } 196 197 td_err_e 198 td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) 199 { 200 const td_thragent_t *ta = th->th_ta; 201 return (ta->ta_ops->to_thr_set_event(th, events)); 202 } 203 204 td_err_e 205 td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 206 { 207 const td_thragent_t *ta = th->th_ta; 208 return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); 209 } 210 211 td_err_e 212 td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 213 { 214 const td_thragent_t *ta = th->th_ta; 215 return (ta->ta_ops->to_thr_setgregs(th, gregs)); 216 } 217 218 td_err_e 219 td_thr_validate(const td_thrhandle_t *th) 220 { 221 const td_thragent_t *ta = th->th_ta; 222 return (ta->ta_ops->to_thr_validate(th)); 223 } 224 225 td_err_e 226 td_thr_tls_get_addr(const td_thrhandle_t *th, void *linkmap, size_t offset, 227 void **address) 228 { 229 const td_thragent_t *ta = th->th_ta; 230 return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address)); 231 } 232