13c1e38eaSMarcel Moolenaar /* 23c1e38eaSMarcel Moolenaar * Copyright (c) 2004 David Xu <davidxu@freebsd.org> 33c1e38eaSMarcel Moolenaar * All rights reserved. 43c1e38eaSMarcel Moolenaar * 53c1e38eaSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 63c1e38eaSMarcel Moolenaar * modification, are permitted provided that the following conditions 73c1e38eaSMarcel Moolenaar * are met: 83c1e38eaSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 93c1e38eaSMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 103c1e38eaSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 113c1e38eaSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 123c1e38eaSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 133c1e38eaSMarcel Moolenaar * 143c1e38eaSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 153c1e38eaSMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 163c1e38eaSMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 173c1e38eaSMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 183c1e38eaSMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193c1e38eaSMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 203c1e38eaSMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 213c1e38eaSMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 223c1e38eaSMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 233c1e38eaSMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 243c1e38eaSMarcel Moolenaar * SUCH DAMAGE. 253c1e38eaSMarcel Moolenaar */ 263c1e38eaSMarcel Moolenaar 273c1e38eaSMarcel Moolenaar #include <sys/cdefs.h> 283c1e38eaSMarcel Moolenaar __FBSDID("$FreeBSD$"); 293c1e38eaSMarcel Moolenaar 303c1e38eaSMarcel Moolenaar #include <proc_service.h> 313c1e38eaSMarcel Moolenaar #include <stddef.h> 323c1e38eaSMarcel Moolenaar #include <thread_db.h> 333c1e38eaSMarcel Moolenaar #include <unistd.h> 3420b94d80SDavid Xu #include <sys/cdefs.h> 3520b94d80SDavid Xu #include <sys/linker_set.h> 363c1e38eaSMarcel Moolenaar 373c1e38eaSMarcel Moolenaar #include "thread_db_int.h" 383c1e38eaSMarcel Moolenaar 393c1e38eaSMarcel Moolenaar struct td_thragent 403c1e38eaSMarcel Moolenaar { 413c1e38eaSMarcel Moolenaar TD_THRAGENT_FIELDS; 423c1e38eaSMarcel Moolenaar }; 433c1e38eaSMarcel Moolenaar 443c1e38eaSMarcel Moolenaar static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); 453c1e38eaSMarcel Moolenaar 4620b94d80SDavid Xu SET_DECLARE(__ta_ops, struct ta_ops); 473c1e38eaSMarcel Moolenaar 483c1e38eaSMarcel Moolenaar td_err_e 493c1e38eaSMarcel Moolenaar td_init(void) 503c1e38eaSMarcel Moolenaar { 513c1e38eaSMarcel Moolenaar td_err_e ret, tmp; 5220b94d80SDavid Xu struct ta_ops *ops_p, **ops_pp; 533c1e38eaSMarcel Moolenaar size_t i; 543c1e38eaSMarcel Moolenaar 553c1e38eaSMarcel Moolenaar ret = 0; 5620b94d80SDavid Xu SET_FOREACH(ops_pp, __ta_ops) { 5720b94d80SDavid Xu ops_p = *ops_pp; 5820b94d80SDavid Xu if (ops_p->to_init != NULL) { 5920b94d80SDavid Xu tmp = ops_p->to_init(); 603c1e38eaSMarcel Moolenaar if (tmp != TD_OK) 613c1e38eaSMarcel Moolenaar ret = tmp; 623c1e38eaSMarcel Moolenaar } 633c1e38eaSMarcel Moolenaar } 643c1e38eaSMarcel Moolenaar return (ret); 653c1e38eaSMarcel Moolenaar } 663c1e38eaSMarcel Moolenaar 673c1e38eaSMarcel Moolenaar td_err_e 683c1e38eaSMarcel Moolenaar td_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 693c1e38eaSMarcel Moolenaar { 703c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_clear_event(ta, events)); 713c1e38eaSMarcel Moolenaar } 723c1e38eaSMarcel Moolenaar 733c1e38eaSMarcel Moolenaar td_err_e 743c1e38eaSMarcel Moolenaar td_ta_delete(td_thragent_t *ta) 753c1e38eaSMarcel Moolenaar { 763c1e38eaSMarcel Moolenaar TAILQ_REMOVE(&proclist, ta, ta_next); 773c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_delete(ta)); 783c1e38eaSMarcel Moolenaar } 793c1e38eaSMarcel Moolenaar 803c1e38eaSMarcel Moolenaar td_err_e 813c1e38eaSMarcel Moolenaar td_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 823c1e38eaSMarcel Moolenaar { 833c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); 843c1e38eaSMarcel Moolenaar } 853c1e38eaSMarcel Moolenaar 863c1e38eaSMarcel Moolenaar td_err_e 873c1e38eaSMarcel Moolenaar td_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 883c1e38eaSMarcel Moolenaar { 893c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); 903c1e38eaSMarcel Moolenaar } 913c1e38eaSMarcel Moolenaar 923c1e38eaSMarcel Moolenaar td_err_e 933c1e38eaSMarcel Moolenaar td_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 943c1e38eaSMarcel Moolenaar { 953c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); 963c1e38eaSMarcel Moolenaar } 973c1e38eaSMarcel Moolenaar 983c1e38eaSMarcel Moolenaar td_err_e 993c1e38eaSMarcel Moolenaar td_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) 1003c1e38eaSMarcel Moolenaar { 1013c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); 1023c1e38eaSMarcel Moolenaar } 1033c1e38eaSMarcel Moolenaar 1043c1e38eaSMarcel Moolenaar td_err_e 1053c1e38eaSMarcel Moolenaar td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 1063c1e38eaSMarcel Moolenaar { 1073c1e38eaSMarcel Moolenaar size_t i; 10820b94d80SDavid Xu struct ta_ops *ops_p, **ops_pp; 1093c1e38eaSMarcel Moolenaar 11020b94d80SDavid Xu SET_FOREACH(ops_pp, __ta_ops) { 11120b94d80SDavid Xu ops_p = *ops_pp; 11220b94d80SDavid Xu if (ops_p->to_ta_new(ph, pta) == TD_OK) { 1133c1e38eaSMarcel Moolenaar TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); 11420b94d80SDavid Xu (*pta)->ta_ops = ops_p; 1153c1e38eaSMarcel Moolenaar return (TD_OK); 1163c1e38eaSMarcel Moolenaar } 1173c1e38eaSMarcel Moolenaar } 1183c1e38eaSMarcel Moolenaar return (TD_NOLIBTHREAD); 1193c1e38eaSMarcel Moolenaar } 1203c1e38eaSMarcel Moolenaar 1213c1e38eaSMarcel Moolenaar td_err_e 1223c1e38eaSMarcel Moolenaar td_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 1233c1e38eaSMarcel Moolenaar { 1243c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_set_event(ta, events)); 1253c1e38eaSMarcel Moolenaar } 1263c1e38eaSMarcel Moolenaar 1273c1e38eaSMarcel Moolenaar td_err_e 1283c1e38eaSMarcel Moolenaar td_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 1293c1e38eaSMarcel Moolenaar void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, 1303c1e38eaSMarcel Moolenaar unsigned int ti_user_flags) 1313c1e38eaSMarcel Moolenaar { 1323c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, 1333c1e38eaSMarcel Moolenaar ti_pri, ti_sigmask_p, ti_user_flags)); 1343c1e38eaSMarcel Moolenaar } 1353c1e38eaSMarcel Moolenaar 1363c1e38eaSMarcel Moolenaar td_err_e 1373c1e38eaSMarcel Moolenaar td_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, 1383c1e38eaSMarcel Moolenaar void *cbdata_p) 1393c1e38eaSMarcel Moolenaar { 1403c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); 1413c1e38eaSMarcel Moolenaar } 1423c1e38eaSMarcel Moolenaar 1433c1e38eaSMarcel Moolenaar td_err_e 1443c1e38eaSMarcel Moolenaar td_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) 1453c1e38eaSMarcel Moolenaar { 1463c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1473c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_clear_event(th, events)); 1483c1e38eaSMarcel Moolenaar } 1493c1e38eaSMarcel Moolenaar 1503c1e38eaSMarcel Moolenaar td_err_e 1513c1e38eaSMarcel Moolenaar td_thr_dbresume(const td_thrhandle_t *th) 1523c1e38eaSMarcel Moolenaar { 1533c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1543c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_dbresume(th)); 1553c1e38eaSMarcel Moolenaar } 1563c1e38eaSMarcel Moolenaar 1573c1e38eaSMarcel Moolenaar td_err_e 1583c1e38eaSMarcel Moolenaar td_thr_dbsuspend(const td_thrhandle_t *th) 1593c1e38eaSMarcel Moolenaar { 1603c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1613c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_dbsuspend(th)); 1623c1e38eaSMarcel Moolenaar } 1633c1e38eaSMarcel Moolenaar 1643c1e38eaSMarcel Moolenaar td_err_e 1653c1e38eaSMarcel Moolenaar td_thr_event_enable(const td_thrhandle_t *th, int en) 1663c1e38eaSMarcel Moolenaar { 1673c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1683c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_event_enable(th, en)); 1693c1e38eaSMarcel Moolenaar } 1703c1e38eaSMarcel Moolenaar 1713c1e38eaSMarcel Moolenaar td_err_e 1723c1e38eaSMarcel Moolenaar td_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 1733c1e38eaSMarcel Moolenaar { 1743c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1753c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_event_getmsg(th, msg)); 1763c1e38eaSMarcel Moolenaar } 1773c1e38eaSMarcel Moolenaar 1783c1e38eaSMarcel Moolenaar td_err_e 1793c1e38eaSMarcel Moolenaar td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 1803c1e38eaSMarcel Moolenaar { 1813c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1823c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_get_info(th, info)); 1833c1e38eaSMarcel Moolenaar } 1843c1e38eaSMarcel Moolenaar 1858d7681bbSDoug Rabson #ifdef __i386__ 1868d7681bbSDoug Rabson td_err_e 1878d7681bbSDoug Rabson td_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 1888d7681bbSDoug Rabson { 1898d7681bbSDoug Rabson const td_thragent_t *ta = th->th_ta; 1908d7681bbSDoug Rabson return (ta->ta_ops->to_thr_getxmmregs(th, fxsave)); 1918d7681bbSDoug Rabson } 1928d7681bbSDoug Rabson #endif 1938d7681bbSDoug Rabson 1948d7681bbSDoug Rabson 1953c1e38eaSMarcel Moolenaar td_err_e 1963c1e38eaSMarcel Moolenaar td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) 1973c1e38eaSMarcel Moolenaar { 1983c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1993c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); 2003c1e38eaSMarcel Moolenaar } 2013c1e38eaSMarcel Moolenaar 2023c1e38eaSMarcel Moolenaar td_err_e 2033c1e38eaSMarcel Moolenaar td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 2043c1e38eaSMarcel Moolenaar { 2053c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2063c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_getgregs(th, gregs)); 2073c1e38eaSMarcel Moolenaar } 2083c1e38eaSMarcel Moolenaar 2093c1e38eaSMarcel Moolenaar td_err_e 2103c1e38eaSMarcel Moolenaar td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) 2113c1e38eaSMarcel Moolenaar { 2123c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2133c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_set_event(th, events)); 2143c1e38eaSMarcel Moolenaar } 2153c1e38eaSMarcel Moolenaar 2168d7681bbSDoug Rabson #ifdef __i386__ 2178d7681bbSDoug Rabson td_err_e 2188d7681bbSDoug Rabson td_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 2198d7681bbSDoug Rabson { 2208d7681bbSDoug Rabson const td_thragent_t *ta = th->th_ta; 2218d7681bbSDoug Rabson return (ta->ta_ops->to_thr_setxmmregs(th, fxsave)); 2228d7681bbSDoug Rabson } 2238d7681bbSDoug Rabson #endif 2248d7681bbSDoug Rabson 2253c1e38eaSMarcel Moolenaar td_err_e 2263c1e38eaSMarcel Moolenaar td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 2273c1e38eaSMarcel Moolenaar { 2283c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2293c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); 2303c1e38eaSMarcel Moolenaar } 2313c1e38eaSMarcel Moolenaar 2323c1e38eaSMarcel Moolenaar td_err_e 2333c1e38eaSMarcel Moolenaar td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 2343c1e38eaSMarcel Moolenaar { 2353c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2363c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_setgregs(th, gregs)); 2373c1e38eaSMarcel Moolenaar } 2383c1e38eaSMarcel Moolenaar 2393c1e38eaSMarcel Moolenaar td_err_e 2403c1e38eaSMarcel Moolenaar td_thr_validate(const td_thrhandle_t *th) 2413c1e38eaSMarcel Moolenaar { 2423c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2433c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_validate(th)); 2443c1e38eaSMarcel Moolenaar } 2453c1e38eaSMarcel Moolenaar 2463e93cc3aSDavid Xu td_err_e 24716b0c20cSMarcel Moolenaar td_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t linkmap, size_t offset, 24816b0c20cSMarcel Moolenaar psaddr_t *address) 2493e93cc3aSDavid Xu { 2503e93cc3aSDavid Xu const td_thragent_t *ta = th->th_ta; 2513e93cc3aSDavid Xu return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address)); 2523e93cc3aSDavid Xu } 2533e93cc3aSDavid Xu 2543c1e38eaSMarcel Moolenaar /* FreeBSD specific extensions. */ 2553c1e38eaSMarcel Moolenaar 2563c1e38eaSMarcel Moolenaar td_err_e 2573c1e38eaSMarcel Moolenaar td_thr_sstep(const td_thrhandle_t *th, int step) 2583c1e38eaSMarcel Moolenaar { 2593c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2603c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_sstep(th, step)); 2613c1e38eaSMarcel Moolenaar } 262