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> 343c1e38eaSMarcel Moolenaar 353c1e38eaSMarcel Moolenaar #include "thread_db_int.h" 363c1e38eaSMarcel Moolenaar 373c1e38eaSMarcel Moolenaar struct td_thragent 383c1e38eaSMarcel Moolenaar { 393c1e38eaSMarcel Moolenaar TD_THRAGENT_FIELDS; 403c1e38eaSMarcel Moolenaar }; 413c1e38eaSMarcel Moolenaar 423c1e38eaSMarcel Moolenaar static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); 433c1e38eaSMarcel Moolenaar 443c1e38eaSMarcel Moolenaar extern struct ta_ops libc_r_db_ops; 453c1e38eaSMarcel Moolenaar extern struct ta_ops libpthread_db_ops; 463c1e38eaSMarcel Moolenaar extern struct ta_ops libthr_db_ops; 473c1e38eaSMarcel Moolenaar 483c1e38eaSMarcel Moolenaar static struct ta_ops *ops[] = { 493c1e38eaSMarcel Moolenaar &libpthread_db_ops, 503c1e38eaSMarcel Moolenaar &libthr_db_ops, 513c1e38eaSMarcel Moolenaar &libc_r_db_ops 523c1e38eaSMarcel Moolenaar }; 533c1e38eaSMarcel Moolenaar 543c1e38eaSMarcel Moolenaar td_err_e 553c1e38eaSMarcel Moolenaar td_init(void) 563c1e38eaSMarcel Moolenaar { 573c1e38eaSMarcel Moolenaar td_err_e ret, tmp; 583c1e38eaSMarcel Moolenaar size_t i; 593c1e38eaSMarcel Moolenaar 603c1e38eaSMarcel Moolenaar ret = 0; 613c1e38eaSMarcel Moolenaar for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { 623c1e38eaSMarcel Moolenaar if (ops[i]->to_init != NULL) { 633c1e38eaSMarcel Moolenaar tmp = ops[i]->to_init(); 643c1e38eaSMarcel Moolenaar if (tmp != TD_OK) 653c1e38eaSMarcel Moolenaar ret = tmp; 663c1e38eaSMarcel Moolenaar } 673c1e38eaSMarcel Moolenaar } 683c1e38eaSMarcel Moolenaar return (ret); 693c1e38eaSMarcel Moolenaar } 703c1e38eaSMarcel Moolenaar 713c1e38eaSMarcel Moolenaar td_err_e 723c1e38eaSMarcel Moolenaar td_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 733c1e38eaSMarcel Moolenaar { 743c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_clear_event(ta, events)); 753c1e38eaSMarcel Moolenaar } 763c1e38eaSMarcel Moolenaar 773c1e38eaSMarcel Moolenaar td_err_e 783c1e38eaSMarcel Moolenaar td_ta_delete(td_thragent_t *ta) 793c1e38eaSMarcel Moolenaar { 803c1e38eaSMarcel Moolenaar TAILQ_REMOVE(&proclist, ta, ta_next); 813c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_delete(ta)); 823c1e38eaSMarcel Moolenaar } 833c1e38eaSMarcel Moolenaar 843c1e38eaSMarcel Moolenaar td_err_e 853c1e38eaSMarcel Moolenaar td_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 863c1e38eaSMarcel Moolenaar { 873c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); 883c1e38eaSMarcel Moolenaar } 893c1e38eaSMarcel Moolenaar 903c1e38eaSMarcel Moolenaar td_err_e 913c1e38eaSMarcel Moolenaar td_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 923c1e38eaSMarcel Moolenaar { 933c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); 943c1e38eaSMarcel Moolenaar } 953c1e38eaSMarcel Moolenaar 963c1e38eaSMarcel Moolenaar td_err_e 973c1e38eaSMarcel Moolenaar td_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 983c1e38eaSMarcel Moolenaar { 993c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); 1003c1e38eaSMarcel Moolenaar } 1013c1e38eaSMarcel Moolenaar 1023c1e38eaSMarcel Moolenaar td_err_e 1033c1e38eaSMarcel Moolenaar td_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) 1043c1e38eaSMarcel Moolenaar { 1053c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); 1063c1e38eaSMarcel Moolenaar } 1073c1e38eaSMarcel Moolenaar 1083c1e38eaSMarcel Moolenaar td_err_e 1093c1e38eaSMarcel Moolenaar td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 1103c1e38eaSMarcel Moolenaar { 1113c1e38eaSMarcel Moolenaar size_t i; 1123c1e38eaSMarcel Moolenaar 1133c1e38eaSMarcel Moolenaar for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { 1143c1e38eaSMarcel Moolenaar if (ops[i]->to_ta_new(ph, pta) == TD_OK) { 1153c1e38eaSMarcel Moolenaar TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); 1163c1e38eaSMarcel Moolenaar (*pta)->ta_ops = ops[i]; 1173c1e38eaSMarcel Moolenaar return (TD_OK); 1183c1e38eaSMarcel Moolenaar } 1193c1e38eaSMarcel Moolenaar } 1203c1e38eaSMarcel Moolenaar return (TD_NOLIBTHREAD); 1213c1e38eaSMarcel Moolenaar } 1223c1e38eaSMarcel Moolenaar 1233c1e38eaSMarcel Moolenaar td_err_e 1243c1e38eaSMarcel Moolenaar td_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 1253c1e38eaSMarcel Moolenaar { 1263c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_set_event(ta, events)); 1273c1e38eaSMarcel Moolenaar } 1283c1e38eaSMarcel Moolenaar 1293c1e38eaSMarcel Moolenaar td_err_e 1303c1e38eaSMarcel Moolenaar td_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 1313c1e38eaSMarcel Moolenaar void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, 1323c1e38eaSMarcel Moolenaar unsigned int ti_user_flags) 1333c1e38eaSMarcel Moolenaar { 1343c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, 1353c1e38eaSMarcel Moolenaar ti_pri, ti_sigmask_p, ti_user_flags)); 1363c1e38eaSMarcel Moolenaar } 1373c1e38eaSMarcel Moolenaar 1383c1e38eaSMarcel Moolenaar td_err_e 1393c1e38eaSMarcel Moolenaar td_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, 1403c1e38eaSMarcel Moolenaar void *cbdata_p) 1413c1e38eaSMarcel Moolenaar { 1423c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); 1433c1e38eaSMarcel Moolenaar } 1443c1e38eaSMarcel Moolenaar 1453c1e38eaSMarcel Moolenaar td_err_e 1463c1e38eaSMarcel Moolenaar td_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) 1473c1e38eaSMarcel Moolenaar { 1483c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1493c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_clear_event(th, events)); 1503c1e38eaSMarcel Moolenaar } 1513c1e38eaSMarcel Moolenaar 1523c1e38eaSMarcel Moolenaar td_err_e 1533c1e38eaSMarcel Moolenaar td_thr_dbresume(const td_thrhandle_t *th) 1543c1e38eaSMarcel Moolenaar { 1553c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1563c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_dbresume(th)); 1573c1e38eaSMarcel Moolenaar } 1583c1e38eaSMarcel Moolenaar 1593c1e38eaSMarcel Moolenaar td_err_e 1603c1e38eaSMarcel Moolenaar td_thr_dbsuspend(const td_thrhandle_t *th) 1613c1e38eaSMarcel Moolenaar { 1623c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1633c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_dbsuspend(th)); 1643c1e38eaSMarcel Moolenaar } 1653c1e38eaSMarcel Moolenaar 1663c1e38eaSMarcel Moolenaar td_err_e 1673c1e38eaSMarcel Moolenaar td_thr_event_enable(const td_thrhandle_t *th, int en) 1683c1e38eaSMarcel Moolenaar { 1693c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1703c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_event_enable(th, en)); 1713c1e38eaSMarcel Moolenaar } 1723c1e38eaSMarcel Moolenaar 1733c1e38eaSMarcel Moolenaar td_err_e 1743c1e38eaSMarcel Moolenaar td_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 1753c1e38eaSMarcel Moolenaar { 1763c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1773c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_event_getmsg(th, msg)); 1783c1e38eaSMarcel Moolenaar } 1793c1e38eaSMarcel Moolenaar 1803c1e38eaSMarcel Moolenaar td_err_e 1813c1e38eaSMarcel Moolenaar td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 1823c1e38eaSMarcel Moolenaar { 1833c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 1843c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_get_info(th, info)); 1853c1e38eaSMarcel Moolenaar } 1863c1e38eaSMarcel Moolenaar 1878d7681bbSDoug Rabson #ifdef __i386__ 1888d7681bbSDoug Rabson td_err_e 1898d7681bbSDoug Rabson td_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 1908d7681bbSDoug Rabson { 1918d7681bbSDoug Rabson const td_thragent_t *ta = th->th_ta; 1928d7681bbSDoug Rabson return (ta->ta_ops->to_thr_getxmmregs(th, fxsave)); 1938d7681bbSDoug Rabson } 1948d7681bbSDoug Rabson #endif 1958d7681bbSDoug Rabson 1968d7681bbSDoug Rabson 1973c1e38eaSMarcel Moolenaar td_err_e 1983c1e38eaSMarcel Moolenaar td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) 1993c1e38eaSMarcel Moolenaar { 2003c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2013c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); 2023c1e38eaSMarcel Moolenaar } 2033c1e38eaSMarcel Moolenaar 2043c1e38eaSMarcel Moolenaar td_err_e 2053c1e38eaSMarcel Moolenaar td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 2063c1e38eaSMarcel Moolenaar { 2073c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2083c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_getgregs(th, gregs)); 2093c1e38eaSMarcel Moolenaar } 2103c1e38eaSMarcel Moolenaar 2113c1e38eaSMarcel Moolenaar td_err_e 2123c1e38eaSMarcel Moolenaar td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) 2133c1e38eaSMarcel Moolenaar { 2143c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2153c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_set_event(th, events)); 2163c1e38eaSMarcel Moolenaar } 2173c1e38eaSMarcel Moolenaar 2188d7681bbSDoug Rabson #ifdef __i386__ 2198d7681bbSDoug Rabson td_err_e 2208d7681bbSDoug Rabson td_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 2218d7681bbSDoug Rabson { 2228d7681bbSDoug Rabson const td_thragent_t *ta = th->th_ta; 2238d7681bbSDoug Rabson return (ta->ta_ops->to_thr_setxmmregs(th, fxsave)); 2248d7681bbSDoug Rabson } 2258d7681bbSDoug Rabson #endif 2268d7681bbSDoug Rabson 2273c1e38eaSMarcel Moolenaar td_err_e 2283c1e38eaSMarcel Moolenaar td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 2293c1e38eaSMarcel Moolenaar { 2303c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2313c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); 2323c1e38eaSMarcel Moolenaar } 2333c1e38eaSMarcel Moolenaar 2343c1e38eaSMarcel Moolenaar td_err_e 2353c1e38eaSMarcel Moolenaar td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 2363c1e38eaSMarcel Moolenaar { 2373c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2383c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_setgregs(th, gregs)); 2393c1e38eaSMarcel Moolenaar } 2403c1e38eaSMarcel Moolenaar 2413c1e38eaSMarcel Moolenaar td_err_e 2423c1e38eaSMarcel Moolenaar td_thr_validate(const td_thrhandle_t *th) 2433c1e38eaSMarcel Moolenaar { 2443c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2453c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_validate(th)); 2463c1e38eaSMarcel Moolenaar } 2473c1e38eaSMarcel Moolenaar 2483e93cc3aSDavid Xu td_err_e 2493e93cc3aSDavid Xu td_thr_tls_get_addr(const td_thrhandle_t *th, void *linkmap, size_t offset, 2503e93cc3aSDavid Xu void **address) 2513e93cc3aSDavid Xu { 2523e93cc3aSDavid Xu const td_thragent_t *ta = th->th_ta; 2533e93cc3aSDavid Xu return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address)); 2543e93cc3aSDavid Xu } 2553e93cc3aSDavid Xu 2563c1e38eaSMarcel Moolenaar /* FreeBSD specific extensions. */ 2573c1e38eaSMarcel Moolenaar 2583c1e38eaSMarcel Moolenaar td_err_e 2593c1e38eaSMarcel Moolenaar td_thr_sstep(const td_thrhandle_t *th, int step) 2603c1e38eaSMarcel Moolenaar { 2613c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 2623c1e38eaSMarcel Moolenaar return (ta->ta_ops->to_thr_sstep(th, step)); 2633c1e38eaSMarcel Moolenaar } 264