1*3c1e38eaSMarcel Moolenaar /* 2*3c1e38eaSMarcel Moolenaar * Copyright (c) 2004 David Xu <[email protected]> 3*3c1e38eaSMarcel Moolenaar * All rights reserved. 4*3c1e38eaSMarcel Moolenaar * 5*3c1e38eaSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 6*3c1e38eaSMarcel Moolenaar * modification, are permitted provided that the following conditions 7*3c1e38eaSMarcel Moolenaar * are met: 8*3c1e38eaSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 9*3c1e38eaSMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 10*3c1e38eaSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 11*3c1e38eaSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 12*3c1e38eaSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 13*3c1e38eaSMarcel Moolenaar * 14*3c1e38eaSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*3c1e38eaSMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*3c1e38eaSMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*3c1e38eaSMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*3c1e38eaSMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*3c1e38eaSMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*3c1e38eaSMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*3c1e38eaSMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*3c1e38eaSMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*3c1e38eaSMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*3c1e38eaSMarcel Moolenaar * SUCH DAMAGE. 25*3c1e38eaSMarcel Moolenaar */ 26*3c1e38eaSMarcel Moolenaar 27*3c1e38eaSMarcel Moolenaar #include <sys/cdefs.h> 28*3c1e38eaSMarcel Moolenaar __FBSDID("$FreeBSD$"); 29*3c1e38eaSMarcel Moolenaar 30*3c1e38eaSMarcel Moolenaar #include <stddef.h> 31*3c1e38eaSMarcel Moolenaar #include <stdlib.h> 32*3c1e38eaSMarcel Moolenaar #include <string.h> 33*3c1e38eaSMarcel Moolenaar #include <unistd.h> 34*3c1e38eaSMarcel Moolenaar #include <pthread.h> 35*3c1e38eaSMarcel Moolenaar #include <sys/types.h> 36*3c1e38eaSMarcel Moolenaar #include <sys/kse.h> 37*3c1e38eaSMarcel Moolenaar #include <sys/ptrace.h> 38*3c1e38eaSMarcel Moolenaar #include <proc_service.h> 39*3c1e38eaSMarcel Moolenaar #include <thread_db.h> 40*3c1e38eaSMarcel Moolenaar 41*3c1e38eaSMarcel Moolenaar #include "libpthread.h" 42*3c1e38eaSMarcel Moolenaar #include "libpthread_db.h" 43*3c1e38eaSMarcel Moolenaar 44*3c1e38eaSMarcel Moolenaar #define P2T(c) ps2td(c) 45*3c1e38eaSMarcel Moolenaar 46*3c1e38eaSMarcel Moolenaar static void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp); 47*3c1e38eaSMarcel Moolenaar static int pt_validate(const td_thrhandle_t *th); 48*3c1e38eaSMarcel Moolenaar 49*3c1e38eaSMarcel Moolenaar static int 50*3c1e38eaSMarcel Moolenaar ps2td(int c) 51*3c1e38eaSMarcel Moolenaar { 52*3c1e38eaSMarcel Moolenaar switch (c) { 53*3c1e38eaSMarcel Moolenaar case PS_OK: 54*3c1e38eaSMarcel Moolenaar return TD_OK; 55*3c1e38eaSMarcel Moolenaar case PS_ERR: 56*3c1e38eaSMarcel Moolenaar return TD_ERR; 57*3c1e38eaSMarcel Moolenaar case PS_BADPID: 58*3c1e38eaSMarcel Moolenaar return TD_BADPH; 59*3c1e38eaSMarcel Moolenaar case PS_BADLID: 60*3c1e38eaSMarcel Moolenaar return TD_NOLWP; 61*3c1e38eaSMarcel Moolenaar case PS_BADADDR: 62*3c1e38eaSMarcel Moolenaar return TD_ERR; 63*3c1e38eaSMarcel Moolenaar case PS_NOSYM: 64*3c1e38eaSMarcel Moolenaar return TD_NOLIBTHREAD; 65*3c1e38eaSMarcel Moolenaar case PS_NOFREGS: 66*3c1e38eaSMarcel Moolenaar return TD_NOFPREGS; 67*3c1e38eaSMarcel Moolenaar default: 68*3c1e38eaSMarcel Moolenaar return TD_ERR; 69*3c1e38eaSMarcel Moolenaar } 70*3c1e38eaSMarcel Moolenaar } 71*3c1e38eaSMarcel Moolenaar 72*3c1e38eaSMarcel Moolenaar static long 73*3c1e38eaSMarcel Moolenaar pt_map_thread(const td_thragent_t *const_ta, psaddr_t pt, int type) 74*3c1e38eaSMarcel Moolenaar { 75*3c1e38eaSMarcel Moolenaar td_thragent_t *ta = __DECONST(td_thragent_t *, const_ta); 76*3c1e38eaSMarcel Moolenaar struct pt_map *new; 77*3c1e38eaSMarcel Moolenaar int i, first = -1; 78*3c1e38eaSMarcel Moolenaar 79*3c1e38eaSMarcel Moolenaar /* leave zero out */ 80*3c1e38eaSMarcel Moolenaar for (i = 1; i < ta->map_len; ++i) { 81*3c1e38eaSMarcel Moolenaar if (ta->map[i].type == PT_NONE) { 82*3c1e38eaSMarcel Moolenaar if (first == -1) 83*3c1e38eaSMarcel Moolenaar first = i; 84*3c1e38eaSMarcel Moolenaar } else if (ta->map[i].type == type && ta->map[i].thr == pt) { 85*3c1e38eaSMarcel Moolenaar return (i); 86*3c1e38eaSMarcel Moolenaar } 87*3c1e38eaSMarcel Moolenaar } 88*3c1e38eaSMarcel Moolenaar 89*3c1e38eaSMarcel Moolenaar if (first == -1) { 90*3c1e38eaSMarcel Moolenaar if (ta->map_len == 0) { 91*3c1e38eaSMarcel Moolenaar ta->map = calloc(20, sizeof(struct pt_map)); 92*3c1e38eaSMarcel Moolenaar if (ta->map == NULL) 93*3c1e38eaSMarcel Moolenaar return (-1); 94*3c1e38eaSMarcel Moolenaar ta->map_len = 20; 95*3c1e38eaSMarcel Moolenaar first = 1; 96*3c1e38eaSMarcel Moolenaar } else { 97*3c1e38eaSMarcel Moolenaar new = realloc(ta->map, 98*3c1e38eaSMarcel Moolenaar sizeof(struct pt_map) * ta->map_len * 2); 99*3c1e38eaSMarcel Moolenaar if (new == NULL) 100*3c1e38eaSMarcel Moolenaar return (-1); 101*3c1e38eaSMarcel Moolenaar memset(new + ta->map_len, '\0', sizeof(struct pt_map) * 102*3c1e38eaSMarcel Moolenaar ta->map_len); 103*3c1e38eaSMarcel Moolenaar first = ta->map_len; 104*3c1e38eaSMarcel Moolenaar ta->map = new; 105*3c1e38eaSMarcel Moolenaar ta->map_len *= 2; 106*3c1e38eaSMarcel Moolenaar } 107*3c1e38eaSMarcel Moolenaar } 108*3c1e38eaSMarcel Moolenaar 109*3c1e38eaSMarcel Moolenaar ta->map[first].type = type; 110*3c1e38eaSMarcel Moolenaar ta->map[first].thr = pt; 111*3c1e38eaSMarcel Moolenaar return (first); 112*3c1e38eaSMarcel Moolenaar } 113*3c1e38eaSMarcel Moolenaar 114*3c1e38eaSMarcel Moolenaar static td_err_e 115*3c1e38eaSMarcel Moolenaar pt_init(void) 116*3c1e38eaSMarcel Moolenaar { 117*3c1e38eaSMarcel Moolenaar pt_md_init(); 118*3c1e38eaSMarcel Moolenaar return (0); 119*3c1e38eaSMarcel Moolenaar } 120*3c1e38eaSMarcel Moolenaar 121*3c1e38eaSMarcel Moolenaar static td_err_e 122*3c1e38eaSMarcel Moolenaar pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 123*3c1e38eaSMarcel Moolenaar { 124*3c1e38eaSMarcel Moolenaar #define LOOKUP_SYM(proc, sym, addr) \ 125*3c1e38eaSMarcel Moolenaar ret = ps_pglobal_lookup(proc, NULL, sym, addr); \ 126*3c1e38eaSMarcel Moolenaar if (ret != 0) { \ 127*3c1e38eaSMarcel Moolenaar TDBG("can not find symbol: %s\n", sym); \ 128*3c1e38eaSMarcel Moolenaar ret = TD_NOLIBTHREAD; \ 129*3c1e38eaSMarcel Moolenaar goto error; \ 130*3c1e38eaSMarcel Moolenaar } 131*3c1e38eaSMarcel Moolenaar 132*3c1e38eaSMarcel Moolenaar td_thragent_t *ta; 133*3c1e38eaSMarcel Moolenaar int dbg; 134*3c1e38eaSMarcel Moolenaar int ret; 135*3c1e38eaSMarcel Moolenaar 136*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 137*3c1e38eaSMarcel Moolenaar 138*3c1e38eaSMarcel Moolenaar ta = malloc(sizeof(td_thragent_t)); 139*3c1e38eaSMarcel Moolenaar if (ta == NULL) 140*3c1e38eaSMarcel Moolenaar return (TD_MALLOC); 141*3c1e38eaSMarcel Moolenaar 142*3c1e38eaSMarcel Moolenaar ta->ph = ph; 143*3c1e38eaSMarcel Moolenaar ta->thread_activated = 0; 144*3c1e38eaSMarcel Moolenaar ta->map = NULL; 145*3c1e38eaSMarcel Moolenaar ta->map_len = 0; 146*3c1e38eaSMarcel Moolenaar 147*3c1e38eaSMarcel Moolenaar LOOKUP_SYM(ph, "_libkse_debug", &ta->libkse_debug_addr); 148*3c1e38eaSMarcel Moolenaar LOOKUP_SYM(ph, "_thread_list", &ta->thread_list_addr); 149*3c1e38eaSMarcel Moolenaar LOOKUP_SYM(ph, "_thread_activated", &ta->thread_activated_addr); 150*3c1e38eaSMarcel Moolenaar LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr); 151*3c1e38eaSMarcel Moolenaar LOOKUP_SYM(ph, "_thread_keytable", &ta->thread_keytable_addr); 152*3c1e38eaSMarcel Moolenaar 153*3c1e38eaSMarcel Moolenaar dbg = getpid(); 154*3c1e38eaSMarcel Moolenaar /* 155*3c1e38eaSMarcel Moolenaar * If this fails it probably means we're debugging a core file and 156*3c1e38eaSMarcel Moolenaar * can't write to it. 157*3c1e38eaSMarcel Moolenaar */ 158*3c1e38eaSMarcel Moolenaar ps_pwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int)); 159*3c1e38eaSMarcel Moolenaar *pta = ta; 160*3c1e38eaSMarcel Moolenaar return (0); 161*3c1e38eaSMarcel Moolenaar 162*3c1e38eaSMarcel Moolenaar error: 163*3c1e38eaSMarcel Moolenaar free(ta); 164*3c1e38eaSMarcel Moolenaar return (ret); 165*3c1e38eaSMarcel Moolenaar } 166*3c1e38eaSMarcel Moolenaar 167*3c1e38eaSMarcel Moolenaar static td_err_e 168*3c1e38eaSMarcel Moolenaar pt_ta_delete(td_thragent_t *ta) 169*3c1e38eaSMarcel Moolenaar { 170*3c1e38eaSMarcel Moolenaar int dbg; 171*3c1e38eaSMarcel Moolenaar 172*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 173*3c1e38eaSMarcel Moolenaar 174*3c1e38eaSMarcel Moolenaar dbg = 0; 175*3c1e38eaSMarcel Moolenaar /* 176*3c1e38eaSMarcel Moolenaar * Error returns from this write are not really a problem; 177*3c1e38eaSMarcel Moolenaar * the process doesn't exist any more. 178*3c1e38eaSMarcel Moolenaar */ 179*3c1e38eaSMarcel Moolenaar ps_pwrite(ta->ph, ta->libkse_debug_addr, &dbg, sizeof(int)); 180*3c1e38eaSMarcel Moolenaar if (ta->map) 181*3c1e38eaSMarcel Moolenaar free(ta->map); 182*3c1e38eaSMarcel Moolenaar free(ta); 183*3c1e38eaSMarcel Moolenaar return (TD_OK); 184*3c1e38eaSMarcel Moolenaar } 185*3c1e38eaSMarcel Moolenaar 186*3c1e38eaSMarcel Moolenaar static td_err_e 187*3c1e38eaSMarcel Moolenaar pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 188*3c1e38eaSMarcel Moolenaar { 189*3c1e38eaSMarcel Moolenaar prgregset_t gregs; 190*3c1e38eaSMarcel Moolenaar TAILQ_HEAD(, pthread) thread_list; 191*3c1e38eaSMarcel Moolenaar psaddr_t pt, tcb_addr; 192*3c1e38eaSMarcel Moolenaar lwpid_t lwp; 193*3c1e38eaSMarcel Moolenaar int ret; 194*3c1e38eaSMarcel Moolenaar 195*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 196*3c1e38eaSMarcel Moolenaar 197*3c1e38eaSMarcel Moolenaar if (id < 0 || id >= ta->map_len || ta->map[id].type == PT_NONE) 198*3c1e38eaSMarcel Moolenaar return (TD_NOTHR); 199*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 200*3c1e38eaSMarcel Moolenaar sizeof(thread_list)); 201*3c1e38eaSMarcel Moolenaar if (ret != 0) 202*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 203*3c1e38eaSMarcel Moolenaar pt = (psaddr_t)thread_list.tqh_first; 204*3c1e38eaSMarcel Moolenaar if (ta->map[id].type == PT_LWP) { 205*3c1e38eaSMarcel Moolenaar /* 206*3c1e38eaSMarcel Moolenaar * if we are referencing a lwp, make sure it was not already 207*3c1e38eaSMarcel Moolenaar * mapped to user thread. 208*3c1e38eaSMarcel Moolenaar */ 209*3c1e38eaSMarcel Moolenaar while (pt != 0) { 210*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 211*3c1e38eaSMarcel Moolenaar pt + offsetof(struct pthread, tcb), 212*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 213*3c1e38eaSMarcel Moolenaar if (ret != 0) 214*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 215*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 216*3c1e38eaSMarcel Moolenaar tcb_addr + offsetof(struct tcb, 217*3c1e38eaSMarcel Moolenaar tcb_tmbx.tm_lwp), 218*3c1e38eaSMarcel Moolenaar &lwp, sizeof(lwp)); 219*3c1e38eaSMarcel Moolenaar if (ret != 0) 220*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 221*3c1e38eaSMarcel Moolenaar /* 222*3c1e38eaSMarcel Moolenaar * If the lwp was already mapped to userland thread, 223*3c1e38eaSMarcel Moolenaar * we shouldn't reference it directly in future. 224*3c1e38eaSMarcel Moolenaar */ 225*3c1e38eaSMarcel Moolenaar if (lwp == ta->map[id].lwp) { 226*3c1e38eaSMarcel Moolenaar ta->map[id].type = PT_NONE; 227*3c1e38eaSMarcel Moolenaar return (TD_NOTHR); 228*3c1e38eaSMarcel Moolenaar } 229*3c1e38eaSMarcel Moolenaar /* get next thread */ 230*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 231*3c1e38eaSMarcel Moolenaar pt + offsetof(struct pthread, tle.tqe_next), 232*3c1e38eaSMarcel Moolenaar &pt, sizeof(pt)); 233*3c1e38eaSMarcel Moolenaar if (ret != 0) 234*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 235*3c1e38eaSMarcel Moolenaar } 236*3c1e38eaSMarcel Moolenaar /* check lwp */ 237*3c1e38eaSMarcel Moolenaar ret = ptrace(PT_GETREGS, ta->map[id].lwp, (caddr_t)&gregs, 0); 238*3c1e38eaSMarcel Moolenaar if (ret != 0) { 239*3c1e38eaSMarcel Moolenaar /* no longer exists */ 240*3c1e38eaSMarcel Moolenaar ta->map[id].type = PT_NONE; 241*3c1e38eaSMarcel Moolenaar return (TD_NOTHR); 242*3c1e38eaSMarcel Moolenaar } 243*3c1e38eaSMarcel Moolenaar } else { 244*3c1e38eaSMarcel Moolenaar while (pt != 0 && ta->map[id].thr != pt) { 245*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 246*3c1e38eaSMarcel Moolenaar pt + offsetof(struct pthread, tcb), 247*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 248*3c1e38eaSMarcel Moolenaar if (ret != 0) 249*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 250*3c1e38eaSMarcel Moolenaar /* get next thread */ 251*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 252*3c1e38eaSMarcel Moolenaar pt + offsetof(struct pthread, tle.tqe_next), 253*3c1e38eaSMarcel Moolenaar &pt, sizeof(pt)); 254*3c1e38eaSMarcel Moolenaar if (ret != 0) 255*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 256*3c1e38eaSMarcel Moolenaar } 257*3c1e38eaSMarcel Moolenaar 258*3c1e38eaSMarcel Moolenaar if (pt == 0) { 259*3c1e38eaSMarcel Moolenaar /* no longer exists */ 260*3c1e38eaSMarcel Moolenaar ta->map[id].type = PT_NONE; 261*3c1e38eaSMarcel Moolenaar return (TD_NOTHR); 262*3c1e38eaSMarcel Moolenaar } 263*3c1e38eaSMarcel Moolenaar } 264*3c1e38eaSMarcel Moolenaar th->th_ta = ta; 265*3c1e38eaSMarcel Moolenaar th->th_tid = id; 266*3c1e38eaSMarcel Moolenaar return (TD_OK); 267*3c1e38eaSMarcel Moolenaar } 268*3c1e38eaSMarcel Moolenaar 269*3c1e38eaSMarcel Moolenaar static td_err_e 270*3c1e38eaSMarcel Moolenaar pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th) 271*3c1e38eaSMarcel Moolenaar { 272*3c1e38eaSMarcel Moolenaar TAILQ_HEAD(, pthread) thread_list; 273*3c1e38eaSMarcel Moolenaar psaddr_t pt, ptr; 274*3c1e38eaSMarcel Moolenaar lwpid_t tmp_lwp; 275*3c1e38eaSMarcel Moolenaar int ret; 276*3c1e38eaSMarcel Moolenaar 277*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 278*3c1e38eaSMarcel Moolenaar 279*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 280*3c1e38eaSMarcel Moolenaar sizeof(thread_list)); 281*3c1e38eaSMarcel Moolenaar if (ret != 0) 282*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 283*3c1e38eaSMarcel Moolenaar pt = (psaddr_t)thread_list.tqh_first; 284*3c1e38eaSMarcel Moolenaar while (pt != 0) { 285*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, pt + offsetof(struct pthread, tcb), 286*3c1e38eaSMarcel Moolenaar &ptr, sizeof(ptr)); 287*3c1e38eaSMarcel Moolenaar if (ret != 0) 288*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 289*3c1e38eaSMarcel Moolenaar ptr += offsetof(struct tcb, tcb_tmbx.tm_lwp); 290*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ptr, &tmp_lwp, sizeof(lwpid_t)); 291*3c1e38eaSMarcel Moolenaar if (ret != 0) 292*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 293*3c1e38eaSMarcel Moolenaar if (tmp_lwp == lwp) { 294*3c1e38eaSMarcel Moolenaar th->th_ta = ta; 295*3c1e38eaSMarcel Moolenaar th->th_tid = pt_map_thread(ta, pt, PT_USER); 296*3c1e38eaSMarcel Moolenaar if (th->th_tid == -1) 297*3c1e38eaSMarcel Moolenaar return (TD_MALLOC); 298*3c1e38eaSMarcel Moolenaar pt_unmap_lwp(ta, lwp); 299*3c1e38eaSMarcel Moolenaar return (TD_OK); 300*3c1e38eaSMarcel Moolenaar } 301*3c1e38eaSMarcel Moolenaar 302*3c1e38eaSMarcel Moolenaar /* get next thread */ 303*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 304*3c1e38eaSMarcel Moolenaar pt + offsetof(struct pthread, tle.tqe_next), 305*3c1e38eaSMarcel Moolenaar &pt, sizeof(pt)); 306*3c1e38eaSMarcel Moolenaar if (ret != 0) 307*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 308*3c1e38eaSMarcel Moolenaar } 309*3c1e38eaSMarcel Moolenaar 310*3c1e38eaSMarcel Moolenaar return (TD_NOTHR); 311*3c1e38eaSMarcel Moolenaar } 312*3c1e38eaSMarcel Moolenaar 313*3c1e38eaSMarcel Moolenaar static td_err_e 314*3c1e38eaSMarcel Moolenaar pt_ta_thr_iter(const td_thragent_t *ta, 315*3c1e38eaSMarcel Moolenaar td_thr_iter_f *callback, void *cbdata_p, 316*3c1e38eaSMarcel Moolenaar td_thr_state_e state, int ti_pri, 317*3c1e38eaSMarcel Moolenaar sigset_t *ti_sigmask_p, 318*3c1e38eaSMarcel Moolenaar unsigned int ti_user_flags) 319*3c1e38eaSMarcel Moolenaar { 320*3c1e38eaSMarcel Moolenaar TAILQ_HEAD(, pthread) thread_list; 321*3c1e38eaSMarcel Moolenaar td_thrhandle_t th; 322*3c1e38eaSMarcel Moolenaar psaddr_t pt; 323*3c1e38eaSMarcel Moolenaar ps_err_e pserr; 324*3c1e38eaSMarcel Moolenaar int activated; 325*3c1e38eaSMarcel Moolenaar 326*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 327*3c1e38eaSMarcel Moolenaar 328*3c1e38eaSMarcel Moolenaar pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated, 329*3c1e38eaSMarcel Moolenaar sizeof(int)); 330*3c1e38eaSMarcel Moolenaar if (pserr != PS_OK) 331*3c1e38eaSMarcel Moolenaar return (P2T(pserr)); 332*3c1e38eaSMarcel Moolenaar if (!activated) 333*3c1e38eaSMarcel Moolenaar return (TD_OK); 334*3c1e38eaSMarcel Moolenaar 335*3c1e38eaSMarcel Moolenaar pserr = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, 336*3c1e38eaSMarcel Moolenaar sizeof(thread_list)); 337*3c1e38eaSMarcel Moolenaar if (pserr != 0) 338*3c1e38eaSMarcel Moolenaar return (P2T(pserr)); 339*3c1e38eaSMarcel Moolenaar pt = (psaddr_t)thread_list.tqh_first; 340*3c1e38eaSMarcel Moolenaar while (pt != 0) { 341*3c1e38eaSMarcel Moolenaar th.th_ta = ta; 342*3c1e38eaSMarcel Moolenaar th.th_tid = pt_map_thread(ta, pt, PT_USER); 343*3c1e38eaSMarcel Moolenaar /* should we unmap lwp here ? */ 344*3c1e38eaSMarcel Moolenaar if (th.th_tid == -1) 345*3c1e38eaSMarcel Moolenaar return (TD_MALLOC); 346*3c1e38eaSMarcel Moolenaar if ((*callback)(&th, cbdata_p)) 347*3c1e38eaSMarcel Moolenaar return (TD_DBERR); 348*3c1e38eaSMarcel Moolenaar /* get next thread */ 349*3c1e38eaSMarcel Moolenaar pserr = ps_pread(ta->ph, 350*3c1e38eaSMarcel Moolenaar pt + offsetof(struct pthread, tle.tqe_next), &pt, 351*3c1e38eaSMarcel Moolenaar sizeof(pt)); 352*3c1e38eaSMarcel Moolenaar if (pserr != PS_OK) 353*3c1e38eaSMarcel Moolenaar return (P2T(pserr)); 354*3c1e38eaSMarcel Moolenaar } 355*3c1e38eaSMarcel Moolenaar return (TD_OK); 356*3c1e38eaSMarcel Moolenaar } 357*3c1e38eaSMarcel Moolenaar 358*3c1e38eaSMarcel Moolenaar static td_err_e 359*3c1e38eaSMarcel Moolenaar pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg) 360*3c1e38eaSMarcel Moolenaar { 361*3c1e38eaSMarcel Moolenaar struct pthread_key keytable[PTHREAD_KEYS_MAX]; 362*3c1e38eaSMarcel Moolenaar int i, ret; 363*3c1e38eaSMarcel Moolenaar 364*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 365*3c1e38eaSMarcel Moolenaar 366*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable, 367*3c1e38eaSMarcel Moolenaar sizeof(keytable)); 368*3c1e38eaSMarcel Moolenaar if (ret != 0) 369*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 370*3c1e38eaSMarcel Moolenaar 371*3c1e38eaSMarcel Moolenaar for (i = 0; i < PTHREAD_KEYS_MAX; i++) { 372*3c1e38eaSMarcel Moolenaar if (keytable[i].allocated) { 373*3c1e38eaSMarcel Moolenaar ret = (ki)(i, keytable[i].destructor, arg); 374*3c1e38eaSMarcel Moolenaar if (ret != 0) 375*3c1e38eaSMarcel Moolenaar return (TD_DBERR); 376*3c1e38eaSMarcel Moolenaar } 377*3c1e38eaSMarcel Moolenaar } 378*3c1e38eaSMarcel Moolenaar return (TD_OK); 379*3c1e38eaSMarcel Moolenaar } 380*3c1e38eaSMarcel Moolenaar 381*3c1e38eaSMarcel Moolenaar static td_err_e 382*3c1e38eaSMarcel Moolenaar pt_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 383*3c1e38eaSMarcel Moolenaar { 384*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 385*3c1e38eaSMarcel Moolenaar return (TD_NOEVENT); 386*3c1e38eaSMarcel Moolenaar } 387*3c1e38eaSMarcel Moolenaar 388*3c1e38eaSMarcel Moolenaar static td_err_e 389*3c1e38eaSMarcel Moolenaar pt_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 390*3c1e38eaSMarcel Moolenaar { 391*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 392*3c1e38eaSMarcel Moolenaar return (TD_ERR); 393*3c1e38eaSMarcel Moolenaar } 394*3c1e38eaSMarcel Moolenaar 395*3c1e38eaSMarcel Moolenaar static td_err_e 396*3c1e38eaSMarcel Moolenaar pt_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 397*3c1e38eaSMarcel Moolenaar { 398*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 399*3c1e38eaSMarcel Moolenaar return (TD_ERR); 400*3c1e38eaSMarcel Moolenaar } 401*3c1e38eaSMarcel Moolenaar 402*3c1e38eaSMarcel Moolenaar static td_err_e 403*3c1e38eaSMarcel Moolenaar pt_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 404*3c1e38eaSMarcel Moolenaar { 405*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 406*3c1e38eaSMarcel Moolenaar return (TD_NOMSG); 407*3c1e38eaSMarcel Moolenaar } 408*3c1e38eaSMarcel Moolenaar 409*3c1e38eaSMarcel Moolenaar static td_err_e 410*3c1e38eaSMarcel Moolenaar pt_thr_dbresume(const td_thrhandle_t *th) 411*3c1e38eaSMarcel Moolenaar { 412*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 413*3c1e38eaSMarcel Moolenaar return (TD_ERR); 414*3c1e38eaSMarcel Moolenaar } 415*3c1e38eaSMarcel Moolenaar 416*3c1e38eaSMarcel Moolenaar static td_err_e 417*3c1e38eaSMarcel Moolenaar pt_thr_dbsuspend(const td_thrhandle_t *th) 418*3c1e38eaSMarcel Moolenaar { 419*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 420*3c1e38eaSMarcel Moolenaar return (TD_ERR); 421*3c1e38eaSMarcel Moolenaar } 422*3c1e38eaSMarcel Moolenaar 423*3c1e38eaSMarcel Moolenaar static td_err_e 424*3c1e38eaSMarcel Moolenaar pt_thr_validate(const td_thrhandle_t *th) 425*3c1e38eaSMarcel Moolenaar { 426*3c1e38eaSMarcel Moolenaar td_thrhandle_t temp; 427*3c1e38eaSMarcel Moolenaar int ret; 428*3c1e38eaSMarcel Moolenaar 429*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 430*3c1e38eaSMarcel Moolenaar 431*3c1e38eaSMarcel Moolenaar ret = pt_ta_map_id2thr(th->th_ta, th->th_tid, 432*3c1e38eaSMarcel Moolenaar &temp); 433*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 434*3c1e38eaSMarcel Moolenaar } 435*3c1e38eaSMarcel Moolenaar 436*3c1e38eaSMarcel Moolenaar static td_err_e 437*3c1e38eaSMarcel Moolenaar pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 438*3c1e38eaSMarcel Moolenaar { 439*3c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 440*3c1e38eaSMarcel Moolenaar struct pthread pt; 441*3c1e38eaSMarcel Moolenaar int ret; 442*3c1e38eaSMarcel Moolenaar 443*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 444*3c1e38eaSMarcel Moolenaar 445*3c1e38eaSMarcel Moolenaar ret = pt_validate(th); 446*3c1e38eaSMarcel Moolenaar if (ret) 447*3c1e38eaSMarcel Moolenaar return (ret); 448*3c1e38eaSMarcel Moolenaar 449*3c1e38eaSMarcel Moolenaar memset(info, 0, sizeof(*info)); 450*3c1e38eaSMarcel Moolenaar if (ta->map[th->th_tid].type == PT_LWP) { 451*3c1e38eaSMarcel Moolenaar info->ti_type = TD_THR_SYSTEM; 452*3c1e38eaSMarcel Moolenaar info->ti_lid = ta->map[th->th_tid].lwp; 453*3c1e38eaSMarcel Moolenaar info->ti_tid = th->th_tid; 454*3c1e38eaSMarcel Moolenaar info->ti_state = TD_THR_RUN; 455*3c1e38eaSMarcel Moolenaar info->ti_type = TD_THR_SYSTEM; 456*3c1e38eaSMarcel Moolenaar return (TD_OK); 457*3c1e38eaSMarcel Moolenaar } 458*3c1e38eaSMarcel Moolenaar 459*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, (psaddr_t)(ta->map[th->th_tid].thr), 460*3c1e38eaSMarcel Moolenaar &pt, sizeof(pt)); 461*3c1e38eaSMarcel Moolenaar if (ret != 0) 462*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 463*3c1e38eaSMarcel Moolenaar if (pt.magic != THR_MAGIC) 464*3c1e38eaSMarcel Moolenaar return (TD_BADTH); 465*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, 466*3c1e38eaSMarcel Moolenaar ((psaddr_t)pt.tcb) + offsetof(struct tcb, tcb_tmbx.tm_lwp), 467*3c1e38eaSMarcel Moolenaar &info->ti_lid, sizeof(lwpid_t)); 468*3c1e38eaSMarcel Moolenaar if (ret != 0) 469*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 470*3c1e38eaSMarcel Moolenaar 471*3c1e38eaSMarcel Moolenaar info->ti_ta_p = th->th_ta; 472*3c1e38eaSMarcel Moolenaar info->ti_tid = th->th_tid; 473*3c1e38eaSMarcel Moolenaar info->ti_tls = (char *)pt.specific; 474*3c1e38eaSMarcel Moolenaar info->ti_startfunc = (psaddr_t)pt.start_routine; 475*3c1e38eaSMarcel Moolenaar info->ti_stkbase = (psaddr_t) pt.attr.stackaddr_attr; 476*3c1e38eaSMarcel Moolenaar info->ti_stksize = pt.attr.stacksize_attr; 477*3c1e38eaSMarcel Moolenaar switch (pt.state) { 478*3c1e38eaSMarcel Moolenaar case PS_RUNNING: 479*3c1e38eaSMarcel Moolenaar info->ti_state = TD_THR_RUN; 480*3c1e38eaSMarcel Moolenaar break; 481*3c1e38eaSMarcel Moolenaar case PS_LOCKWAIT: 482*3c1e38eaSMarcel Moolenaar case PS_MUTEX_WAIT: 483*3c1e38eaSMarcel Moolenaar case PS_COND_WAIT: 484*3c1e38eaSMarcel Moolenaar case PS_SIGSUSPEND: 485*3c1e38eaSMarcel Moolenaar case PS_SIGWAIT: 486*3c1e38eaSMarcel Moolenaar case PS_JOIN: 487*3c1e38eaSMarcel Moolenaar case PS_SUSPENDED: 488*3c1e38eaSMarcel Moolenaar case PS_DEADLOCK: 489*3c1e38eaSMarcel Moolenaar case PS_SLEEP_WAIT: 490*3c1e38eaSMarcel Moolenaar info->ti_state = TD_THR_SLEEP; 491*3c1e38eaSMarcel Moolenaar break; 492*3c1e38eaSMarcel Moolenaar case PS_DEAD: 493*3c1e38eaSMarcel Moolenaar info->ti_state = TD_THR_ZOMBIE; 494*3c1e38eaSMarcel Moolenaar break; 495*3c1e38eaSMarcel Moolenaar default: 496*3c1e38eaSMarcel Moolenaar info->ti_state = TD_THR_UNKNOWN; 497*3c1e38eaSMarcel Moolenaar break; 498*3c1e38eaSMarcel Moolenaar } 499*3c1e38eaSMarcel Moolenaar 500*3c1e38eaSMarcel Moolenaar info->ti_db_suspended = 0; 501*3c1e38eaSMarcel Moolenaar info->ti_type = TD_THR_USER; 502*3c1e38eaSMarcel Moolenaar info->ti_pri = pt.active_priority; 503*3c1e38eaSMarcel Moolenaar info->ti_sigmask = pt.sigmask; 504*3c1e38eaSMarcel Moolenaar info->ti_traceme = 0; 505*3c1e38eaSMarcel Moolenaar info->ti_pending = pt.sigpend; 506*3c1e38eaSMarcel Moolenaar info->ti_events = 0; 507*3c1e38eaSMarcel Moolenaar return (0); 508*3c1e38eaSMarcel Moolenaar } 509*3c1e38eaSMarcel Moolenaar 510*3c1e38eaSMarcel Moolenaar static td_err_e 511*3c1e38eaSMarcel Moolenaar pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs) 512*3c1e38eaSMarcel Moolenaar { 513*3c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 514*3c1e38eaSMarcel Moolenaar struct kse_thr_mailbox tmbx; 515*3c1e38eaSMarcel Moolenaar psaddr_t tcb_addr, tmbx_addr, ptr; 516*3c1e38eaSMarcel Moolenaar lwpid_t lwp; 517*3c1e38eaSMarcel Moolenaar int ret; 518*3c1e38eaSMarcel Moolenaar 519*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 520*3c1e38eaSMarcel Moolenaar 521*3c1e38eaSMarcel Moolenaar ret = pt_validate(th); 522*3c1e38eaSMarcel Moolenaar if (ret) 523*3c1e38eaSMarcel Moolenaar return (ret); 524*3c1e38eaSMarcel Moolenaar 525*3c1e38eaSMarcel Moolenaar if (ta->map[th->th_tid].type == PT_LWP) { 526*3c1e38eaSMarcel Moolenaar ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 527*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 528*3c1e38eaSMarcel Moolenaar } 529*3c1e38eaSMarcel Moolenaar 530*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 531*3c1e38eaSMarcel Moolenaar offsetof(struct pthread, tcb), 532*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 533*3c1e38eaSMarcel Moolenaar if (ret != 0) 534*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 535*3c1e38eaSMarcel Moolenaar tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); 536*3c1e38eaSMarcel Moolenaar ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 537*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 538*3c1e38eaSMarcel Moolenaar if (ret != 0) 539*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 540*3c1e38eaSMarcel Moolenaar if (lwp != 0) { 541*3c1e38eaSMarcel Moolenaar ret = ps_lgetfpregs(ta->ph, lwp, fpregs); 542*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 543*3c1e38eaSMarcel Moolenaar } 544*3c1e38eaSMarcel Moolenaar 545*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 546*3c1e38eaSMarcel Moolenaar if (ret != 0) 547*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 548*3c1e38eaSMarcel Moolenaar pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs); 549*3c1e38eaSMarcel Moolenaar return (0); 550*3c1e38eaSMarcel Moolenaar } 551*3c1e38eaSMarcel Moolenaar 552*3c1e38eaSMarcel Moolenaar static td_err_e 553*3c1e38eaSMarcel Moolenaar pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 554*3c1e38eaSMarcel Moolenaar { 555*3c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 556*3c1e38eaSMarcel Moolenaar struct kse_thr_mailbox tmbx; 557*3c1e38eaSMarcel Moolenaar psaddr_t tcb_addr, tmbx_addr, ptr; 558*3c1e38eaSMarcel Moolenaar lwpid_t lwp; 559*3c1e38eaSMarcel Moolenaar int ret; 560*3c1e38eaSMarcel Moolenaar 561*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 562*3c1e38eaSMarcel Moolenaar 563*3c1e38eaSMarcel Moolenaar ret = pt_validate(th); 564*3c1e38eaSMarcel Moolenaar if (ret) 565*3c1e38eaSMarcel Moolenaar return (ret); 566*3c1e38eaSMarcel Moolenaar 567*3c1e38eaSMarcel Moolenaar if (ta->map[th->th_tid].type == PT_LWP) { 568*3c1e38eaSMarcel Moolenaar ret = ps_lgetregs(ta->ph, 569*3c1e38eaSMarcel Moolenaar ta->map[th->th_tid].lwp, gregs); 570*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 571*3c1e38eaSMarcel Moolenaar } 572*3c1e38eaSMarcel Moolenaar 573*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 574*3c1e38eaSMarcel Moolenaar offsetof(struct pthread, tcb), 575*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 576*3c1e38eaSMarcel Moolenaar if (ret != 0) 577*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 578*3c1e38eaSMarcel Moolenaar tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); 579*3c1e38eaSMarcel Moolenaar ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 580*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 581*3c1e38eaSMarcel Moolenaar if (ret != 0) 582*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 583*3c1e38eaSMarcel Moolenaar if (lwp != 0) { 584*3c1e38eaSMarcel Moolenaar ret = ps_lgetregs(ta->ph, lwp, gregs); 585*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 586*3c1e38eaSMarcel Moolenaar } 587*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 588*3c1e38eaSMarcel Moolenaar if (ret != 0) 589*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 590*3c1e38eaSMarcel Moolenaar pt_ucontext_to_reg(&tmbx.tm_context, gregs); 591*3c1e38eaSMarcel Moolenaar return (0); 592*3c1e38eaSMarcel Moolenaar } 593*3c1e38eaSMarcel Moolenaar 594*3c1e38eaSMarcel Moolenaar static td_err_e 595*3c1e38eaSMarcel Moolenaar pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 596*3c1e38eaSMarcel Moolenaar { 597*3c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 598*3c1e38eaSMarcel Moolenaar struct kse_thr_mailbox tmbx; 599*3c1e38eaSMarcel Moolenaar psaddr_t tcb_addr, tmbx_addr, ptr; 600*3c1e38eaSMarcel Moolenaar lwpid_t lwp; 601*3c1e38eaSMarcel Moolenaar int ret; 602*3c1e38eaSMarcel Moolenaar 603*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 604*3c1e38eaSMarcel Moolenaar 605*3c1e38eaSMarcel Moolenaar ret = pt_validate(th); 606*3c1e38eaSMarcel Moolenaar if (ret) 607*3c1e38eaSMarcel Moolenaar return (ret); 608*3c1e38eaSMarcel Moolenaar 609*3c1e38eaSMarcel Moolenaar if (ta->map[th->th_tid].type == PT_LWP) { 610*3c1e38eaSMarcel Moolenaar ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); 611*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 612*3c1e38eaSMarcel Moolenaar } 613*3c1e38eaSMarcel Moolenaar 614*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 615*3c1e38eaSMarcel Moolenaar offsetof(struct pthread, tcb), 616*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 617*3c1e38eaSMarcel Moolenaar if (ret != 0) 618*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 619*3c1e38eaSMarcel Moolenaar tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); 620*3c1e38eaSMarcel Moolenaar ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 621*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 622*3c1e38eaSMarcel Moolenaar if (ret != 0) 623*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 624*3c1e38eaSMarcel Moolenaar if (lwp != 0) { 625*3c1e38eaSMarcel Moolenaar ret = ps_lsetfpregs(ta->ph, lwp, fpregs); 626*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 627*3c1e38eaSMarcel Moolenaar } 628*3c1e38eaSMarcel Moolenaar /* 629*3c1e38eaSMarcel Moolenaar * Read a copy of context, this makes sure that registers 630*3c1e38eaSMarcel Moolenaar * not covered by structure reg won't be clobbered 631*3c1e38eaSMarcel Moolenaar */ 632*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 633*3c1e38eaSMarcel Moolenaar if (ret != 0) 634*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 635*3c1e38eaSMarcel Moolenaar 636*3c1e38eaSMarcel Moolenaar pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context); 637*3c1e38eaSMarcel Moolenaar ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 638*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 639*3c1e38eaSMarcel Moolenaar } 640*3c1e38eaSMarcel Moolenaar 641*3c1e38eaSMarcel Moolenaar static td_err_e 642*3c1e38eaSMarcel Moolenaar pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 643*3c1e38eaSMarcel Moolenaar { 644*3c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 645*3c1e38eaSMarcel Moolenaar struct kse_thr_mailbox tmbx; 646*3c1e38eaSMarcel Moolenaar psaddr_t tcb_addr, tmbx_addr, ptr; 647*3c1e38eaSMarcel Moolenaar lwpid_t lwp; 648*3c1e38eaSMarcel Moolenaar int ret; 649*3c1e38eaSMarcel Moolenaar 650*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 651*3c1e38eaSMarcel Moolenaar 652*3c1e38eaSMarcel Moolenaar ret = pt_validate(th); 653*3c1e38eaSMarcel Moolenaar if (ret) 654*3c1e38eaSMarcel Moolenaar return (ret); 655*3c1e38eaSMarcel Moolenaar 656*3c1e38eaSMarcel Moolenaar if (ta->map[th->th_tid].type == PT_LWP) { 657*3c1e38eaSMarcel Moolenaar ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs); 658*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 659*3c1e38eaSMarcel Moolenaar } 660*3c1e38eaSMarcel Moolenaar 661*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 662*3c1e38eaSMarcel Moolenaar offsetof(struct pthread, tcb), 663*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 664*3c1e38eaSMarcel Moolenaar if (ret != 0) 665*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 666*3c1e38eaSMarcel Moolenaar tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); 667*3c1e38eaSMarcel Moolenaar ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp); 668*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t)); 669*3c1e38eaSMarcel Moolenaar if (ret != 0) 670*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 671*3c1e38eaSMarcel Moolenaar if (lwp != 0) { 672*3c1e38eaSMarcel Moolenaar ret = ps_lsetregs(ta->ph, lwp, gregs); 673*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 674*3c1e38eaSMarcel Moolenaar } 675*3c1e38eaSMarcel Moolenaar 676*3c1e38eaSMarcel Moolenaar /* 677*3c1e38eaSMarcel Moolenaar * Read a copy of context, make sure that registers 678*3c1e38eaSMarcel Moolenaar * not covered by structure reg won't be clobbered 679*3c1e38eaSMarcel Moolenaar */ 680*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 681*3c1e38eaSMarcel Moolenaar if (ret != 0) 682*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 683*3c1e38eaSMarcel Moolenaar pt_reg_to_ucontext(gregs, &tmbx.tm_context); 684*3c1e38eaSMarcel Moolenaar ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 685*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 686*3c1e38eaSMarcel Moolenaar } 687*3c1e38eaSMarcel Moolenaar 688*3c1e38eaSMarcel Moolenaar static td_err_e 689*3c1e38eaSMarcel Moolenaar pt_thr_event_enable(const td_thrhandle_t *th, int en) 690*3c1e38eaSMarcel Moolenaar { 691*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 692*3c1e38eaSMarcel Moolenaar return (TD_ERR); 693*3c1e38eaSMarcel Moolenaar } 694*3c1e38eaSMarcel Moolenaar 695*3c1e38eaSMarcel Moolenaar static td_err_e 696*3c1e38eaSMarcel Moolenaar pt_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *setp) 697*3c1e38eaSMarcel Moolenaar { 698*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 699*3c1e38eaSMarcel Moolenaar return (TD_ERR); 700*3c1e38eaSMarcel Moolenaar } 701*3c1e38eaSMarcel Moolenaar 702*3c1e38eaSMarcel Moolenaar static td_err_e 703*3c1e38eaSMarcel Moolenaar pt_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *setp) 704*3c1e38eaSMarcel Moolenaar { 705*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 706*3c1e38eaSMarcel Moolenaar return (TD_ERR); 707*3c1e38eaSMarcel Moolenaar } 708*3c1e38eaSMarcel Moolenaar 709*3c1e38eaSMarcel Moolenaar static td_err_e 710*3c1e38eaSMarcel Moolenaar pt_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 711*3c1e38eaSMarcel Moolenaar { 712*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 713*3c1e38eaSMarcel Moolenaar return (TD_NOMSG); 714*3c1e38eaSMarcel Moolenaar } 715*3c1e38eaSMarcel Moolenaar 716*3c1e38eaSMarcel Moolenaar static td_err_e 717*3c1e38eaSMarcel Moolenaar pt_thr_sstep(const td_thrhandle_t *th, int step) 718*3c1e38eaSMarcel Moolenaar { 719*3c1e38eaSMarcel Moolenaar const td_thragent_t *ta = th->th_ta; 720*3c1e38eaSMarcel Moolenaar struct kse_thr_mailbox tmbx; 721*3c1e38eaSMarcel Moolenaar struct reg regs; 722*3c1e38eaSMarcel Moolenaar psaddr_t tcb_addr, tmbx_addr; 723*3c1e38eaSMarcel Moolenaar uint32_t tmp; 724*3c1e38eaSMarcel Moolenaar lwpid_t lwp; 725*3c1e38eaSMarcel Moolenaar int ret; 726*3c1e38eaSMarcel Moolenaar 727*3c1e38eaSMarcel Moolenaar TDBG_FUNC(); 728*3c1e38eaSMarcel Moolenaar 729*3c1e38eaSMarcel Moolenaar ret = pt_validate(th); 730*3c1e38eaSMarcel Moolenaar if (ret) 731*3c1e38eaSMarcel Moolenaar return (ret); 732*3c1e38eaSMarcel Moolenaar 733*3c1e38eaSMarcel Moolenaar if (ta->map[th->th_tid].type == PT_LWP) 734*3c1e38eaSMarcel Moolenaar return (TD_BADTH); 735*3c1e38eaSMarcel Moolenaar 736*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 737*3c1e38eaSMarcel Moolenaar offsetof(struct pthread, tcb), 738*3c1e38eaSMarcel Moolenaar &tcb_addr, sizeof(tcb_addr)); 739*3c1e38eaSMarcel Moolenaar if (ret != 0) 740*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 741*3c1e38eaSMarcel Moolenaar 742*3c1e38eaSMarcel Moolenaar /* Clear or set single step flag in thread mailbox */ 743*3c1e38eaSMarcel Moolenaar tmp = step ? TMDF_SSTEP : 0; 744*3c1e38eaSMarcel Moolenaar ret = ps_pwrite(ta->ph, tcb_addr + offsetof(struct tcb, 745*3c1e38eaSMarcel Moolenaar tcb_tmbx.tm_dflags), &tmp, sizeof(tmp)); 746*3c1e38eaSMarcel Moolenaar if (ret != 0) 747*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 748*3c1e38eaSMarcel Moolenaar /* Get lwp */ 749*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, tcb_addr + offsetof(struct tcb, 750*3c1e38eaSMarcel Moolenaar tcb_tmbx.tm_lwp), &lwp, sizeof(lwpid_t)); 751*3c1e38eaSMarcel Moolenaar if (ret != 0) 752*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 753*3c1e38eaSMarcel Moolenaar if (lwp != 0) 754*3c1e38eaSMarcel Moolenaar return (TD_BADTH); 755*3c1e38eaSMarcel Moolenaar 756*3c1e38eaSMarcel Moolenaar tmbx_addr = tcb_addr + offsetof(struct tcb, tcb_tmbx); 757*3c1e38eaSMarcel Moolenaar /* 758*3c1e38eaSMarcel Moolenaar * context is in userland, some architectures store 759*3c1e38eaSMarcel Moolenaar * single step status in registers, we should change 760*3c1e38eaSMarcel Moolenaar * these registers. 761*3c1e38eaSMarcel Moolenaar */ 762*3c1e38eaSMarcel Moolenaar ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); 763*3c1e38eaSMarcel Moolenaar if (ret == 0) { 764*3c1e38eaSMarcel Moolenaar pt_ucontext_to_reg(&tmbx.tm_context, ®s); 765*3c1e38eaSMarcel Moolenaar /* only write out if it is really changed. */ 766*3c1e38eaSMarcel Moolenaar if (pt_reg_sstep(®s, step) != 0) { 767*3c1e38eaSMarcel Moolenaar pt_reg_to_ucontext(®s, &tmbx.tm_context); 768*3c1e38eaSMarcel Moolenaar ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, 769*3c1e38eaSMarcel Moolenaar sizeof(tmbx)); 770*3c1e38eaSMarcel Moolenaar } 771*3c1e38eaSMarcel Moolenaar } 772*3c1e38eaSMarcel Moolenaar return (P2T(ret)); 773*3c1e38eaSMarcel Moolenaar } 774*3c1e38eaSMarcel Moolenaar 775*3c1e38eaSMarcel Moolenaar static void 776*3c1e38eaSMarcel Moolenaar pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp) 777*3c1e38eaSMarcel Moolenaar { 778*3c1e38eaSMarcel Moolenaar int i; 779*3c1e38eaSMarcel Moolenaar 780*3c1e38eaSMarcel Moolenaar for (i = 0; i < ta->map_len; ++i) { 781*3c1e38eaSMarcel Moolenaar if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) { 782*3c1e38eaSMarcel Moolenaar ta->map[i].type = PT_NONE; 783*3c1e38eaSMarcel Moolenaar return; 784*3c1e38eaSMarcel Moolenaar } 785*3c1e38eaSMarcel Moolenaar } 786*3c1e38eaSMarcel Moolenaar } 787*3c1e38eaSMarcel Moolenaar 788*3c1e38eaSMarcel Moolenaar static int 789*3c1e38eaSMarcel Moolenaar pt_validate(const td_thrhandle_t *th) 790*3c1e38eaSMarcel Moolenaar { 791*3c1e38eaSMarcel Moolenaar 792*3c1e38eaSMarcel Moolenaar if (th->th_tid < 0 || th->th_tid >= th->th_ta->map_len || 793*3c1e38eaSMarcel Moolenaar th->th_ta->map[th->th_tid].type == PT_NONE) 794*3c1e38eaSMarcel Moolenaar return (TD_NOTHR); 795*3c1e38eaSMarcel Moolenaar return (TD_OK); 796*3c1e38eaSMarcel Moolenaar } 797*3c1e38eaSMarcel Moolenaar 798*3c1e38eaSMarcel Moolenaar struct ta_ops libpthread_db_ops = { 799*3c1e38eaSMarcel Moolenaar .to_init = pt_init, 800*3c1e38eaSMarcel Moolenaar .to_ta_clear_event = pt_ta_clear_event, 801*3c1e38eaSMarcel Moolenaar .to_ta_delete = pt_ta_delete, 802*3c1e38eaSMarcel Moolenaar .to_ta_event_addr = pt_ta_event_addr, 803*3c1e38eaSMarcel Moolenaar .to_ta_event_getmsg = pt_ta_event_getmsg, 804*3c1e38eaSMarcel Moolenaar .to_ta_map_id2thr = pt_ta_map_id2thr, 805*3c1e38eaSMarcel Moolenaar .to_ta_map_lwp2thr = pt_ta_map_lwp2thr, 806*3c1e38eaSMarcel Moolenaar .to_ta_new = pt_ta_new, 807*3c1e38eaSMarcel Moolenaar .to_ta_set_event = pt_ta_set_event, 808*3c1e38eaSMarcel Moolenaar .to_ta_thr_iter = pt_ta_thr_iter, 809*3c1e38eaSMarcel Moolenaar .to_ta_tsd_iter = pt_ta_tsd_iter, 810*3c1e38eaSMarcel Moolenaar .to_thr_clear_event = pt_thr_clear_event, 811*3c1e38eaSMarcel Moolenaar .to_thr_dbresume = pt_thr_dbresume, 812*3c1e38eaSMarcel Moolenaar .to_thr_dbsuspend = pt_thr_dbsuspend, 813*3c1e38eaSMarcel Moolenaar .to_thr_event_enable = pt_thr_event_enable, 814*3c1e38eaSMarcel Moolenaar .to_thr_event_getmsg = pt_thr_event_getmsg, 815*3c1e38eaSMarcel Moolenaar .to_thr_get_info = pt_thr_get_info, 816*3c1e38eaSMarcel Moolenaar .to_thr_getfpregs = pt_thr_getfpregs, 817*3c1e38eaSMarcel Moolenaar .to_thr_getgregs = pt_thr_getgregs, 818*3c1e38eaSMarcel Moolenaar .to_thr_set_event = pt_thr_set_event, 819*3c1e38eaSMarcel Moolenaar .to_thr_setfpregs = pt_thr_setfpregs, 820*3c1e38eaSMarcel Moolenaar .to_thr_setgregs = pt_thr_setgregs, 821*3c1e38eaSMarcel Moolenaar .to_thr_validate = pt_thr_validate, 822*3c1e38eaSMarcel Moolenaar 823*3c1e38eaSMarcel Moolenaar /* FreeBSD specific extensions. */ 824*3c1e38eaSMarcel Moolenaar .to_thr_sstep = pt_thr_sstep, 825*3c1e38eaSMarcel Moolenaar }; 826