1132332Smarcel/* 2132332Smarcel * Copyright (c) 2004 David Xu <davidxu@freebsd.org> 3132332Smarcel * All rights reserved. 4132332Smarcel * 5132332Smarcel * Redistribution and use in source and binary forms, with or without 6132332Smarcel * modification, are permitted provided that the following conditions 7132332Smarcel * are met: 8132332Smarcel * 1. Redistributions of source code must retain the above copyright 9132332Smarcel * notice, this list of conditions and the following disclaimer. 10132332Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11132332Smarcel * notice, this list of conditions and the following disclaimer in the 12132332Smarcel * documentation and/or other materials provided with the distribution. 13132332Smarcel * 14132332Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132332Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132332Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132332Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132332Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132332Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132332Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132332Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22132332Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132332Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132332Smarcel * SUCH DAMAGE. 25132332Smarcel */ 26132332Smarcel 27132332Smarcel#include <sys/cdefs.h> 28132332Smarcel__FBSDID("$FreeBSD$"); 29132332Smarcel 30132332Smarcel#include <proc_service.h> 31132332Smarcel#include <stddef.h> 32132332Smarcel#include <thread_db.h> 33132332Smarcel#include <unistd.h> 34177490Sdavidxu#include <sys/cdefs.h> 35181065Smarcel#include <sys/endian.h> 36181065Smarcel#include <sys/errno.h> 37177490Sdavidxu#include <sys/linker_set.h> 38132332Smarcel 39132332Smarcel#include "thread_db_int.h" 40132332Smarcel 41132332Smarcelstruct td_thragent 42132332Smarcel{ 43132332Smarcel TD_THRAGENT_FIELDS; 44132332Smarcel}; 45132332Smarcel 46132332Smarcelstatic TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); 47132332Smarcel 48177490SdavidxuSET_DECLARE(__ta_ops, struct ta_ops); 49132332Smarcel 50132332Smarceltd_err_e 51132332Smarceltd_init(void) 52132332Smarcel{ 53132332Smarcel td_err_e ret, tmp; 54177490Sdavidxu struct ta_ops *ops_p, **ops_pp; 55132332Smarcel 56132332Smarcel ret = 0; 57177490Sdavidxu SET_FOREACH(ops_pp, __ta_ops) { 58177490Sdavidxu ops_p = *ops_pp; 59177490Sdavidxu if (ops_p->to_init != NULL) { 60177490Sdavidxu tmp = ops_p->to_init(); 61132332Smarcel if (tmp != TD_OK) 62132332Smarcel ret = tmp; 63132332Smarcel } 64132332Smarcel } 65132332Smarcel return (ret); 66132332Smarcel} 67132332Smarcel 68132332Smarceltd_err_e 69132332Smarceltd_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) 70132332Smarcel{ 71132332Smarcel return (ta->ta_ops->to_ta_clear_event(ta, events)); 72132332Smarcel} 73132332Smarcel 74132332Smarceltd_err_e 75132332Smarceltd_ta_delete(td_thragent_t *ta) 76132332Smarcel{ 77132332Smarcel TAILQ_REMOVE(&proclist, ta, ta_next); 78132332Smarcel return (ta->ta_ops->to_ta_delete(ta)); 79132332Smarcel} 80132332Smarcel 81132332Smarceltd_err_e 82132332Smarceltd_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) 83132332Smarcel{ 84132332Smarcel return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); 85132332Smarcel} 86132332Smarcel 87132332Smarceltd_err_e 88132332Smarceltd_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) 89132332Smarcel{ 90132332Smarcel return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); 91132332Smarcel} 92132332Smarcel 93132332Smarceltd_err_e 94132332Smarceltd_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) 95132332Smarcel{ 96132332Smarcel return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); 97132332Smarcel} 98132332Smarcel 99132332Smarceltd_err_e 100132332Smarceltd_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) 101132332Smarcel{ 102132332Smarcel return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); 103132332Smarcel} 104132332Smarcel 105132332Smarceltd_err_e 106132332Smarceltd_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) 107132332Smarcel{ 108177490Sdavidxu struct ta_ops *ops_p, **ops_pp; 109132332Smarcel 110177490Sdavidxu SET_FOREACH(ops_pp, __ta_ops) { 111177490Sdavidxu ops_p = *ops_pp; 112177490Sdavidxu if (ops_p->to_ta_new(ph, pta) == TD_OK) { 113132332Smarcel TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); 114177490Sdavidxu (*pta)->ta_ops = ops_p; 115132332Smarcel return (TD_OK); 116132332Smarcel } 117132332Smarcel } 118132332Smarcel return (TD_NOLIBTHREAD); 119132332Smarcel} 120132332Smarcel 121132332Smarceltd_err_e 122132332Smarceltd_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) 123132332Smarcel{ 124132332Smarcel return (ta->ta_ops->to_ta_set_event(ta, events)); 125132332Smarcel} 126132332Smarcel 127132332Smarceltd_err_e 128132332Smarceltd_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback, 129132332Smarcel void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, 130132332Smarcel unsigned int ti_user_flags) 131132332Smarcel{ 132132332Smarcel return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, 133132332Smarcel ti_pri, ti_sigmask_p, ti_user_flags)); 134132332Smarcel} 135132332Smarcel 136132332Smarceltd_err_e 137132332Smarceltd_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, 138132332Smarcel void *cbdata_p) 139132332Smarcel{ 140132332Smarcel return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); 141132332Smarcel} 142132332Smarcel 143132332Smarceltd_err_e 144132332Smarceltd_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) 145132332Smarcel{ 146132332Smarcel const td_thragent_t *ta = th->th_ta; 147132332Smarcel return (ta->ta_ops->to_thr_clear_event(th, events)); 148132332Smarcel} 149132332Smarcel 150132332Smarceltd_err_e 151132332Smarceltd_thr_dbresume(const td_thrhandle_t *th) 152132332Smarcel{ 153132332Smarcel const td_thragent_t *ta = th->th_ta; 154132332Smarcel return (ta->ta_ops->to_thr_dbresume(th)); 155132332Smarcel} 156132332Smarcel 157132332Smarceltd_err_e 158132332Smarceltd_thr_dbsuspend(const td_thrhandle_t *th) 159132332Smarcel{ 160132332Smarcel const td_thragent_t *ta = th->th_ta; 161132332Smarcel return (ta->ta_ops->to_thr_dbsuspend(th)); 162132332Smarcel} 163132332Smarcel 164132332Smarceltd_err_e 165132332Smarceltd_thr_event_enable(const td_thrhandle_t *th, int en) 166132332Smarcel{ 167132332Smarcel const td_thragent_t *ta = th->th_ta; 168132332Smarcel return (ta->ta_ops->to_thr_event_enable(th, en)); 169132332Smarcel} 170132332Smarcel 171132332Smarceltd_err_e 172132332Smarceltd_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) 173132332Smarcel{ 174132332Smarcel const td_thragent_t *ta = th->th_ta; 175132332Smarcel return (ta->ta_ops->to_thr_event_getmsg(th, msg)); 176132332Smarcel} 177132332Smarcel 178132332Smarceltd_err_e 179209689Skibtd_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *info) 180209689Skib{ 181209689Skib const td_thragent_t *ta = th->th_ta; 182209689Skib return (ta->ta_ops->to_thr_old_get_info(th, info)); 183209689Skib} 184209689Skib__sym_compat(td_thr_get_info, td_thr_old_get_info, FBSD_1.0); 185209689Skib 186209689Skibtd_err_e 187132332Smarceltd_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) 188132332Smarcel{ 189132332Smarcel const td_thragent_t *ta = th->th_ta; 190132332Smarcel return (ta->ta_ops->to_thr_get_info(th, info)); 191132332Smarcel} 192132332Smarcel 193146818Sdfr#ifdef __i386__ 194132332Smarceltd_err_e 195146818Sdfrtd_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave) 196146818Sdfr{ 197146818Sdfr const td_thragent_t *ta = th->th_ta; 198146818Sdfr return (ta->ta_ops->to_thr_getxmmregs(th, fxsave)); 199146818Sdfr} 200146818Sdfr#endif 201146818Sdfr 202146818Sdfr 203146818Sdfrtd_err_e 204132332Smarceltd_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) 205132332Smarcel{ 206132332Smarcel const td_thragent_t *ta = th->th_ta; 207132332Smarcel return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); 208132332Smarcel} 209132332Smarcel 210132332Smarceltd_err_e 211132332Smarceltd_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) 212132332Smarcel{ 213132332Smarcel const td_thragent_t *ta = th->th_ta; 214132332Smarcel return (ta->ta_ops->to_thr_getgregs(th, gregs)); 215132332Smarcel} 216132332Smarcel 217132332Smarceltd_err_e 218132332Smarceltd_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) 219132332Smarcel{ 220132332Smarcel const td_thragent_t *ta = th->th_ta; 221132332Smarcel return (ta->ta_ops->to_thr_set_event(th, events)); 222132332Smarcel} 223132332Smarcel 224146818Sdfr#ifdef __i386__ 225132332Smarceltd_err_e 226146818Sdfrtd_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave) 227146818Sdfr{ 228146818Sdfr const td_thragent_t *ta = th->th_ta; 229146818Sdfr return (ta->ta_ops->to_thr_setxmmregs(th, fxsave)); 230146818Sdfr} 231146818Sdfr#endif 232146818Sdfr 233146818Sdfrtd_err_e 234132332Smarceltd_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) 235132332Smarcel{ 236132332Smarcel const td_thragent_t *ta = th->th_ta; 237132332Smarcel return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); 238132332Smarcel} 239132332Smarcel 240132332Smarceltd_err_e 241132332Smarceltd_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) 242132332Smarcel{ 243132332Smarcel const td_thragent_t *ta = th->th_ta; 244132332Smarcel return (ta->ta_ops->to_thr_setgregs(th, gregs)); 245132332Smarcel} 246132332Smarcel 247132332Smarceltd_err_e 248132332Smarceltd_thr_validate(const td_thrhandle_t *th) 249132332Smarcel{ 250132332Smarcel const td_thragent_t *ta = th->th_ta; 251132332Smarcel return (ta->ta_ops->to_thr_validate(th)); 252132332Smarcel} 253132332Smarcel 254133342Sdavidxutd_err_e 255180982Smarceltd_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t linkmap, size_t offset, 256180982Smarcel psaddr_t *address) 257133342Sdavidxu{ 258133342Sdavidxu const td_thragent_t *ta = th->th_ta; 259133342Sdavidxu return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address)); 260133342Sdavidxu} 261133342Sdavidxu 262132332Smarcel/* FreeBSD specific extensions. */ 263132332Smarcel 264132332Smarceltd_err_e 265132332Smarceltd_thr_sstep(const td_thrhandle_t *th, int step) 266132332Smarcel{ 267132332Smarcel const td_thragent_t *ta = th->th_ta; 268132332Smarcel return (ta->ta_ops->to_thr_sstep(th, step)); 269132332Smarcel} 270181065Smarcel 271181065Smarcel/* 272181065Smarcel * Support functions for reading from and writing to the target 273181065Smarcel * address space. 274181065Smarcel */ 275181065Smarcel 276181065Smarcelstatic int 277181065Smarcelthr_pread(struct ps_prochandle *ph, psaddr_t addr, uint64_t *val, 278181065Smarcel u_int size, u_int byteorder) 279181065Smarcel{ 280181065Smarcel uint8_t buf[sizeof(*val)]; 281181065Smarcel ps_err_e err; 282181065Smarcel 283181065Smarcel if (size > sizeof(buf)) 284181065Smarcel return (EOVERFLOW); 285181065Smarcel 286181065Smarcel err = ps_pread(ph, addr, buf, size); 287181065Smarcel if (err != PS_OK) 288181065Smarcel return (EFAULT); 289181065Smarcel 290181065Smarcel switch (byteorder) { 291181065Smarcel case BIG_ENDIAN: 292181065Smarcel switch (size) { 293181065Smarcel case 1: 294181065Smarcel *val = buf[0]; 295181065Smarcel break; 296181065Smarcel case 2: 297181065Smarcel *val = be16dec(buf); 298181065Smarcel break; 299181065Smarcel case 4: 300181065Smarcel *val = be32dec(buf); 301181065Smarcel break; 302181065Smarcel case 8: 303181065Smarcel *val = be64dec(buf); 304181065Smarcel break; 305181065Smarcel default: 306181065Smarcel return (EINVAL); 307181065Smarcel } 308181065Smarcel break; 309181065Smarcel case LITTLE_ENDIAN: 310181065Smarcel switch (size) { 311181065Smarcel case 1: 312181065Smarcel *val = buf[0]; 313181065Smarcel break; 314181065Smarcel case 2: 315181065Smarcel *val = le16dec(buf); 316181065Smarcel break; 317181065Smarcel case 4: 318181065Smarcel *val = le32dec(buf); 319181065Smarcel break; 320181065Smarcel case 8: 321181065Smarcel *val = le64dec(buf); 322181065Smarcel break; 323181065Smarcel default: 324181065Smarcel return (EINVAL); 325181065Smarcel } 326181065Smarcel break; 327181065Smarcel default: 328181065Smarcel return (EINVAL); 329181065Smarcel } 330181065Smarcel 331181065Smarcel return (0); 332181065Smarcel} 333181065Smarcel 334181065Smarcelint 335183021Smarcelthr_pread_int(const struct td_thragent *ta, psaddr_t addr, uint32_t *val) 336181065Smarcel{ 337181065Smarcel uint64_t tmp; 338181065Smarcel int error; 339181065Smarcel 340181065Smarcel error = thr_pread(ta->ph, addr, &tmp, sizeof(int), BYTE_ORDER); 341181065Smarcel if (!error) 342181065Smarcel *val = tmp; 343181065Smarcel 344181065Smarcel return (error); 345181065Smarcel} 346181065Smarcel 347181065Smarcelint 348183021Smarcelthr_pread_long(const struct td_thragent *ta, psaddr_t addr, uint64_t *val) 349181065Smarcel{ 350181065Smarcel 351181065Smarcel return (thr_pread(ta->ph, addr, val, sizeof(long), BYTE_ORDER)); 352181065Smarcel} 353181065Smarcel 354181065Smarcelint 355183021Smarcelthr_pread_ptr(const struct td_thragent *ta, psaddr_t addr, psaddr_t *val) 356181065Smarcel{ 357183021Smarcel uint64_t tmp; 358183021Smarcel int error; 359181065Smarcel 360183021Smarcel error = thr_pread(ta->ph, addr, &tmp, sizeof(void *), BYTE_ORDER); 361183021Smarcel if (!error) 362183021Smarcel *val = tmp; 363183021Smarcel 364183021Smarcel return (error); 365181065Smarcel} 366181065Smarcel 367181065Smarcelstatic int 368181065Smarcelthr_pwrite(struct ps_prochandle *ph, psaddr_t addr, uint64_t val, 369181065Smarcel u_int size, u_int byteorder) 370181065Smarcel{ 371181065Smarcel uint8_t buf[sizeof(val)]; 372181065Smarcel ps_err_e err; 373181065Smarcel 374181065Smarcel if (size > sizeof(buf)) 375181065Smarcel return (EOVERFLOW); 376181065Smarcel 377181065Smarcel switch (byteorder) { 378181065Smarcel case BIG_ENDIAN: 379181065Smarcel switch (size) { 380181065Smarcel case 1: 381181065Smarcel buf[0] = (uint8_t)val; 382181065Smarcel break; 383181065Smarcel case 2: 384181065Smarcel be16enc(buf, (uint16_t)val); 385181065Smarcel break; 386181065Smarcel case 4: 387181065Smarcel be32enc(buf, (uint32_t)val); 388181065Smarcel break; 389181065Smarcel case 8: 390181065Smarcel be64enc(buf, (uint64_t)val); 391181065Smarcel break; 392181065Smarcel default: 393181065Smarcel return (EINVAL); 394181065Smarcel } 395181065Smarcel break; 396181065Smarcel case LITTLE_ENDIAN: 397181065Smarcel switch (size) { 398181065Smarcel case 1: 399181065Smarcel buf[0] = (uint8_t)val; 400181065Smarcel break; 401181065Smarcel case 2: 402181065Smarcel le16enc(buf, (uint16_t)val); 403181065Smarcel break; 404181065Smarcel case 4: 405181065Smarcel le32enc(buf, (uint32_t)val); 406181065Smarcel break; 407181065Smarcel case 8: 408181065Smarcel le64enc(buf, (uint64_t)val); 409181065Smarcel break; 410181065Smarcel default: 411181065Smarcel return (EINVAL); 412181065Smarcel } 413181065Smarcel break; 414181065Smarcel default: 415181065Smarcel return (EINVAL); 416181065Smarcel } 417181065Smarcel 418181065Smarcel err = ps_pwrite(ph, addr, buf, size); 419181065Smarcel return ((err != PS_OK) ? EFAULT : 0); 420181065Smarcel} 421181065Smarcel 422181065Smarcelint 423183021Smarcelthr_pwrite_int(const struct td_thragent *ta, psaddr_t addr, uint32_t val) 424181065Smarcel{ 425181065Smarcel 426181065Smarcel return (thr_pwrite(ta->ph, addr, val, sizeof(int), BYTE_ORDER)); 427181065Smarcel} 428181065Smarcel 429181065Smarcelint 430183021Smarcelthr_pwrite_long(const struct td_thragent *ta, psaddr_t addr, uint64_t val) 431181065Smarcel{ 432181065Smarcel 433181065Smarcel return (thr_pwrite(ta->ph, addr, val, sizeof(long), BYTE_ORDER)); 434181065Smarcel} 435181065Smarcel 436181065Smarcelint 437183021Smarcelthr_pwrite_ptr(const struct td_thragent *ta, psaddr_t addr, psaddr_t val) 438181065Smarcel{ 439181065Smarcel 440181065Smarcel return (thr_pwrite(ta->ph, addr, val, sizeof(void *), BYTE_ORDER)); 441181065Smarcel} 442181065Smarcel 443