diff options
author | marcel <marcel@FreeBSD.org> | 2004-07-18 04:17:15 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2004-07-18 04:17:15 +0000 |
commit | 03a64a6205cacf6f86c1fd453ba860c7c396b285 (patch) | |
tree | 7bd51edf97e872db5b632c4e4f5b742ac0fb5e09 /lib/libthread_db/pthread/pthread_db.c | |
parent | 606ea367aee6e42c3e2ef3e78e6a2c9450ca0733 (diff) | |
download | FreeBSD-src-03a64a6205cacf6f86c1fd453ba860c7c396b285.zip FreeBSD-src-03a64a6205cacf6f86c1fd453ba860c7c396b285.tar.gz |
Add rudimentary support and stubs for libthr and libc_r on alpha, amd64,
i386, ia64 and sparc64. Add stubs for alpha, amd64, ia64 and sparc64 for
libpthread.
Restructure the source files to avoid unnecessary use of subdirectories
that also force us to use non-portable compilation flags to deal with
the uncommon compilation requirements (building archive libraries for
linkage into a shared library).
The libpthread support has been copied from the original local and
cleaned-up to make them WARNS=2 clean.
that also force us to use non-portable compilation flags to deal with
the uncommon compilation requirements (building archive libraries for
linkage into a shared library).
The libpthread support has been copied from the original local and
cleaned-up to make them WARNS=2 clean.
Tested on: amd64, i386, ia64
Diffstat (limited to 'lib/libthread_db/pthread/pthread_db.c')
-rw-r--r-- | lib/libthread_db/pthread/pthread_db.c | 1087 |
1 files changed, 0 insertions, 1087 deletions
diff --git a/lib/libthread_db/pthread/pthread_db.c b/lib/libthread_db/pthread/pthread_db.c deleted file mode 100644 index 9a468b3..0000000 --- a/lib/libthread_db/pthread/pthread_db.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (c) 2004 David Xu <davidxu@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <pthread.h> -#include <thr_private.h> -#include <sys/types.h> -#include <sys/kse.h> -#include <sys/ptrace.h> -#include <proc_service.h> -#include <thread_db.h> - -#include "pthread_db.h" - -struct pt_map { - enum { - PT_NONE, - PT_USER, - PT_LWP - } type; - - union { - lwpid_t lwp; - psaddr_t thr; - }; -}; - -#define P2T(c) ps2td(c) - -static td_err_e pt_ta_activated(pt_thragent_t *ta, int *a); -static long pt_map_thread(const pt_thragent_t *ta, psaddr_t pt); -static long pt_map_lwp(const pt_thragent_t *ta, lwpid_t lwp); -static void pt_unmap_lwp(const pt_thragent_t *ta, lwpid_t lwp); -static int pt_validate(const td_thrhandle_t *th); - -static int -ps2td(int c) -{ - switch (c) { - case PS_OK: - return TD_OK; - case PS_ERR: - return TD_ERR; - case PS_BADPID: - return TD_BADPH; - case PS_BADLID: - return TD_NOLWP; - case PS_BADADDR: - return TD_ERR; - case PS_NOSYM: - return TD_NOLIBTHREAD; - case PS_NOFREGS: - return TD_NOFPREGS; - default: - return TD_ERR; - } -} - -static td_err_e -pt_init(void) -{ - pt_md_init(); - return (0); -} - -static td_err_e -pt_ta_new(struct ps_prochandle *ph, pt_thragent_t **pta) -{ -#define LOOKUP_SYM(proc, sym, addr) \ - ret = ps_pglobal_lookup(proc, NULL, sym, addr); \ - if (ret != 0) { \ - TDBG("can not find symbol: %s\n", sym); \ - ret = TD_NOLIBTHREAD; \ - goto error; \ - } - - pt_thragent_t *ta; - int dbg; - int ret; - - TDBG_FUNC(); - - ta = malloc(sizeof(pt_thragent_t)); - if (ta == NULL) - return (TD_MALLOC); - - ta->ph = ph; - ta->thread_activated = 0; - ta->map = NULL; - ta->map_len = 0; - - LOOKUP_SYM(ph, "_libkse_debug", &ta->libkse_debug_addr); - LOOKUP_SYM(ph, "_thread_list", &ta->thread_list_addr); - LOOKUP_SYM(ph, "_thread_activated", &ta->thread_activated_addr); - LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr); - LOOKUP_SYM(ph, "_thread_keytable", &ta->thread_keytable_addr); - - dbg = getpid(); - /* - * If this fails it probably means we're debugging a core file and - * can't write to it. - */ - ps_pdwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int)); - *pta = ta; - return (0); - -error: - free(ta); - return (ret); -} - -static td_err_e -pt_ta_delete(pt_thragent_t *ta) -{ - int dbg; - - TDBG_FUNC(); - - dbg = 0; - /* - * Error returns from this write are not really a problem; - * the process doesn't exist any more. - */ - ps_pdwrite(ta->ph, ta->libkse_debug_addr, &dbg, sizeof(int)); - if (ta->map) - free(ta->map); - free(ta); - return (TD_OK); -} - -static td_err_e -pt_ta_get_nthreads (const pt_thragent_t *ta, int *np) -{ - int ret; - - TDBG_FUNC(); - - ret = ps_pdread(ta->ph, ta->thread_active_threads_addr, np, - sizeof(int)); - return (P2T(ret)); -} - -static td_err_e -pt_ta_get_ph(const pt_thragent_t *ta, struct ps_prochandle **ph) -{ - TDBG_FUNC(); - - *ph = ta->ph; - return (TD_OK); -} - -static td_err_e -pt_ta_map_id2thr(const pt_thragent_t *ta, thread_t id, td_thrhandle_t *th) -{ - prgregset_t gregs; - TAILQ_HEAD(, pthread) thread_list; - psaddr_t pt, tcb_addr; - lwpid_t lwp; - int ret; - - TDBG_FUNC(); - - if (id < 0 || id >= ta->map_len || ta->map[id].type == PT_NONE) - return (TD_NOTHR); - ret = ps_pdread(ta->ph, ta->thread_list_addr, &thread_list, - sizeof(thread_list)); - if (ret != 0) - return (P2T(ret)); - pt = (psaddr_t)thread_list.tqh_first; - if (ta->map[id].type == PT_LWP) { - /* - * if we are referencing a lwp, make sure it was not already - * mapped to user thread. - */ - while (pt != 0) { - ret = ps_pdread(ta->ph, - pt + offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - ret = ps_pdread(ta->ph, - tcb_addr + offsetof(struct tcb, - tcb_tmbx.tm_lwp), - &lwp, sizeof(lwp)); - if (ret != 0) - return (P2T(ret)); - /* - * If the lwp was already mapped to userland thread, - * we shouldn't reference it directly in future. - */ - if (lwp == ta->map[id].lwp) { - ta->map[id].type = PT_NONE; - return (TD_NOTHR); - } - /* get next thread */ - ret = ps_pdread(ta->ph, - pt + offsetof(struct pthread, tle.tqe_next), - &pt, sizeof(pt)); - if (ret != 0) - return (P2T(ret)); - } - /* check lwp */ - ret = ptrace(PT_GETREGS, ta->map[id].lwp, (caddr_t)&gregs, 0); - if (ret != 0) { - /* no longer exists */ - ta->map[id].type = PT_NONE; - return (TD_NOTHR); - } - } else { - while (pt != 0 && ta->map[id].thr != pt) { - ret = ps_pdread(ta->ph, - pt + offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - /* get next thread */ - ret = ps_pdread(ta->ph, - pt + offsetof(struct pthread, tle.tqe_next), - &pt, sizeof(pt)); - if (ret != 0) - return (P2T(ret)); - } - - if (pt == 0) { - /* no longer exists */ - ta->map[id].type = PT_NONE; - return (TD_NOTHR); - } - } - th->th_ta_p = (td_thragent_t *)ta; - th->th_unique = id; - return (TD_OK); -} - -static td_err_e -pt_ta_map_lwp2thr(const pt_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th) -{ - TAILQ_HEAD(, pthread) thread_list; - psaddr_t pt, ptr; - lwpid_t tmp_lwp; - int ret; - - TDBG_FUNC(); - - ret = ps_pdread(ta->ph, ta->thread_list_addr, &thread_list, - sizeof(thread_list)); - if (ret != 0) - return (P2T(ret)); - pt = (psaddr_t)thread_list.tqh_first; - while (pt != 0) { - ret = ps_pdread(ta->ph, pt + offsetof(struct pthread, tcb), - &ptr, sizeof(ptr)); - if (ret != 0) - return (P2T(ret)); - ptr += offsetof(struct tcb, tcb_tmbx.tm_lwp); - ret = ps_pdread(ta->ph, ptr, &tmp_lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - if (tmp_lwp == lwp) { - th->th_ta_p = (td_thragent_t *)ta; - th->th_unique = pt_map_thread(ta, pt); - if (th->th_unique == -1) - return (TD_MALLOC); - pt_unmap_lwp(ta, lwp); - return (TD_OK); - } - - /* get next thread */ - ret = ps_pdread(ta->ph, - pt + offsetof(struct pthread, tle.tqe_next), - &pt, sizeof(pt)); - if (ret != 0) - return (P2T(ret)); - } - - return (TD_NOTHR); -} - -static td_err_e -pt_ta_thr_iter(const pt_thragent_t *ta, - td_thr_iter_f *callback, void *cbdata_p, - td_thr_state_e state, int ti_pri, - sigset_t *ti_sigmask_p, - unsigned int ti_user_flags) -{ - TAILQ_HEAD(, pthread) thread_list; - td_thrhandle_t th; - psaddr_t pt; - int ret, activated; - - TDBG_FUNC(); - - ret = pt_ta_activated((pt_thragent_t *)ta, &activated); - if (ret != 0) - return (P2T(ret)); - if (!activated) - return (0); - ret = ps_pdread(ta->ph, ta->thread_list_addr, &thread_list, - sizeof(thread_list)); - if (ret != 0) - return (P2T(ret)); - pt = (psaddr_t)thread_list.tqh_first; - while (pt != 0) { - th.th_ta_p = (td_thragent_t *)ta; - th.th_unique = pt_map_thread(ta, pt); - /* should we unmap lwp here ? */ - if (th.th_unique == -1) - return (TD_MALLOC); - if ((*callback)(&th, cbdata_p)) - return (TD_DBERR); - /* get next thread */ - ret = ps_pdread(ta->ph, - pt + offsetof(struct pthread, tle.tqe_next), - &pt, sizeof(pt)); - if (ret != 0) - return (P2T(ret)); - } - return (TD_OK); -} - -static td_err_e -pt_ta_tsd_iter(const pt_thragent_t *ta, td_key_iter_f *ki, void *arg) -{ - struct pthread_key keytable[PTHREAD_KEYS_MAX]; - int i, ret; - - TDBG_FUNC(); - - ret = ps_pdread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable, - sizeof(keytable)); - if (ret != 0) - return (P2T(ret)); - - for (i = 0; i < PTHREAD_KEYS_MAX; i++) { - if (keytable[i].allocated) { - ret = (ki)(i, keytable[i].destructor, arg); - if (ret != 0) - return (TD_DBERR); - } - } - return (TD_OK); -} - -static td_err_e -pt_ta_event_addr(const pt_thragent_t *ta, td_event_e event, td_notify_t *ptr) -{ - TDBG_FUNC(); - return (TD_NOEVENT); -} - -static td_err_e -pt_ta_set_event(const pt_thragent_t *ta, td_thr_events_t *events) -{ - TDBG_FUNC(); - return (TD_ERR); -} - -static td_err_e -pt_ta_clear_event(const pt_thragent_t *ta, td_thr_events_t *events) -{ - TDBG_FUNC(); - return (TD_ERR); -} - -static td_err_e -pt_ta_event_getmsg(const pt_thragent_t *ta, td_event_msg_t *msg) -{ - TDBG_FUNC(); - return (TD_NOMSG); -} - -static td_err_e -pt_ta_setconcurrency(const pt_thragent_t *ta, int level) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_ta_enable_stats(const pt_thragent_t *ta, int enable) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_ta_reset_stats(const pt_thragent_t *ta) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_ta_get_stats(const pt_thragent_t *ta, td_ta_stats_t *statsp) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_thr_validate(const td_thrhandle_t *th) -{ - td_thrhandle_t temp; - int ret; - - TDBG_FUNC(); - - ret = pt_ta_map_id2thr((pt_thragent_t *)th->th_ta_p, th->th_unique, - &temp); - return (P2T(ret)); -} - -static td_err_e -pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) -{ - struct pthread pt; - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr; - uint32_t dflags; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - memset(info, 0, sizeof(*info)); - if (ta->map[th->th_unique].type == PT_LWP) { - info->ti_type = TD_THR_SYSTEM; - info->ti_lid = ta->map[th->th_unique].lwp; - info->ti_tid = th->th_unique; - info->ti_state = TD_THR_RUN; - info->ti_type = TD_THR_SYSTEM; - return (TD_OK); - } - - ret = ps_pdread(ta->ph, (psaddr_t)(ta->map[th->th_unique].thr), - &pt, sizeof(pt)); - if (ret != 0) - return (P2T(ret)); - if (pt.magic != THR_MAGIC) - return (TD_BADTH); - tcb_addr = (psaddr_t) pt.tcb; - ret = ps_pdread(ta->ph, - tcb_addr + offsetof(struct tcb, tcb_tmbx.tm_lwp), - &info->ti_lid, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - ret = ps_pdread(ta->ph, - tcb_addr + offsetof(struct tcb, tcb_tmbx.tm_dflags), - &dflags, sizeof(dflags)); - info->ti_ta_p = th->th_ta_p; - info->ti_tid = th->th_unique; - info->ti_tls = (char *)pt.specific; - info->ti_startfunc = (psaddr_t)pt.start_routine; - info->ti_stkbase = (psaddr_t) pt.attr.stackaddr_attr; - info->ti_stksize = pt.attr.stacksize_attr; - switch (pt.state) { - case PS_RUNNING: - info->ti_state = TD_THR_RUN; - break; - case PS_LOCKWAIT: - case PS_MUTEX_WAIT: - case PS_COND_WAIT: - case PS_SIGSUSPEND: - case PS_SIGWAIT: - case PS_JOIN: - case PS_SUSPENDED: - case PS_DEADLOCK: - case PS_SLEEP_WAIT: - info->ti_state = TD_THR_SLEEP; - break; - case PS_DEAD: - info->ti_state = TD_THR_ZOMBIE; - break; - default: - info->ti_state = TD_THR_UNKNOWN; - break; - } - - info->ti_db_suspended = ((dflags & TMDF_DONOTRUNUSER) != 0); - info->ti_type = TD_THR_USER; - info->ti_pri = pt.active_priority; - info->ti_sigmask = pt.sigmask; - info->ti_traceme = 0; - info->ti_pending = pt.sigpend; - info->ti_events = 0; - return (0); -} - -static td_err_e -pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) -{ - struct kse_thr_mailbox tmbx; - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr, tmbx_addr, ptr; - lwpid_t lwp; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (ta->map[th->th_unique].type == PT_LWP) { - ret = ps_lgetfpregs(ta->ph, ta->map[th->th_unique].lwp, fpregs); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); - ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); - ret = ps_pdread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - if (lwp != 0) { - ret = ps_lgetfpregs(ta->ph, lwp, fpregs); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - if (ret != 0) - return (P2T(ret)); - pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs); - return (0); -} - -static td_err_e -pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) -{ - struct kse_thr_mailbox tmbx; - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr, tmbx_addr, ptr; - lwpid_t lwp; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (ta->map[th->th_unique].type == PT_LWP) { - ret = ps_lgetregs(ta->ph, - ta->map[th->th_unique].lwp, gregs); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); - ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); - ret = ps_pdread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - if (lwp != 0) { - ret = ps_lgetregs(ta->ph, lwp, gregs); - return (P2T(ret)); - } - ret = ps_pdread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - if (ret != 0) - return (P2T(ret)); - pt_ucontext_to_reg(&tmbx.tm_context, gregs); - return (0); -} - -static td_err_e -pt_thr_getxregs (const td_thrhandle_t *th, void *xregs) -{ - return (TD_NOXREGS); -} - -static td_err_e -pt_thr_getxregsize (const td_thrhandle_t *th, int *sizep) -{ - return (TD_NOXREGS); -} - -static td_err_e -pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) -{ - struct kse_thr_mailbox tmbx; - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr, tmbx_addr, ptr; - lwpid_t lwp; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (ta->map[th->th_unique].type == PT_LWP) { - ret = ps_lsetfpregs(ta->ph, ta->map[th->th_unique].lwp, fpregs); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); - ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); - ret = ps_pdread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - if (lwp != 0) { - ret = ps_lsetfpregs(ta->ph, lwp, fpregs); - return (P2T(ret)); - } - /* - * Read a copy of context, this makes sure that registers - * not covered by structure reg won't be clobbered - */ - ret = ps_pdread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - if (ret != 0) - return (P2T(ret)); - - pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context); - ret = ps_pdwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - return (P2T(ret)); -} - -static td_err_e -pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) -{ - struct kse_thr_mailbox tmbx; - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr, tmbx_addr, ptr; - lwpid_t lwp; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (ta->map[th->th_unique].type == PT_LWP) { - ret = ps_lsetregs(ta->ph, ta->map[th->th_unique].lwp, gregs); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); - ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); - ret = ps_pdread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - if (lwp != 0) { - ret = ps_lsetregs(ta->ph, lwp, gregs); - return (P2T(ret)); - } - - /* - * Read a copy of context, make sure that registers - * not covered by structure reg won't be clobbered - */ - ret = ps_pdread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - if (ret != 0) - return (P2T(ret)); - pt_reg_to_ucontext(gregs, &tmbx.tm_context); - ret = ps_pdwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - return (P2T(ret)); -} - -static td_err_e -pt_thr_setxregs(const td_thrhandle_t *th, const void *addr) -{ - TDBG_FUNC(); - return (TD_NOXREGS); -} - -static td_err_e -pt_thr_event_enable(const td_thrhandle_t *th, int en) -{ - TDBG_FUNC(); - return (TD_ERR); -} - -static td_err_e -pt_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *setp) -{ - TDBG_FUNC(); - return (TD_ERR); -} - -static td_err_e -pt_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *setp) -{ - TDBG_FUNC(); - return (TD_ERR); -} - -static td_err_e -pt_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) -{ - TDBG_FUNC(); - return (TD_NOMSG); -} - -static td_err_e -pt_thr_setprio(const td_thrhandle_t *th, int pri) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_thr_setsigpending(const td_thrhandle_t *th, unsigned char n, - const sigset_t *set) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_thr_sigsetmask(const td_thrhandle_t *th, const sigset_t *set) -{ - TDBG_FUNC(); - return (TD_OK); -} - -static td_err_e -pt_thr_tsd(const td_thrhandle_t *th, const thread_key_t key, void **data) -{ - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - struct pthread_specific_elem *spec, elem; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (key < 0 || key >= PTHREAD_KEYS_MAX) - return (TD_BADKEY); - - if (ta->map[th->th_unique].type == PT_LWP) { - *data = NULL; - return (TD_OK); - } - - ret = ps_pdread(ta->ph, - ta->map[th->th_unique].thr + - offsetof(struct pthread, specific), - &spec, sizeof(spec)); - if (ret == 0) { - if (spec == NULL) { - *data = NULL; - return (0); - } - ret = ps_pdread(ta->ph, (psaddr_t)&spec[key], - &elem, sizeof(elem)); - if (ret == 0) - *data = (void *)elem.data; - } - return (P2T(ret)); -} - -static td_err_e -pt_dbsuspend(const td_thrhandle_t *th, int suspend) -{ - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr, tmbx_addr, ptr; - lwpid_t lwp; - uint32_t dflags; - int attrflags; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (ta->map[th->th_unique].type == PT_LWP) { - if (suspend) - ret = ps_lstop(ta->ph, ta->map[th->th_unique].lwp); - else - ret = ps_lcontinue(ta->ph, ta->map[th->th_unique].lwp); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, attr.flags), - &attrflags, sizeof(attrflags)); - if (ret != 0) - return (P2T(ret)); - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); - ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); - ret = ps_pdread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - /* - * don't stop lwp assigned to a M:N thread, it belongs - * to UTS, UTS shouldn't be stopped. - */ - if (lwp != 0 && (attrflags & PTHREAD_SCOPE_SYSTEM)) { - /* dont' suspend signal thread */ - if (attrflags & THR_SIGNAL_THREAD) - return 0; - if (suspend) - ret = ps_lstop(ta->ph, lwp); - else - ret = ps_lcontinue(ta->ph, lwp); - return (P2T(ret)); - } - - ret = ps_pdread(ta->ph, - tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), - &dflags, sizeof(dflags)); - if (ret != 0) - return (P2T(ret)); - - if (suspend) - dflags |= TMDF_DONOTRUNUSER; - else - dflags &= ~TMDF_DONOTRUNUSER; - ret = ps_pdwrite(ta->ph, - tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags), - &dflags, sizeof(dflags)); - return (P2T(ret)); -} - -static td_err_e -pt_thr_dbsuspend(const td_thrhandle_t *th) -{ - TDBG_FUNC(); - return pt_dbsuspend(th, 1); -} - -static td_err_e -pt_thr_dbresume(const td_thrhandle_t *th) -{ - TDBG_FUNC(); - return pt_dbsuspend(th, 0); -} - -static td_err_e -pt_ta_activated(pt_thragent_t *ta, int *a) -{ - int ret; - - TDBG_FUNC(); - - if (ta->thread_activated) { - *a = ta->thread_activated; - return (TD_OK); - } - ret = ps_pdread(ta->ph, ta->thread_activated_addr, - &ta->thread_activated, sizeof(int)); - if (ret == 0) - *a = ta->thread_activated; - return (P2T(ret)); -} - -static td_err_e -pt_thr_sstep(td_thrhandle_t *th, int step) -{ - struct kse_thr_mailbox tmbx; - struct reg regs; - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - psaddr_t tcb_addr, tmbx_addr; - uint32_t tmp; - lwpid_t lwp; - int ret; - - TDBG_FUNC(); - - ret = pt_validate(th); - if (ret) - return (ret); - - if (ta->map[th->th_unique].type == PT_LWP) { - /* Let debugger deal with single step flag in in kernel */ - return (0); - } - - ret = ps_pdread(ta->ph, ta->map[th->th_unique].thr + - offsetof(struct pthread, tcb), - &tcb_addr, sizeof(tcb_addr)); - if (ret != 0) - return (P2T(ret)); - - /* Clear or set single step flag in thread mailbox */ - tmp = step ? TMDF_SSTEP : 0; - ret = ps_pdwrite(ta->ph, tcb_addr + offsetof(struct tcb, - tcb_tmbx.tm_dflags), &tmp, sizeof(tmp)); - if (ret != 0) - return (P2T(ret)); - /* Get lwp */ - ret = ps_pdread(ta->ph, tcb_addr + offsetof(struct tcb, - tcb_tmbx.tm_lwp), &lwp, sizeof(lwpid_t)); - if (ret != 0) - return (P2T(ret)); - if (lwp != 0) /* Let debugger deal with single step flag in in kernel */ - return (0); - - tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); - /* - * context is in userland, some architectures store - * single step status in registers, we should change - * these registers. - */ - ret = ps_pdread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); - if (ret == 0) { - pt_ucontext_to_reg(&tmbx.tm_context, ®s); - /* only write out if it is really changed. */ - if (pt_reg_sstep(®s, step) != 0) { - pt_reg_to_ucontext(®s, &tmbx.tm_context); - ret = ps_pdwrite(ta->ph, tmbx_addr, &tmbx, - sizeof(tmbx)); - } - } - return (P2T(ret)); -} - -static long -_map_thread(pt_thragent_t *ta, psaddr_t pt, int type) -{ - struct pt_map *new; - int i, first = -1; - - /* leave zero out */ - for (i = 1; i < ta->map_len; ++i) { - if (ta->map[i].type == PT_NONE) { - if (first == -1) - first = i; - } else if (ta->map[i].type == type && ta->map[i].thr == pt) { - return (i); - } - } - - if (first == -1) { - if (ta->map_len == 0) { - ta->map = calloc(20, sizeof(struct pt_map)); - if (ta->map == NULL) - return (-1); - ta->map_len = 20; - first = 1; - } else { - new = realloc(ta->map, - sizeof(struct pt_map) * ta->map_len * 2); - if (new == NULL) - return (-1); - memset(new + ta->map_len, '\0', sizeof(struct pt_map) * - ta->map_len); - first = ta->map_len; - ta->map = new; - ta->map_len *= 2; - } - } - - ta->map[first].type = type; - ta->map[first].thr = pt; - return (first); -} - -static long -pt_map_thread(const pt_thragent_t *ta, psaddr_t pt) -{ - return _map_thread((pt_thragent_t *)ta, pt, PT_USER); -} - -#if 0 -static long -pt_map_lwp(const pt_thragent_t *ta, lwpid_t lwp) -{ - return _map_thread((pt_thragent_t *)ta, (psaddr_t)lwp, PT_LWP); -} -#endif - -static void -pt_unmap_lwp(const pt_thragent_t *ta, lwpid_t lwp) -{ - int i; - - for (i = 0; i < ta->map_len; ++i) { - if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) { - ta->map[i].type = PT_NONE; - return; - } - } -} - -static int -pt_validate(const td_thrhandle_t *th) -{ - pt_thragent_t *ta = (pt_thragent_t *)th->th_ta_p; - - if (th->th_unique < 0 || th->th_unique >= ta->map_len || - ta->map[th->th_unique].type == PT_NONE) - return (TD_NOTHR); - return (TD_OK); -} - -struct ta_ops pthread_ops = { - .to_init = pt_init, - .to_ta_new = (void *)pt_ta_new, - .to_ta_delete = (void *)pt_ta_delete, - .to_ta_get_nthreads = (void *)pt_ta_get_nthreads, - .to_ta_get_ph = (void *)pt_ta_get_ph, - .to_ta_map_id2thr = (void *)pt_ta_map_id2thr, - .to_ta_map_lwp2thr = (void *)pt_ta_map_lwp2thr, - .to_ta_thr_iter = (void *)pt_ta_thr_iter, - .to_ta_tsd_iter = (void *)pt_ta_tsd_iter, - .to_ta_event_addr = (void *)pt_ta_event_addr, - .to_ta_set_event = (void *)pt_ta_set_event, - .to_ta_clear_event = (void *)pt_ta_clear_event, - .to_ta_event_getmsg = (void *)pt_ta_event_getmsg, - .to_ta_setconcurrency = (void *)pt_ta_setconcurrency, - .to_ta_enable_stats = (void *)pt_ta_enable_stats, - .to_ta_reset_stats = (void *)pt_ta_reset_stats, - .to_ta_get_stats = (void *)pt_ta_get_stats, - .to_thr_validate = pt_thr_validate, - .to_thr_get_info = pt_thr_get_info, - .to_thr_getfpregs = (void *)pt_thr_getfpregs, - .to_thr_getgregs = pt_thr_getgregs, - .to_thr_getxregs = pt_thr_getxregs, - .to_thr_getxregsize = pt_thr_getxregsize, - .to_thr_setfpregs = pt_thr_setfpregs, - .to_thr_setgregs = pt_thr_setgregs, - .to_thr_setxregs = pt_thr_setxregs, - .to_thr_event_enable = pt_thr_event_enable, - .to_thr_set_event = pt_thr_set_event, - .to_thr_clear_event = pt_thr_clear_event, - .to_thr_event_getmsg = pt_thr_event_getmsg, - .to_thr_setprio = pt_thr_setprio, - .to_thr_setsigpending = pt_thr_setsigpending, - .to_thr_sigsetmask = pt_thr_sigsetmask, - .to_thr_tsd = pt_thr_tsd, - .to_thr_dbsuspend = pt_thr_dbsuspend, - .to_thr_dbresume = pt_thr_dbresume, - .to_ta_activated = (void *)pt_ta_activated, - .to_thr_sstep = pt_thr_sstep -}; |