diff --git a/lib/libthread_db/Makefile b/lib/libthread_db/Makefile index e6295989b7cb..5825cc908a20 100644 --- a/lib/libthread_db/Makefile +++ b/lib/libthread_db/Makefile @@ -1,5 +1,28 @@ # $FreeBSD$ -SUBDIR=pthread src +.PATH: ${.CURDIR}/arch/${MACHINE_ARCH} -.include +LIB= thread_db +SHLIB_MAJOR= 1 +SRCS= thread_db.c +SRCS+= libpthread_db.c libpthread_md.c +SRCS+= libc_r_db.c libc_r_md.c +SRCS+= libthr_db.c +INCS= thread_db.h +WARNS?= 2 + +CFLAGS+=-I. -I${.CURDIR} + +SRCS+= libpthread.h +CLEANFILES+= libpthread.h + +LIBPTHREAD= ${.CURDIR}/../libpthread +LIBPTHREAD_ARCH= ${LIBPTHREAD}/arch/${MACHINE_ARCH}/include + +libpthread.h: + @echo '#define LIBTHREAD_DB 1' > ${.TARGET} + @echo '#include "${LIBPTHREAD}/sys/lock.h"' >> ${.TARGET} + @echo '#include "${LIBPTHREAD_ARCH}/pthread_md.h"' >> ${.TARGET} + @echo '#include "${LIBPTHREAD}/thread/thr_private.h"' >> ${.TARGET} + +.include diff --git a/lib/libthread_db/arch/alpha/libc_r_md.c b/lib/libthread_db/arch/alpha/libc_r_md.c new file mode 100644 index 000000000000..2f0f7f706f9a --- /dev/null +++ b/lib/libthread_db/arch/alpha/libc_r_md.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +void +libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +{ + r->r_regs[R_V0] = jb->_jb[4]; + r->r_regs[R_T0] = jb->_jb[5]; + r->r_regs[R_T1] = jb->_jb[6]; + r->r_regs[R_T2] = jb->_jb[7]; + r->r_regs[R_T3] = jb->_jb[8]; + r->r_regs[R_T4] = jb->_jb[9]; + r->r_regs[R_T5] = jb->_jb[10]; + r->r_regs[R_T6] = jb->_jb[11]; + r->r_regs[R_T7] = jb->_jb[12]; + r->r_regs[R_S0] = jb->_jb[13]; + r->r_regs[R_S1] = jb->_jb[14]; + r->r_regs[R_S2] = jb->_jb[15]; + r->r_regs[R_S3] = jb->_jb[16]; + r->r_regs[R_S4] = jb->_jb[17]; + r->r_regs[R_S5] = jb->_jb[18]; + r->r_regs[R_S6] = jb->_jb[19]; + r->r_regs[R_A0] = jb->_jb[20]; + r->r_regs[R_A1] = jb->_jb[21]; + r->r_regs[R_A2] = jb->_jb[22]; + r->r_regs[R_A3] = jb->_jb[23]; + r->r_regs[R_A4] = jb->_jb[24]; + r->r_regs[R_A5] = jb->_jb[25]; + r->r_regs[R_T8] = jb->_jb[26]; + r->r_regs[R_T9] = jb->_jb[27]; + r->r_regs[R_T10] = jb->_jb[28]; + r->r_regs[R_T11] = jb->_jb[29]; + r->r_regs[R_RA] = jb->_jb[30]; + r->r_regs[R_T12] = jb->_jb[31]; + r->r_regs[R_AT] = jb->_jb[32]; + r->r_regs[R_GP] = jb->_jb[33]; + r->r_regs[R_SP] = jb->_jb[34]; + r->r_regs[R_ZERO] = jb->_jb[35]; +} + +void +libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +{ +} diff --git a/lib/libthread_db/arch/alpha/libpthread_md.c b/lib/libthread_db/arch/alpha/libpthread_md.c new file mode 100644 index 000000000000..49593875932a --- /dev/null +++ b/lib/libthread_db/arch/alpha/libpthread_md.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +void +pt_reg_to_ucontext(const struct reg *r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_reg(const ucontext_t *uc, struct reg *r) +{ +} + +void +pt_fpreg_to_ucontext(const struct fpreg* r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_fpreg(const ucontext_t *uc, struct fpreg *r) +{ +} + +void +pt_md_init(void) +{ +} + +int +pt_reg_sstep(struct reg *reg, int step) +{ + return (0); +} diff --git a/lib/libthread_db/arch/amd64/libc_r_md.c b/lib/libthread_db/arch/amd64/libc_r_md.c new file mode 100644 index 000000000000..6c53953235be --- /dev/null +++ b/lib/libthread_db/arch/amd64/libc_r_md.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +void +libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +{ +} + +void +libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +{ +} diff --git a/lib/libthread_db/arch/amd64/libpthread_md.c b/lib/libthread_db/arch/amd64/libpthread_md.c new file mode 100644 index 000000000000..49593875932a --- /dev/null +++ b/lib/libthread_db/arch/amd64/libpthread_md.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +void +pt_reg_to_ucontext(const struct reg *r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_reg(const ucontext_t *uc, struct reg *r) +{ +} + +void +pt_fpreg_to_ucontext(const struct fpreg* r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_fpreg(const ucontext_t *uc, struct fpreg *r) +{ +} + +void +pt_md_init(void) +{ +} + +int +pt_reg_sstep(struct reg *reg, int step) +{ + return (0); +} diff --git a/lib/libthread_db/arch/i386/libc_r_md.c b/lib/libthread_db/arch/i386/libc_r_md.c new file mode 100644 index 000000000000..de27b682a804 --- /dev/null +++ b/lib/libthread_db/arch/i386/libc_r_md.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +void +libc_r_md_getgregs(jmp_buf jb, prgregset_t r) +{ + r->r_eip = jb->_jb[0]; + r->r_ebx = jb->_jb[1]; + r->r_esp = jb->_jb[2]; + r->r_ebp = jb->_jb[3]; + r->r_esi = jb->_jb[4]; + r->r_edi = jb->_jb[5]; + r->r_eax = jb->_jb[6]; +} + +void +libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +{ +} diff --git a/lib/libthread_db/pthread/pthread_db_i386.c b/lib/libthread_db/arch/i386/libpthread_md.c similarity index 99% rename from lib/libthread_db/pthread/pthread_db_i386.c rename to lib/libthread_db/arch/i386/libpthread_md.c index 4875b74cd7f6..86bb88d33689 100644 --- a/lib/libthread_db/pthread/pthread_db_i386.c +++ b/lib/libthread_db/arch/i386/libpthread_md.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "pthread_db.h" +#include "libpthread_db.h" static int has_xmm_regs; diff --git a/lib/libthread_db/arch/ia64/libc_r_md.c b/lib/libthread_db/arch/ia64/libc_r_md.c new file mode 100644 index 000000000000..6c53953235be --- /dev/null +++ b/lib/libthread_db/arch/ia64/libc_r_md.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +void +libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +{ +} + +void +libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +{ +} diff --git a/lib/libthread_db/arch/ia64/libpthread_md.c b/lib/libthread_db/arch/ia64/libpthread_md.c new file mode 100644 index 000000000000..49593875932a --- /dev/null +++ b/lib/libthread_db/arch/ia64/libpthread_md.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +void +pt_reg_to_ucontext(const struct reg *r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_reg(const ucontext_t *uc, struct reg *r) +{ +} + +void +pt_fpreg_to_ucontext(const struct fpreg* r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_fpreg(const ucontext_t *uc, struct fpreg *r) +{ +} + +void +pt_md_init(void) +{ +} + +int +pt_reg_sstep(struct reg *reg, int step) +{ + return (0); +} diff --git a/lib/libthread_db/arch/sparc64/libc_r_md.c b/lib/libthread_db/arch/sparc64/libc_r_md.c new file mode 100644 index 000000000000..6c53953235be --- /dev/null +++ b/lib/libthread_db/arch/sparc64/libc_r_md.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +void +libc_r_md_getgregs(jmp_buf jb, prgregset_t *r) +{ +} + +void +libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r) +{ +} diff --git a/lib/libthread_db/arch/sparc64/libpthread_md.c b/lib/libthread_db/arch/sparc64/libpthread_md.c new file mode 100644 index 000000000000..49593875932a --- /dev/null +++ b/lib/libthread_db/arch/sparc64/libpthread_md.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +void +pt_reg_to_ucontext(const struct reg *r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_reg(const ucontext_t *uc, struct reg *r) +{ +} + +void +pt_fpreg_to_ucontext(const struct fpreg* r, ucontext_t *uc) +{ +} + +void +pt_ucontext_to_fpreg(const ucontext_t *uc, struct fpreg *r) +{ +} + +void +pt_md_init(void) +{ +} + +int +pt_reg_sstep(struct reg *reg, int step) +{ + return (0); +} diff --git a/lib/libthread_db/include/thread_db.h b/lib/libthread_db/include/thread_db.h deleted file mode 100644 index 82c8dc252aa2..000000000000 --- a/lib/libthread_db/include/thread_db.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2004 David Xu - * 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 REGENTS 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 REGENTS 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. - * - * $FreeBSD$ - */ - -#ifndef _THREAD_DB_H_ -#define _THREAD_DB_H_ - -#include -#include - -typedef enum -{ - TD_OK, - TD_ERR, - TD_NOTHR, - TD_NOSV, - TD_NOLWP, - TD_BADPH, - TD_BADTH, - TD_BADSH, - TD_BADTA, - TD_BADKEY, - TD_NOMSG, - TD_NOFPREGS, - TD_NOLIBTHREAD, - TD_NOEVENT, - TD_NOCAPAB, - TD_DBERR, - TD_NOAPLIC, - TD_NOTSD, - TD_MALLOC, - TD_PARTIALREG, - TD_NOXREGS -} td_err_e; - -typedef enum -{ - TD_THR_ANY_STATE, - TD_THR_UNKNOWN, - TD_THR_STOPPED, - TD_THR_RUN, - TD_THR_ACTIVE, - TD_THR_ZOMBIE, - TD_THR_SLEEP, - TD_THR_STOPPED_ASLEEP -} td_thr_state_e; - -typedef enum -{ - TD_THR_ANY_TYPE, - TD_THR_USER, - TD_THR_SYSTEM -} td_thr_type_e; - -typedef long thread_t; -typedef pthread_key_t thread_key_t; -typedef struct td_thragent td_thragent_t; - -typedef struct td_thrhandle -{ - td_thragent_t *th_ta_p; - thread_t th_unique; - int th_ta_data; -} td_thrhandle_t; - -/* Flags for `td_ta_thr_iter'. */ -#define TD_THR_ANY_USER_FLAGS 0xffffffff -#define TD_THR_LOWEST_PRIORITY 0 -#define TD_SIGNO_MASK NULL - -typedef uint32_t td_thr_events_t; - -typedef enum -{ - TD_ALL_EVENTS, - TD_EVENT_NONE = TD_ALL_EVENTS, - TD_CREATE, - TD_DEATH, - TD_REAP, - TD_READY, - TD_SLEEP, - TD_SWITCHTO, - TD_SWITCHFROM, - TD_LOCK_TRY, - TD_CATCHSIG, - TD_IDLE, - TD_PREEMPT, - TD_PRI_INHERIT, - TD_CONCURRENCY, - TD_TIMEOUT, - TD_MIN_EVENT_NUM = TD_READY, - TD_MAX_EVENT_NUM = TD_TIMEOUT, - TD_EVENTS_ENABLE = 31 -} td_event_e; - -typedef enum -{ - NOTIFY_BPT, - NOTIFY_AUTOBPT, - NOTIFY_SYSCALL -} td_notify_e; - -typedef struct td_notify -{ - td_notify_e type; - union { - psaddr_t bptaddr; - int syscallno; - } u; -} td_notify_t; - -typedef struct td_event_msg -{ - td_event_e event; - const td_thrhandle_t *th_p; - union { -#if 0 - td_synchandle_t *sh; -#endif - uintptr_t data; - } msg; -} td_event_msg_t; - -/* Structure containing event data available in each thread structure. */ -typedef struct -{ - td_thr_events_t eventmask; /* Mask of enabled events. */ - td_event_e eventnum; /* Number of last event. */ - void *eventdata; /* Data associated with event. */ -} td_eventbuf_t; - -/* Gathered statistics about the process. */ -typedef struct td_ta_stats -{ - int nthreads; /* Total number of threads in use. */ - int r_concurrency; /* Concurrency level requested by user. */ - int nrunnable_num; /* Average runnable threads, numerator. */ - int nrunnable_den; /* Average runnable threads, denominator. */ - int a_concurrency_num; /* Achieved concurrency level, numerator. */ - int a_concurrency_den; /* Achieved concurrency level, denominator. */ - int nlwps_num; /* Average number of processes in use, - numerator. */ - int nlwps_den; /* Average number of processes in use, - denominator. */ - int nidle_num; /* Average number of idling processes, - numerator. */ - int nidle_den; /* Average number of idling processes, - denominator. */ -} td_ta_stats_t; - -static inline void -td_event_emptyset(td_thr_events_t *setp) -{ - *setp = 0; -} - -static inline void -td_event_fillset(td_thr_events_t *setp) -{ - *setp = 0xFFFFFFFF; -} - -static inline void -td_event_addset(td_thr_events_t *setp, int n) -{ - *setp |= (1 << (n-1)); -} - -static inline void -td_event_delset(td_thr_events_t *setp, int n) -{ - *setp &= ~(1 << (n-1)); -} - -static inline int -td_eventismember(td_thr_events_t *setp, int n) -{ - return (*setp & (1 << (n-1)) ? 1 : 0); -} - -static inline int -td_eventisempty(td_thr_events_t *setp) -{ - return (*setp == 0); -} - -typedef int td_thr_iter_f(const td_thrhandle_t *, void *); -typedef int td_key_iter_f(thread_key_t, void (*) (void *), void *); - -struct ps_prochandle; - -typedef struct td_thrinfo -{ - td_thragent_t *ti_ta_p; - unsigned int ti_user_flags; - thread_t ti_tid; - char *ti_tls; - psaddr_t ti_startfunc; - psaddr_t ti_stkbase; - long int ti_stksize; - psaddr_t ti_ro_area; - int ti_ro_size; - td_thr_state_e ti_state; - unsigned char ti_db_suspended; - td_thr_type_e ti_type; - intptr_t ti_pc; - intptr_t ti_sp; - short int ti_flags; - int ti_pri; - lwpid_t ti_lid; - sigset_t ti_sigmask; - unsigned char ti_traceme; - unsigned char ti_preemptflag; - unsigned char ti_pirecflag; - sigset_t ti_pending; - td_thr_events_t ti_events; -} td_thrinfo_t; - -td_err_e td_init(void); -td_err_e td_log(void); -td_err_e td_ta_new(struct ps_prochandle *, td_thragent_t **); -td_err_e td_ta_delete(td_thragent_t *); -td_err_e td_ta_get_nthreads(const td_thragent_t *, int *); -td_err_e td_ta_get_ph(const td_thragent_t *, struct ps_prochandle **); -td_err_e td_ta_map_id2thr(const td_thragent_t *, thread_t, td_thrhandle_t *); -td_err_e td_ta_map_lwp2thr(const td_thragent_t *, lwpid_t lwpid, - td_thrhandle_t *); -td_err_e td_ta_thr_iter(const td_thragent_t *, td_thr_iter_f *, void *, - td_thr_state_e, int, sigset_t *, unsigned int); -td_err_e td_ta_tsd_iter(const td_thragent_t *, td_key_iter_f *, void *); -td_err_e td_ta_event_addr(const td_thragent_t *, td_event_e , td_notify_t *); -td_err_e td_ta_set_event(const td_thragent_t *, td_thr_events_t *); -td_err_e td_ta_clear_event(const td_thragent_t *, td_thr_events_t *); -td_err_e td_ta_event_getmsg(const td_thragent_t *, td_event_msg_t *); -td_err_e td_ta_setconcurrency(const td_thragent_t *, int); -td_err_e td_ta_enable_stats(const td_thragent_t *, int); -td_err_e td_ta_reset_stats(const td_thragent_t *); -td_err_e td_ta_get_stats(const td_thragent_t *, td_ta_stats_t *); -td_err_e td_thr_validate(const td_thrhandle_t *); -td_err_e td_thr_get_info(const td_thrhandle_t *, td_thrinfo_t *); -td_err_e td_thr_getfpregs(const td_thrhandle_t *, prfpregset_t *); -td_err_e td_thr_getgregs(const td_thrhandle_t *, prgregset_t); -td_err_e td_thr_getxregs(const td_thrhandle_t *, void *); -td_err_e td_thr_getxregsize(const td_thrhandle_t *, int *); -td_err_e td_thr_setfpregs(const td_thrhandle_t *, const prfpregset_t *); -td_err_e td_thr_setgregs(const td_thrhandle_t *, const prgregset_t); -td_err_e td_thr_setxregs(const td_thrhandle_t *, const void *); -td_err_e td_thr_event_enable(const td_thrhandle_t *, int); -td_err_e td_thr_set_event(const td_thrhandle_t *, td_thr_events_t *); -td_err_e td_thr_clear_event(const td_thrhandle_t *, td_thr_events_t *); -td_err_e td_thr_event_getmsg(const td_thrhandle_t *, td_event_msg_t *); -td_err_e td_thr_setprio(const td_thrhandle_t *, int); -td_err_e td_thr_setsigpending(const td_thrhandle_t *, unsigned char, - const sigset_t *); -td_err_e td_thr_sigsetmask(const td_thrhandle_t *, const sigset_t *); -td_err_e td_thr_tsd(const td_thrhandle_t *, const thread_key_t, void **); -td_err_e td_thr_dbsuspend(const td_thrhandle_t *); -td_err_e td_thr_dbresume(const td_thrhandle_t *); -td_err_e td_get_ta(int pid, td_thragent_t **); -td_err_e td_ta_activated(td_thragent_t *, int *); -td_err_e td_thr_sstep(td_thrhandle_t *, int); - -#endif diff --git a/lib/libthread_db/libc_r_db.c b/lib/libthread_db/libc_r_db.c new file mode 100644 index 000000000000..c141f0eb46e5 --- /dev/null +++ b/lib/libthread_db/libc_r_db.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "thread_db_int.h" + +void libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *); +void libc_r_md_getgregs(jmp_buf jb, prgregset_t); + +struct td_thragent { + TD_THRAGENT_FIELDS; + struct ps_prochandle *ta_ph; + psaddr_t ta_thread_initial; + psaddr_t ta_thread_list; + psaddr_t ta_thread_run; + int ta_ofs_ctx; + int ta_ofs_next; + int ta_ofs_uniqueid; +}; + +static td_err_e +libc_r_db_init() +{ + return (TD_OK); +} + +static td_err_e +libc_r_db_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_ta_delete(td_thragent_t *ta) +{ + free(ta); + return (TD_OK); +} + +static td_err_e +libc_r_db_ta_event_addr(const td_thragent_t *ta, td_thr_events_e ev, + td_notify_t *n) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_ta_map_id2thr(const td_thragent_t *ta, thread_t tid, + td_thrhandle_t *th) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, + td_thrhandle_t *th) +{ + psaddr_t addr; + ps_err_e err; + + th->th_ta = ta; + err = ps_pread(ta->ta_ph, ta->ta_thread_initial, &addr, sizeof(addr)); + if (err != PS_OK) + return (TD_ERR); + if (addr == NULL) + return (TD_NOLWP); + err = ps_pread(ta->ta_ph, ta->ta_thread_run, &th->th_thread, + sizeof(psaddr_t)); + return ((err == PS_OK) ? TD_OK : TD_ERR); +} + +static td_err_e +libc_r_db_ta_new(struct ps_prochandle *ph, td_thragent_t **ta_p) +{ + td_thragent_t *ta; + psaddr_t addr; + ps_err_e err; + + ta = malloc(sizeof(td_thragent_t)); + if (ta == NULL) + return (TD_MALLOC); + + ta->ta_ph = ph; + + err = ps_pglobal_lookup(ph, NULL, "_thread_initial", + &ta->ta_thread_initial); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_list", &ta->ta_thread_list); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_run", &ta->ta_thread_run); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_ctx_offset", &addr); + if (err != PS_OK) + goto fail; + err = ps_pread(ph, addr, &ta->ta_ofs_ctx, sizeof(int)); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_next_offset", &addr); + if (err != PS_OK) + goto fail; + err = ps_pread(ph, addr, &ta->ta_ofs_next, sizeof(int)); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_uniqueid_offset", &addr); + if (err != PS_OK) + goto fail; + err = ps_pread(ph, addr, &ta->ta_ofs_uniqueid, sizeof(int)); + if (err != PS_OK) + goto fail; + + *ta_p = ta; + return (TD_OK); + + fail: + free(ta); + *ta_p = NULL; + return (TD_ERR); +} + +static td_err_e +libc_r_db_ta_set_event(const td_thragent_t *ta, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *cb, void *data, + td_thr_state_e state, int pri, sigset_t *mask, unsigned int flags) +{ + td_thrhandle_t th; + psaddr_t addr; + ps_err_e err; + + th.th_ta = ta; + + err = ps_pread(ta->ta_ph, ta->ta_thread_list, &th.th_thread, + sizeof(th.th_thread)); + if (err != PS_OK) + return (TD_ERR); + while (th.th_thread != NULL) { + if (cb(&th, data) != 0) + return (TD_OK); + addr = (psaddr_t)((uintptr_t)th.th_thread + ta->ta_ofs_next); + err = ps_pread(ta->ta_ph, addr, &th.th_thread, + sizeof(th.th_thread)); + if (err != PS_OK) + return (TD_ERR); + } + return (TD_OK); +} + +static td_err_e +libc_r_db_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_thr_event_enable(const td_thrhandle_t *th, int oo) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *ti) +{ + const td_thragent_t *ta; + psaddr_t addr, current; + ps_err_e err; + + ta = th->th_ta; + ti->ti_ta_p = ta; + err = ps_pread(ta->ta_ph, ta->ta_thread_run, ¤t, + sizeof(psaddr_t)); + if (err != PS_OK) + return (TD_ERR); + ti->ti_lid = (th->th_thread == current) ? -1 : 0; + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_uniqueid); + err = ps_pread(ta->ta_ph, addr, &ti->ti_tid, sizeof(thread_t)); + /* libc_r numbers its threads starting with 0. Not smart. */ + ti->ti_tid++; + return ((err == PS_OK) ? TD_OK : TD_ERR); +} + +static td_err_e +libc_r_db_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *r) +{ + jmp_buf jb; + const td_thragent_t *ta; + psaddr_t addr; + ps_err_e err; + + ta = th->th_ta; + err = ps_lgetfpregs(ta->ta_ph, -1, r); + if (err != PS_OK) + return (TD_ERR); + err = ps_pread(ta->ta_ph, ta->ta_thread_run, &addr, sizeof(psaddr_t)); + if (err != PS_OK) + return (TD_ERR); + if (th->th_thread == addr) + return (TD_OK); + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_ctx); + err = ps_pread(ta->ta_ph, addr, jb, sizeof(jb)); + if (err != PS_OK) + return (TD_ERR); + libc_r_md_getfpregs(jb, r); + return (TD_OK); +} + +static td_err_e +libc_r_db_thr_getgregs(const td_thrhandle_t *th, prgregset_t r) +{ + jmp_buf jb; + const td_thragent_t *ta; + psaddr_t addr; + ps_err_e err; + + ta = th->th_ta; + err = ps_lgetregs(ta->ta_ph, -1, r); + if (err != PS_OK) + return (TD_ERR); + err = ps_pread(ta->ta_ph, ta->ta_thread_run, &addr, sizeof(psaddr_t)); + if (err != PS_OK) + return (TD_ERR); + if (th->th_thread == addr) + return (TD_OK); + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_ctx); + err = ps_pread(ta->ta_ph, addr, jb, sizeof(jb)); + if (err != PS_OK) + return (TD_ERR); + libc_r_md_getgregs(jb, r); + return (TD_OK); +} + +static td_err_e +libc_r_db_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *r) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_thr_setgregs(const td_thrhandle_t *th, const prgregset_t r) +{ + return (TD_ERR); +} + +static td_err_e +libc_r_db_thr_validate(const td_thrhandle_t *th) +{ + return (TD_ERR); +} + +struct ta_ops libc_r_db_ops = { + .to_init = libc_r_db_init, + + .to_ta_clear_event = libc_r_db_ta_clear_event, + .to_ta_delete = libc_r_db_ta_delete, + .to_ta_event_addr = libc_r_db_ta_event_addr, + .to_ta_event_getmsg = libc_r_db_ta_event_getmsg, + .to_ta_map_id2thr = libc_r_db_ta_map_id2thr, + .to_ta_map_lwp2thr = libc_r_db_ta_map_lwp2thr, + .to_ta_new = libc_r_db_ta_new, + .to_ta_set_event = libc_r_db_ta_set_event, + .to_ta_thr_iter = libc_r_db_ta_thr_iter, + + .to_thr_clear_event = libc_r_db_thr_clear_event, + .to_thr_event_enable = libc_r_db_thr_event_enable, + .to_thr_event_getmsg = libc_r_db_thr_event_getmsg, + .to_thr_get_info = libc_r_db_thr_get_info, + .to_thr_getfpregs = libc_r_db_thr_getfpregs, + .to_thr_getgregs = libc_r_db_thr_getgregs, + .to_thr_set_event = libc_r_db_thr_set_event, + .to_thr_setfpregs = libc_r_db_thr_setfpregs, + .to_thr_setgregs = libc_r_db_thr_setgregs, + .to_thr_validate = libc_r_db_thr_validate +}; diff --git a/lib/libthread_db/pthread/pthread_db.c b/lib/libthread_db/libpthread_db.c similarity index 56% rename from lib/libthread_db/pthread/pthread_db.c rename to lib/libthread_db/libpthread_db.c index 9a468b34cdcb..0afb689acdd4 100644 --- a/lib/libthread_db/pthread/pthread_db.c +++ b/lib/libthread_db/libpthread_db.c @@ -32,34 +32,18 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include #include -#include "pthread_db.h" - -struct pt_map { - enum { - PT_NONE, - PT_USER, - PT_LWP - } type; - - union { - lwpid_t lwp; - psaddr_t thr; - }; -}; +#include "libpthread.h" +#include "libpthread_db.h" #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 void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp); static int pt_validate(const td_thrhandle_t *th); static int @@ -85,890 +69,10 @@ ps2td(int c) } } -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) +pt_map_thread(const td_thragent_t *const_ta, psaddr_t pt, int type) { + td_thragent_t *ta = __DECONST(td_thragent_t *, const_ta); struct pt_map *new; int i, first = -1; @@ -1007,22 +111,669 @@ _map_thread(pt_thragent_t *ta, psaddr_t pt, int type) return (first); } -static long -pt_map_thread(const pt_thragent_t *ta, psaddr_t pt) +static td_err_e +pt_init(void) { - return _map_thread((pt_thragent_t *)ta, pt, PT_USER); + pt_md_init(); + return (0); } -#if 0 -static long -pt_map_lwp(const pt_thragent_t *ta, lwpid_t lwp) +static td_err_e +pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) { - return _map_thread((pt_thragent_t *)ta, (psaddr_t)lwp, PT_LWP); +#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; \ + } + + td_thragent_t *ta; + int dbg; + int ret; + + TDBG_FUNC(); + + ta = malloc(sizeof(td_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_pwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int)); + *pta = ta; + return (0); + +error: + free(ta); + return (ret); +} + +static td_err_e +pt_ta_delete(td_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_pwrite(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_map_id2thr(const td_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_pread(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_pread(ta->ph, + pt + offsetof(struct pthread, tcb), + &tcb_addr, sizeof(tcb_addr)); + if (ret != 0) + return (P2T(ret)); + ret = ps_pread(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_pread(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_pread(ta->ph, + pt + offsetof(struct pthread, tcb), + &tcb_addr, sizeof(tcb_addr)); + if (ret != 0) + return (P2T(ret)); + /* get next thread */ + ret = ps_pread(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 = ta; + th->th_tid = id; + return (TD_OK); +} + +static td_err_e +pt_ta_map_lwp2thr(const td_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_pread(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_pread(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_pread(ta->ph, ptr, &tmp_lwp, sizeof(lwpid_t)); + if (ret != 0) + return (P2T(ret)); + if (tmp_lwp == lwp) { + th->th_ta = ta; + th->th_tid = pt_map_thread(ta, pt, PT_USER); + if (th->th_tid == -1) + return (TD_MALLOC); + pt_unmap_lwp(ta, lwp); + return (TD_OK); + } + + /* get next thread */ + ret = ps_pread(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 td_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; + ps_err_e pserr; + int activated; + + TDBG_FUNC(); + + pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated, + sizeof(int)); + if (pserr != PS_OK) + return (P2T(pserr)); + if (!activated) + return (TD_OK); + + pserr = ps_pread(ta->ph, ta->thread_list_addr, &thread_list, + sizeof(thread_list)); + if (pserr != 0) + return (P2T(pserr)); + pt = (psaddr_t)thread_list.tqh_first; + while (pt != 0) { + th.th_ta = ta; + th.th_tid = pt_map_thread(ta, pt, PT_USER); + /* should we unmap lwp here ? */ + if (th.th_tid == -1) + return (TD_MALLOC); + if ((*callback)(&th, cbdata_p)) + return (TD_DBERR); + /* get next thread */ + pserr = ps_pread(ta->ph, + pt + offsetof(struct pthread, tle.tqe_next), &pt, + sizeof(pt)); + if (pserr != PS_OK) + return (P2T(pserr)); + } + return (TD_OK); +} + +static td_err_e +pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg) +{ + struct pthread_key keytable[PTHREAD_KEYS_MAX]; + int i, ret; + + TDBG_FUNC(); + + ret = ps_pread(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 td_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 td_thragent_t *ta, td_thr_events_t *events) +{ + TDBG_FUNC(); + return (TD_ERR); +} + +static td_err_e +pt_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) +{ + TDBG_FUNC(); + return (TD_ERR); +} + +static td_err_e +pt_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) +{ + TDBG_FUNC(); + return (TD_NOMSG); +} + +static td_err_e +pt_thr_dbresume(const td_thrhandle_t *th) +{ + TDBG_FUNC(); + return (TD_ERR); +} + +static td_err_e +pt_thr_dbsuspend(const td_thrhandle_t *th) +{ + TDBG_FUNC(); + return (TD_ERR); +} + +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(th->th_ta, th->th_tid, + &temp); + return (P2T(ret)); +} + +static td_err_e +pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) +{ + const td_thragent_t *ta = th->th_ta; + struct pthread pt; + int ret; + + TDBG_FUNC(); + + ret = pt_validate(th); + if (ret) + return (ret); + + memset(info, 0, sizeof(*info)); + if (ta->map[th->th_tid].type == PT_LWP) { + info->ti_type = TD_THR_SYSTEM; + info->ti_lid = ta->map[th->th_tid].lwp; + info->ti_tid = th->th_tid; + info->ti_state = TD_THR_RUN; + info->ti_type = TD_THR_SYSTEM; + return (TD_OK); + } + + ret = ps_pread(ta->ph, (psaddr_t)(ta->map[th->th_tid].thr), + &pt, sizeof(pt)); + if (ret != 0) + return (P2T(ret)); + if (pt.magic != THR_MAGIC) + return (TD_BADTH); + ret = ps_pread(ta->ph, + ((psaddr_t)pt.tcb) + offsetof(struct tcb, tcb_tmbx.tm_lwp), + &info->ti_lid, sizeof(lwpid_t)); + if (ret != 0) + return (P2T(ret)); + + info->ti_ta_p = th->th_ta; + info->ti_tid = th->th_tid; + 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 = 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) +{ + const td_thragent_t *ta = th->th_ta; + struct kse_thr_mailbox tmbx; + 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_tid].type == PT_LWP) { + ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); + return (P2T(ret)); + } + + ret = ps_pread(ta->ph, ta->map[th->th_tid].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_pread(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_pread(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) +{ + const td_thragent_t *ta = th->th_ta; + struct kse_thr_mailbox tmbx; + 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_tid].type == PT_LWP) { + ret = ps_lgetregs(ta->ph, + ta->map[th->th_tid].lwp, gregs); + return (P2T(ret)); + } + + ret = ps_pread(ta->ph, ta->map[th->th_tid].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_pread(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_pread(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_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + const td_thragent_t *ta = th->th_ta; + struct kse_thr_mailbox tmbx; + 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_tid].type == PT_LWP) { + ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs); + return (P2T(ret)); + } + + ret = ps_pread(ta->ph, ta->map[th->th_tid].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_pread(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_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); + if (ret != 0) + return (P2T(ret)); + + pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context); + ret = ps_pwrite(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) +{ + const td_thragent_t *ta = th->th_ta; + struct kse_thr_mailbox tmbx; + 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_tid].type == PT_LWP) { + ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs); + return (P2T(ret)); + } + + ret = ps_pread(ta->ph, ta->map[th->th_tid].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_pread(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_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); + if (ret != 0) + return (P2T(ret)); + pt_reg_to_ucontext(gregs, &tmbx.tm_context); + ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx)); + return (P2T(ret)); +} + +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_sstep(const td_thrhandle_t *th, int step) +{ + const td_thragent_t *ta = th->th_ta; + struct kse_thr_mailbox tmbx; + struct reg regs; + 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_tid].type == PT_LWP) + return (TD_BADTH); + + ret = ps_pread(ta->ph, ta->map[th->th_tid].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_pwrite(ta->ph, tcb_addr + offsetof(struct tcb, + tcb_tmbx.tm_dflags), &tmp, sizeof(tmp)); + if (ret != 0) + return (P2T(ret)); + /* Get lwp */ + ret = ps_pread(ta->ph, tcb_addr + offsetof(struct tcb, + tcb_tmbx.tm_lwp), &lwp, sizeof(lwpid_t)); + if (ret != 0) + return (P2T(ret)); + if (lwp != 0) + return (TD_BADTH); + + 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_pread(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_pwrite(ta->ph, tmbx_addr, &tmbx, + sizeof(tmbx)); + } + } + return (P2T(ret)); } -#endif static void -pt_unmap_lwp(const pt_thragent_t *ta, lwpid_t lwp) +pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp) { int i; @@ -1037,51 +788,38 @@ pt_unmap_lwp(const pt_thragent_t *ta, lwpid_t lwp) 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) + if (th->th_tid < 0 || th->th_tid >= th->th_ta->map_len || + th->th_ta->map[th->th_tid].type == PT_NONE) return (TD_NOTHR); return (TD_OK); } -struct ta_ops pthread_ops = { +struct ta_ops libpthread_db_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_ta_clear_event = pt_ta_clear_event, + .to_ta_delete = pt_ta_delete, + .to_ta_event_addr = pt_ta_event_addr, + .to_ta_event_getmsg = pt_ta_event_getmsg, + .to_ta_map_id2thr = pt_ta_map_id2thr, + .to_ta_map_lwp2thr = pt_ta_map_lwp2thr, + .to_ta_new = pt_ta_new, + .to_ta_set_event = pt_ta_set_event, + .to_ta_thr_iter = pt_ta_thr_iter, + .to_ta_tsd_iter = pt_ta_tsd_iter, + .to_thr_clear_event = pt_thr_clear_event, + .to_thr_dbresume = pt_thr_dbresume, + .to_thr_dbsuspend = pt_thr_dbsuspend, + .to_thr_event_enable = pt_thr_event_enable, + .to_thr_event_getmsg = pt_thr_event_getmsg, .to_thr_get_info = pt_thr_get_info, - .to_thr_getfpregs = (void *)pt_thr_getfpregs, + .to_thr_getfpregs = pt_thr_getfpregs, .to_thr_getgregs = pt_thr_getgregs, - .to_thr_getxregs = pt_thr_getxregs, - .to_thr_getxregsize = pt_thr_getxregsize, + .to_thr_set_event = pt_thr_set_event, .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 + .to_thr_validate = pt_thr_validate, + + /* FreeBSD specific extensions. */ + .to_thr_sstep = pt_thr_sstep, }; diff --git a/lib/libthread_db/pthread/pthread_db.h b/lib/libthread_db/libpthread_db.h similarity index 78% rename from lib/libthread_db/pthread/pthread_db.h rename to lib/libthread_db/libpthread_db.h index 49dcdd7ca9ec..397ec72a5682 100644 --- a/lib/libthread_db/pthread/pthread_db.h +++ b/lib/libthread_db/libpthread_db.h @@ -26,29 +26,39 @@ * $FreeBSD$ */ -#ifndef _PTHREAD_DB_H -#define _PTHREAD_DB_H +#ifndef _LIBPTHREAD_DB_H_ +#define _LIBPTHREAD_DB_H_ #include #include #include "thread_db_int.h" -struct pt_thragent { - struct td_thragent base; - struct ps_prochandle *ph; - psaddr_t libkse_debug_addr; - psaddr_t thread_list_addr; - psaddr_t thread_listgen_addr; - psaddr_t thread_activated_addr; - psaddr_t thread_active_threads_addr; - psaddr_t thread_keytable_addr; - int thread_activated; - struct pt_map *map; - int map_len; +struct pt_map { + enum { + PT_NONE, + PT_USER, + PT_LWP + } type; + + union { + lwpid_t lwp; + psaddr_t thr; + }; }; -typedef struct pt_thragent pt_thragent_t; +struct td_thragent { + TD_THRAGENT_FIELDS; + psaddr_t libkse_debug_addr; + psaddr_t thread_list_addr; + psaddr_t thread_listgen_addr; + psaddr_t thread_activated_addr; + psaddr_t thread_active_threads_addr; + psaddr_t thread_keytable_addr; + int thread_activated; + struct pt_map *map; + int map_len; +}; void pt_md_init(void); void pt_reg_to_ucontext(const struct reg *, ucontext_t *); @@ -57,4 +67,4 @@ void pt_fpreg_to_ucontext(const struct fpreg *, ucontext_t *); void pt_ucontext_to_fpreg(const ucontext_t *, struct fpreg *); int pt_reg_sstep(struct reg *reg, int step); -#endif +#endif /* _LIBPTHREAD_DB_H_ */ diff --git a/lib/libthread_db/libthr_db.c b/lib/libthread_db/libthr_db.c new file mode 100644 index 000000000000..878fcb05acd5 --- /dev/null +++ b/lib/libthread_db/libthr_db.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "thread_db_int.h" + +struct td_thragent { + TD_THRAGENT_FIELDS; + struct ps_prochandle *ta_ph; + psaddr_t ta_thread_list; + int ta_ofs_ctx; + int ta_ofs_next; + int ta_ofs_thr_id; +}; + +static td_err_e +libthr_db_init() +{ + return (TD_OK); +} + +static td_err_e +libthr_db_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_ta_delete(td_thragent_t *ta) +{ + free(ta); + return (TD_OK); +} + +static td_err_e +libthr_db_ta_event_addr(const td_thragent_t *ta, td_thr_events_e event, + td_notify_t *n) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_ta_map_id2thr(const td_thragent_t *ta, thread_t tid, + td_thrhandle_t *th) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, + td_thrhandle_t *th) +{ + psaddr_t addr; + thread_t tid; + ps_err_e err; + + th->th_ta = ta; + + err = ps_pread(ta->ta_ph, ta->ta_thread_list, &th->th_thread, + sizeof(th->th_thread)); + if (err != PS_OK) + return (TD_ERR); + while (th->th_thread != NULL) { + addr = (psaddr_t)((uintptr_t)th->th_thread + + ta->ta_ofs_thr_id); + err = ps_pread(ta->ta_ph, addr, &tid, sizeof(thread_t)); + if (err != PS_OK) + return (TD_ERR); + if (tid == lwpid) + return (TD_OK); + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_next); + err = ps_pread(ta->ta_ph, addr, &th->th_thread, + sizeof(th->th_thread)); + if (err != PS_OK) + return (TD_ERR); + } + return (TD_NOLWP); +} + +static td_err_e +libthr_db_ta_new(struct ps_prochandle *ph, td_thragent_t **ta_p) +{ + td_thragent_t *ta; + psaddr_t addr; + ps_err_e err; + + err = ps_pglobal_lookup(ph, NULL, "_libthr_debug", &addr); + if (err != PS_OK) + return (TD_NOLIBTHREAD); + + ta = malloc(sizeof(td_thragent_t)); + if (ta == NULL) + return (TD_MALLOC); + + ta->ta_ph = ph; + + err = ps_pglobal_lookup(ph, NULL, "_thread_list", &ta->ta_thread_list); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_ctx_offset", &addr); + if (err != PS_OK) + goto fail; + err = ps_pread(ph, addr, &ta->ta_ofs_ctx, sizeof(int)); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_next_offset", &addr); + if (err != PS_OK) + goto fail; + err = ps_pread(ph, addr, &ta->ta_ofs_next, sizeof(int)); + if (err != PS_OK) + goto fail; + err = ps_pglobal_lookup(ph, NULL, "_thread_thr_id_offset", &addr); + if (err != PS_OK) + goto fail; + err = ps_pread(ph, addr, &ta->ta_ofs_thr_id, sizeof(int)); + if (err != PS_OK) + goto fail; + + *ta_p = ta; + return (TD_OK); + + fail: + free(ta); + *ta_p = NULL; + return (TD_ERR); +} + +static td_err_e +libthr_db_ta_set_event(const td_thragent_t *ta, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *cb, void *data, + td_thr_state_e state, int pri, sigset_t *mask, unsigned int flags) +{ + td_thrhandle_t th; + psaddr_t addr; + ps_err_e err; + + th.th_ta = ta; + + err = ps_pread(ta->ta_ph, ta->ta_thread_list, &th.th_thread, + sizeof(th.th_thread)); + if (err != PS_OK) + return (TD_ERR); + while (th.th_thread != NULL) { + if (cb(&th, data) != 0) + return (TD_OK); + addr = (psaddr_t)((uintptr_t)th.th_thread + ta->ta_ofs_next); + err = ps_pread(ta->ta_ph, addr, &th.th_thread, + sizeof(th.th_thread)); + if (err != PS_OK) + return (TD_ERR); + } + return (TD_OK); +} + +static td_err_e +libthr_db_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_thr_event_enable(const td_thrhandle_t *th, int oo) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *ti) +{ + const td_thragent_t *ta; + psaddr_t addr; + thread_t tid; + ps_err_e err; + + ta = th->th_ta; + ti->ti_ta_p = ta; + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_thr_id); + err = ps_pread(ta->ta_ph, addr, &tid, sizeof(thread_t)); + ti->ti_lid = tid; + ti->ti_tid = tid; + return ((err == PS_OK) ? TD_OK : TD_ERR); +} + +static td_err_e +libthr_db_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *r) +{ + const td_thragent_t *ta; + psaddr_t addr; + thread_t tid; + ps_err_e err; + + ta = th->th_ta; + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_thr_id); + err = ps_pread(ta->ta_ph, addr, &tid, sizeof(thread_t)); + if (err != PS_OK) + return (TD_ERR); + err = ps_lgetfpregs(ta->ta_ph, tid, r); + return ((err == PS_OK) ? TD_OK : TD_ERR); +} + +static td_err_e +libthr_db_thr_getgregs(const td_thrhandle_t *th, prgregset_t r) +{ + const td_thragent_t *ta; + psaddr_t addr; + thread_t tid; + ps_err_e err; + + ta = th->th_ta; + addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_thr_id); + err = ps_pread(ta->ta_ph, addr, &tid, sizeof(thread_t)); + if (err != PS_OK) + return (TD_ERR); + err = ps_lgetregs(ta->ta_ph, tid, r); + return ((err == PS_OK) ? TD_OK : TD_ERR); +} + +static td_err_e +libthr_db_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *ev) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *r) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_thr_setgregs(const td_thrhandle_t *th, const prgregset_t r) +{ + return (TD_ERR); +} + +static td_err_e +libthr_db_thr_validate(const td_thrhandle_t *th) +{ + return (TD_ERR); +} + +struct ta_ops libthr_db_ops = { + .to_init = libthr_db_init, + + .to_ta_clear_event = libthr_db_ta_clear_event, + .to_ta_delete = libthr_db_ta_delete, + .to_ta_event_addr = libthr_db_ta_event_addr, + .to_ta_event_getmsg = libthr_db_ta_event_getmsg, + .to_ta_map_id2thr = libthr_db_ta_map_id2thr, + .to_ta_map_lwp2thr = libthr_db_ta_map_lwp2thr, + .to_ta_new = libthr_db_ta_new, + .to_ta_set_event = libthr_db_ta_set_event, + .to_ta_thr_iter = libthr_db_ta_thr_iter, + + .to_thr_clear_event = libthr_db_thr_clear_event, + .to_thr_event_enable = libthr_db_thr_event_enable, + .to_thr_event_getmsg = libthr_db_thr_event_getmsg, + .to_thr_get_info = libthr_db_thr_get_info, + .to_thr_getfpregs = libthr_db_thr_getfpregs, + .to_thr_getgregs = libthr_db_thr_getgregs, + .to_thr_set_event = libthr_db_thr_set_event, + .to_thr_setfpregs = libthr_db_thr_setfpregs, + .to_thr_setgregs = libthr_db_thr_setgregs, + .to_thr_validate = libthr_db_thr_validate +}; diff --git a/lib/libthread_db/pthread/Makefile b/lib/libthread_db/pthread/Makefile deleted file mode 100644 index cbd245d9b556..000000000000 --- a/lib/libthread_db/pthread/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ - -LIB=pthread_db -INTERNALLIB=yes -NOPROFILE=yes -NOPIC=yes -CFLAGS+=-DPTHREAD_KERNEL -fpic -DPIC -CFLAGS+=-I${.CURDIR}/../include \ - -I${.CURDIR}/../../libc/include -I${.CURDIR}/../../libpthread/thread \ - -I${.CURDIR}/../../../include -CFLAGS+=-I${.CURDIR}/../../libpthread/arch/${MACHINE_ARCH}/include -CFLAGS+=-I${.CURDIR}/../../libpthread/sys -CFLAGS+=-Wall - -.PATH: ${.CURDIR} - -SRCS+=pthread_db.c pthread_db_${MACHINE_ARCH}.c - -.include diff --git a/lib/libthread_db/src/Makefile b/lib/libthread_db/src/Makefile deleted file mode 100644 index 236e7bc21b49..000000000000 --- a/lib/libthread_db/src/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# $FreeBSD$ - -SHLIB_NAME=libthread_db.so.1 -NOPROFILE=yes -CFLAGS+=-Wall -I${.CURDIR}/../../../include -I${.CURDIR}/../include -LDADD=../pthread/libpthread_db.a - -PRECIOUSLIB=yes - -.PATH: ${.CURDIR} - -SRCS+=thread_db.c -INCS=../include/thread_db.h - -.include diff --git a/lib/libthread_db/src/thread_db.c b/lib/libthread_db/src/thread_db.c deleted file mode 100644 index 1e841c27f25c..000000000000 --- a/lib/libthread_db/src/thread_db.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) 2004 David Xu - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include "thread_db_int.h" - -static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); - -extern struct ta_ops pthread_ops; -#if 0 -extern struct ta_ops thr_ops; -extern struct ta_ops c_r_ops; -#endif - -static struct ta_ops *ops[] = { - &pthread_ops, -#if 0 - &thr_ops, - &c_r_ops -#endif -}; - -td_err_e -td_init(void) -{ - int i, ret = 0; - - for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { - int tmp; - if ((tmp = ops[i]->to_init()) != 0) - ret = tmp; - } - return (ret); -} - -td_err_e -td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) -{ - int i; - - for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { - if (ops[i]->to_ta_new(ph, pta) == 0) { - (*pta)->ta_ops = ops[i]; - TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); - return (0); - } - } - return (TD_NOLIBTHREAD); - -} - -td_err_e -td_ta_delete(td_thragent_t *ta) -{ - TAILQ_REMOVE(&proclist, ta, ta_next); - return ta->ta_ops->to_ta_delete(ta); -} - -td_err_e -td_ta_get_nthreads(const td_thragent_t *ta, int *np) -{ - return ta->ta_ops->to_ta_get_nthreads(ta, np); -} - -td_err_e -td_ta_get_ph(const td_thragent_t *ta, struct ps_prochandle **ph) -{ - return ta->ta_ops->to_ta_get_ph(ta, ph); -} - -td_err_e -td_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) -{ - return ta->ta_ops->to_ta_map_id2thr(ta, id, th); -} - -td_err_e -td_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) -{ - return ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th); -} - -td_err_e -td_ta_thr_iter(const td_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) -{ - return ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, - ti_pri, ti_sigmask_p, ti_user_flags); -} - -td_err_e -td_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg) -{ - return ta->ta_ops->to_ta_tsd_iter(ta, ki, arg); -} - -td_err_e -td_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) -{ - return ta->ta_ops->to_ta_event_addr(ta, event, ptr); -} - -td_err_e -td_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) -{ - return ta->ta_ops->to_ta_set_event(ta, events); -} - -td_err_e -td_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) -{ - return ta->ta_ops->to_ta_clear_event(ta, events); -} - -td_err_e -td_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) -{ - return ta->ta_ops->to_ta_event_getmsg(ta, msg); -} - -td_err_e -td_ta_setconcurrency(const td_thragent_t *ta, int level) -{ - return ta->ta_ops->to_ta_setconcurrency(ta, level); -} - -td_err_e -td_ta_enable_stats(const td_thragent_t *ta, int enable) -{ - return ta->ta_ops->to_ta_enable_stats(ta, enable); -} - -td_err_e -td_ta_reset_stats(const td_thragent_t *ta) -{ - return ta->ta_ops->to_ta_reset_stats(ta); -} - -td_err_e -td_ta_get_stats(const td_thragent_t *ta, td_ta_stats_t *statsp) -{ - return ta->ta_ops->to_ta_get_stats(ta, statsp); -} - -td_err_e -td_thr_validate(const td_thrhandle_t *th) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_validate(th); -} - -td_err_e -td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_get_info(th, info); -} - -td_err_e -td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_getfpregs(th, fpregset); -} - -td_err_e -td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_getgregs(th, gregs); -} - -td_err_e -td_thr_getxregs(const td_thrhandle_t *th, void *xregs) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_getxregs(th, xregs); -} - -td_err_e -td_thr_getxregsize(const td_thrhandle_t *th, int *sizep) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_getxregsize(th, sizep); -} - -td_err_e -td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_setfpregs(th, fpregs); -} - -td_err_e -td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_setgregs(th, gregs); -} - -td_err_e -td_thr_setxregs(const td_thrhandle_t *th, const void *addr) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_setxregs(th, addr); -} - -td_err_e -td_thr_event_enable(const td_thrhandle_t *th, int en) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_event_enable(th, en); -} - -td_err_e -td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *setp) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_set_event(th, setp); -} - -td_err_e -td_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *setp) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_clear_event(th, setp); -} - -td_err_e -td_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_event_getmsg(th, msg); -} - -td_err_e -td_thr_setprio(const td_thrhandle_t *th, int pri) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_setprio(th, pri); -} - -td_err_e -td_thr_setsigpending(const td_thrhandle_t *th, unsigned char n, - const sigset_t *set) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_setsigpending(th, n, set); -} - -td_err_e -td_thr_sigsetmask(const td_thrhandle_t *th, const sigset_t *set) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_sigsetmask(th, set); -} - -td_err_e -td_thr_tsd(const td_thrhandle_t *th, const thread_key_t key, void **data) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_tsd(th, key, data); -} - -td_err_e -td_thr_dbsuspend(const td_thrhandle_t *th) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_dbsuspend(th); -} - -td_err_e -td_thr_dbresume(const td_thrhandle_t *th) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_dbresume(th); -} - -td_err_e -td_get_ta(int pid, td_thragent_t **ta_p) -{ - td_thragent_t *ta; - struct ps_prochandle *ph; - - TAILQ_FOREACH(ta, &proclist, ta_next) { - td_ta_get_ph(ta, &ph); - if (ps_getpid(ph) == pid) { - *ta_p = ta; - return (TD_OK); - } - } - return (TD_ERR); -} - -td_err_e -td_ta_activated(td_thragent_t *ta, int *a) -{ - return ta->ta_ops->to_ta_activated(ta, a); -} - -td_err_e -td_thr_sstep(td_thrhandle_t *th, int step) -{ - td_thragent_t *ta = th->th_ta_p; - - return ta->ta_ops->to_thr_sstep(th, step); -} diff --git a/lib/libthread_db/thread_db.c b/lib/libthread_db/thread_db.c new file mode 100644 index 000000000000..e92d4ff3c13c --- /dev/null +++ b/lib/libthread_db/thread_db.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2004 David Xu + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "thread_db_int.h" + +struct td_thragent +{ + TD_THRAGENT_FIELDS; +}; + +static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); + +extern struct ta_ops libc_r_db_ops; +extern struct ta_ops libpthread_db_ops; +extern struct ta_ops libthr_db_ops; + +static struct ta_ops *ops[] = { + &libpthread_db_ops, + &libthr_db_ops, + &libc_r_db_ops +}; + +td_err_e +td_init(void) +{ + td_err_e ret, tmp; + size_t i; + + ret = 0; + for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { + if (ops[i]->to_init != NULL) { + tmp = ops[i]->to_init(); + if (tmp != TD_OK) + ret = tmp; + } + } + return (ret); +} + +td_err_e +td_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events) +{ + return (ta->ta_ops->to_ta_clear_event(ta, events)); +} + +td_err_e +td_ta_delete(td_thragent_t *ta) +{ + TAILQ_REMOVE(&proclist, ta, ta_next); + return (ta->ta_ops->to_ta_delete(ta)); +} + +td_err_e +td_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr) +{ + return (ta->ta_ops->to_ta_event_addr(ta, event, ptr)); +} + +td_err_e +td_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg) +{ + return (ta->ta_ops->to_ta_event_getmsg(ta, msg)); +} + +td_err_e +td_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th) +{ + return (ta->ta_ops->to_ta_map_id2thr(ta, id, th)); +} + +td_err_e +td_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) +{ + return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th)); +} + +td_err_e +td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) +{ + size_t i; + + for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { + if (ops[i]->to_ta_new(ph, pta) == TD_OK) { + TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); + (*pta)->ta_ops = ops[i]; + return (TD_OK); + } + } + return (TD_NOLIBTHREAD); +} + +td_err_e +td_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events) +{ + return (ta->ta_ops->to_ta_set_event(ta, events)); +} + +td_err_e +td_ta_thr_iter(const td_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) +{ + return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state, + ti_pri, ti_sigmask_p, ti_user_flags)); +} + +td_err_e +td_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback, + void *cbdata_p) +{ + return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p)); +} + +td_err_e +td_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_clear_event(th, events)); +} + +td_err_e +td_thr_dbresume(const td_thrhandle_t *th) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_dbresume(th)); +} + +td_err_e +td_thr_dbsuspend(const td_thrhandle_t *th) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_dbsuspend(th)); +} + +td_err_e +td_thr_event_enable(const td_thrhandle_t *th, int en) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_event_enable(th, en)); +} + +td_err_e +td_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_event_getmsg(th, msg)); +} + +td_err_e +td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_get_info(th, info)); +} + +td_err_e +td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_getfpregs(th, fpregset)); +} + +td_err_e +td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_getgregs(th, gregs)); +} + +td_err_e +td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_set_event(th, events)); +} + +td_err_e +td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_setfpregs(th, fpregs)); +} + +td_err_e +td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_setgregs(th, gregs)); +} + +td_err_e +td_thr_validate(const td_thrhandle_t *th) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_validate(th)); +} + +/* FreeBSD specific extensions. */ + +td_err_e +td_thr_sstep(const td_thrhandle_t *th, int step) +{ + const td_thragent_t *ta = th->th_ta; + return (ta->ta_ops->to_thr_sstep(th, step)); +} diff --git a/lib/libthread_db/thread_db.h b/lib/libthread_db/thread_db.h new file mode 100644 index 000000000000..ec0baafb7467 --- /dev/null +++ b/lib/libthread_db/thread_db.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 ``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 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. + * + * $FreeBSD$ + */ + +#ifndef _THREAD_DB_H_ +#define _THREAD_DB_H_ + +#include +#include + +typedef enum { + TD_ERR = -1, /* Unspecified error. */ + TD_OK = 0, /* No error. */ + TD_BADKEY, + TD_BADPH, + TD_BADSH, + TD_BADTA, + TD_BADTH, + TD_DBERR, + TD_MALLOC, + TD_NOAPLIC, + TD_NOCAPAB, + TD_NOEVENT, + TD_NOFPREGS, + TD_NOLIBTHREAD, + TD_NOLWP, + TD_NOMSG, + TD_NOSV, + TD_NOTHR, + TD_NOTSD, + TD_NOXREGS, + TD_PARTIALREG +} td_err_e; + +typedef struct td_thragent td_thragent_t; +typedef long thread_t; /* Must be an integral type. */ + +typedef struct { + const td_thragent_t *th_ta; + psaddr_t th_thread; + thread_t th_tid; +} td_thrhandle_t; /* Used non-opaguely. */ + +/* + * Events. + */ + +typedef enum { + TD_EVENT_NONE = 0, + TD_CREATE = 0x0001, + TD_DEATH = 0x0002, + TD_ALL_EVENTS = ~0 +} td_thr_events_e; + +/* Compatibility with Linux. */ +#define td_event_e td_thr_events_e + +typedef struct { + td_thr_events_e event; + const td_thrhandle_t *th_p; + uintptr_t data; +} td_event_msg_t; + +typedef unsigned int td_thr_events_t; + +/* XXX can't be it... */ +typedef struct { + union { + psaddr_t bptaddr; + } u; +} td_notify_t; + +static __inline void +td_event_addset(td_thr_events_t *es, td_thr_events_e e) +{ + *es |= e; +} + +static __inline void +td_event_delset(td_thr_events_t *es, td_thr_events_e e) +{ + *es &= ~e; +} + +static __inline void +td_event_emptyset(td_thr_events_t *es) +{ + *es = TD_EVENT_NONE; +} + +static __inline void +td_event_fillset(td_thr_events_t *es) +{ + *es = TD_ALL_EVENTS; +} + +static __inline int +td_eventisempty(td_thr_events_t *es) +{ + return ((*es == TD_EVENT_NONE) ? 1 : 0); +} + +static __inline int +td_eventismember(td_thr_events_t *es, td_thr_events_e e) +{ + return ((*es & e) ? 1 : 0); +} + +/* + * Thread info. + */ + +typedef enum { + TD_THR_UNKNOWN = -1, + TD_THR_ANY_STATE = 0, + TD_THR_ACTIVE, + TD_THR_RUN, + TD_THR_SLEEP, + TD_THR_STOPPED, + TD_THR_STOPPED_ASLEEP, + TD_THR_ZOMBIE +} td_thr_state_e; + +typedef enum +{ + TD_THR_SYSTEM = 1, + TD_THR_USER +} td_thr_type_e; + +typedef int thread_key_t; + +#if 0 +typedef struct td_thrinfo_t { + unsigned int ti_user_flags; + psaddr_t ti_pc; + psaddr_t ti_sp; + short ti_flags; + uchar_t ti_preemptflag; + uchar_t ti_pirecflag; +}; +#endif + +typedef struct { + const td_thragent_t *ti_ta_p; + thread_t ti_tid; + td_thr_state_e ti_state; + td_thr_type_e ti_type; + td_thr_events_t ti_events; + int ti_pri; + lwpid_t ti_lid; + char ti_db_suspended; + char ti_traceme; + sigset_t ti_sigmask; + sigset_t ti_pending; + psaddr_t ti_tls; + psaddr_t ti_startfunc; + psaddr_t ti_stkbase; + size_t ti_stksize; +} td_thrinfo_t; + +/* + * Prototypes. + */ + +typedef int td_key_iter_f(thread_key_t, void (*)(void *), void *); +typedef int td_thr_iter_f(const td_thrhandle_t *, void *); + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + +__BEGIN_DECLS +td_err_e td_init(void); + +td_err_e td_ta_clear_event(const td_thragent_t *, td_thr_events_t *); +td_err_e td_ta_delete(td_thragent_t *); +td_err_e td_ta_event_addr(const td_thragent_t *, td_thr_events_e, + td_notify_t *); +td_err_e td_ta_event_getmsg(const td_thragent_t *, td_event_msg_t *); +td_err_e td_ta_map_id2thr(const td_thragent_t *, thread_t, td_thrhandle_t *); +td_err_e td_ta_map_lwp2thr(const td_thragent_t *, lwpid_t, td_thrhandle_t *); +td_err_e td_ta_new(struct ps_prochandle *, td_thragent_t **); +td_err_e td_ta_set_event(const td_thragent_t *, td_thr_events_t *); +td_err_e td_ta_thr_iter(const td_thragent_t *, td_thr_iter_f *, void *, + td_thr_state_e, int, sigset_t *, unsigned int); +td_err_e td_ta_tsd_iter(const td_thragent_t *, td_key_iter_f *, void *); + +td_err_e td_thr_clear_event(const td_thrhandle_t *, td_thr_events_t *); +td_err_e td_thr_dbresume(const td_thrhandle_t *); +td_err_e td_thr_dbsuspend(const td_thrhandle_t *); +td_err_e td_thr_event_enable(const td_thrhandle_t *, int); +td_err_e td_thr_event_getmsg(const td_thrhandle_t *, td_event_msg_t *); +td_err_e td_thr_get_info(const td_thrhandle_t *, td_thrinfo_t *); +td_err_e td_thr_getfpregs(const td_thrhandle_t *, prfpregset_t *); +td_err_e td_thr_getgregs(const td_thrhandle_t *, prgregset_t); +td_err_e td_thr_set_event(const td_thrhandle_t *, td_thr_events_t *); +td_err_e td_thr_setfpregs(const td_thrhandle_t *, const prfpregset_t *); +td_err_e td_thr_setgregs(const td_thrhandle_t *, const prgregset_t); +td_err_e td_thr_validate(const td_thrhandle_t *); + +/* FreeBSD specific extensions. */ +td_err_e td_thr_sstep(const td_thrhandle_t *, int); +__END_DECLS + +#endif /* _THREAD_DB_H_ */ diff --git a/lib/libthread_db/include/thread_db_int.h b/lib/libthread_db/thread_db_int.h similarity index 54% rename from lib/libthread_db/include/thread_db_int.h rename to lib/libthread_db/thread_db_int.h index 5afcb024a901..1b562518d21c 100644 --- a/lib/libthread_db/include/thread_db_int.h +++ b/lib/libthread_db/thread_db_int.h @@ -26,68 +26,65 @@ * $FreeBSD$ */ -#ifndef _THREAD_DB_INT_H -#define _THREAD_DB_INT_H +#ifndef _THREAD_DB_INT_H_ +#define _THREAD_DB_INT_H_ #include #include -struct td_thragent { - struct ta_ops *ta_ops; - TAILQ_ENTRY(td_thragent) ta_next; -}; +#define TD_THRAGENT_FIELDS \ + struct ta_ops *ta_ops; \ + TAILQ_ENTRY(td_thragent) ta_next; \ + struct ps_prochandle *ph struct ta_ops { td_err_e (*to_init)(void); - td_err_e (*to_ta_new)(struct ps_prochandle *, td_thragent_t **); + + td_err_e (*to_ta_clear_event)(const td_thragent_t *, + td_thr_events_t *); td_err_e (*to_ta_delete)(td_thragent_t *); - td_err_e (*to_ta_get_nthreads)(const td_thragent_t *, int *); - td_err_e (*to_ta_get_ph)(const td_thragent_t *, struct ps_prochandle **); - td_err_e (*to_ta_map_id2thr)(const td_thragent_t *, thread_t, td_thrhandle_t *); - td_err_e (*to_ta_map_lwp2thr)(const td_thragent_t *, lwpid_t lwpid, - td_thrhandle_t *); - td_err_e (*to_ta_thr_iter)(const td_thragent_t *, td_thr_iter_f *, void *, - td_thr_state_e, int, sigset_t *, unsigned int); - td_err_e (*to_ta_tsd_iter)(const td_thragent_t *, td_key_iter_f *, void *); - td_err_e (*to_ta_event_addr)(const td_thragent_t *, td_event_e , td_notify_t *); + td_err_e (*to_ta_event_addr)(const td_thragent_t *, td_thr_events_e, + td_notify_t *); + td_err_e (*to_ta_event_getmsg)(const td_thragent_t *, + td_event_msg_t *); + td_err_e (*to_ta_map_id2thr)(const td_thragent_t *, thread_t, + td_thrhandle_t *); + td_err_e (*to_ta_map_lwp2thr)(const td_thragent_t *, lwpid_t, + td_thrhandle_t *); + td_err_e (*to_ta_new)(struct ps_prochandle *, td_thragent_t **); td_err_e (*to_ta_set_event)(const td_thragent_t *, td_thr_events_t *); - td_err_e (*to_ta_clear_event)(const td_thragent_t *, td_thr_events_t *); - td_err_e (*to_ta_event_getmsg)(const td_thragent_t *, td_event_msg_t *); - td_err_e (*to_ta_setconcurrency)(const td_thragent_t *, int); - td_err_e (*to_ta_enable_stats)(const td_thragent_t *, int); - td_err_e (*to_ta_reset_stats)(const td_thragent_t *); - td_err_e (*to_ta_get_stats)(const td_thragent_t *, td_ta_stats_t *); - td_err_e (*to_thr_validate)(const td_thrhandle_t *); + td_err_e (*to_ta_thr_iter)(const td_thragent_t *, td_thr_iter_f *, + void *, td_thr_state_e, int, sigset_t *, unsigned int); + td_err_e (*to_ta_tsd_iter)(const td_thragent_t *, td_key_iter_f *, + void *); + + td_err_e (*to_thr_clear_event)(const td_thrhandle_t *, + td_thr_events_t *); + td_err_e (*to_thr_dbresume)(const td_thrhandle_t *); + td_err_e (*to_thr_dbsuspend)(const td_thrhandle_t *); + td_err_e (*to_thr_event_enable)(const td_thrhandle_t *, int); + td_err_e (*to_thr_event_getmsg)(const td_thrhandle_t *, + td_event_msg_t *); td_err_e (*to_thr_get_info)(const td_thrhandle_t *, td_thrinfo_t *); td_err_e (*to_thr_getfpregs)(const td_thrhandle_t *, prfpregset_t *); td_err_e (*to_thr_getgregs)(const td_thrhandle_t *, prgregset_t); - td_err_e (*to_thr_getxregs)(const td_thrhandle_t *, void *); - td_err_e (*to_thr_getxregsize)(const td_thrhandle_t *, int *); - td_err_e (*to_thr_setfpregs)(const td_thrhandle_t *, const prfpregset_t *); + td_err_e (*to_thr_set_event)(const td_thrhandle_t *, + td_thr_events_t *); + td_err_e (*to_thr_setfpregs)(const td_thrhandle_t *, + const prfpregset_t *); td_err_e (*to_thr_setgregs)(const td_thrhandle_t *, const prgregset_t); - td_err_e (*to_thr_setxregs)(const td_thrhandle_t *, const void *); - td_err_e (*to_thr_event_enable)(const td_thrhandle_t *, int); - td_err_e (*to_thr_set_event)(const td_thrhandle_t *, td_thr_events_t *); - td_err_e (*to_thr_clear_event)(const td_thrhandle_t *, td_thr_events_t *); - td_err_e (*to_thr_event_getmsg)(const td_thrhandle_t *, td_event_msg_t *); - td_err_e (*to_thr_setprio)(const td_thrhandle_t *, int); - td_err_e (*to_thr_setsigpending)(const td_thrhandle_t *, unsigned char, - const sigset_t *); - td_err_e (*to_thr_sigsetmask)(const td_thrhandle_t *, const sigset_t *); - td_err_e (*to_thr_tsd)(const td_thrhandle_t *, const thread_key_t, void **); - td_err_e (*to_thr_dbsuspend)(const td_thrhandle_t *); - td_err_e (*to_thr_dbresume)(const td_thrhandle_t *); - td_err_e (*to_get_ta)(int pid, td_thragent_t **); - td_err_e (*to_ta_activated)(td_thragent_t *, int *); - td_err_e (*to_thr_sstep)(td_thrhandle_t *, int step); + td_err_e (*to_thr_validate)(const td_thrhandle_t *); + + /* FreeBSD specific extensions. */ + td_err_e (*to_thr_sstep)(const td_thrhandle_t *, int); }; #ifdef TD_DEBUG #define TDBG(...) ps_plog(__VA_ARGS__) -#define TDBG_FUNC() ps_plog(__func__); ps_plog("\n") +#define TDBG_FUNC() ps_plog("%s\n", __func__) #else #define TDBG(...) #define TDBG_FUNC() #endif -#endif +#endif /* _THREAD_DB_INT_H_ */