Add rudimentary support and stubs for libthr and libc_r on alpha, amd64,

i386, ia64 and sparc64. Add stubs for alpha, amd64, ia64 and sparc64 for
libpthread.

Restructure the source files to avoid unnecessary use of subdirectories
that also force us to use non-portable compilation flags to deal with
the uncommon compilation requirements (building archive libraries for
linkage into a shared library).

The libpthread support has been copied from the original local and
cleaned-up to make them WARNS=2 clean.
that also force us to use non-portable compilation flags to deal with
the uncommon compilation requirements (building archive libraries for
linkage into a shared library).

The libpthread support has been copied from the original local and
cleaned-up to make them WARNS=2 clean.

Tested on: amd64, i386, ia64
This commit is contained in:
Marcel Moolenaar 2004-07-18 04:17:15 +00:00
parent 38da2381cd
commit 3c1e38ea6e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132332
22 changed files with 2362 additions and 1689 deletions

View File

@ -1,5 +1,28 @@
# $FreeBSD$
SUBDIR=pthread src
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}
.include <bsd.subdir.mk>
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 <bsd.lib.mk>

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/procfs.h>
#include <machine/setjmp.h>
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)
{
}

View File

@ -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 <sys/cdefs.h>
__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);
}

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/procfs.h>
#include <machine/setjmp.h>
void
libc_r_md_getgregs(jmp_buf jb, prgregset_t *r)
{
}
void
libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r)
{
}

View File

@ -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 <sys/cdefs.h>
__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);
}

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/procfs.h>
#include <machine/setjmp.h>
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)
{
}

View File

@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
#include <thread_db.h>
#include <machine/npx.h>
#include "pthread_db.h"
#include "libpthread_db.h"
static int has_xmm_regs;

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/procfs.h>
#include <machine/setjmp.h>
void
libc_r_md_getgregs(jmp_buf jb, prgregset_t *r)
{
}
void
libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r)
{
}

View File

@ -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 <sys/cdefs.h>
__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);
}

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/procfs.h>
#include <machine/setjmp.h>
void
libc_r_md_getgregs(jmp_buf jb, prgregset_t *r)
{
}
void
libc_r_md_getfpregs(jmp_buf jb, prfpregset_t *r)
{
}

View File

@ -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 <sys/cdefs.h>
__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);
}

View File

@ -1,287 +0,0 @@
/*
* Copyright (c) 2004 David Xu <davidxu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE 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 <sys/types.h>
#include <pthread.h>
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

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <machine/setjmp.h>
#include <proc_service.h>
#include <stdlib.h>
#include <string.h>
#include <thread_db.h>
#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, &current,
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
};

View File

@ -26,29 +26,39 @@
* $FreeBSD$
*/
#ifndef _PTHREAD_DB_H
#define _PTHREAD_DB_H
#ifndef _LIBPTHREAD_DB_H_
#define _LIBPTHREAD_DB_H_
#include <sys/ucontext.h>
#include <machine/reg.h>
#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_ */

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <proc_service.h>
#include <stdlib.h>
#include <thread_db.h>
#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
};

View File

@ -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 <bsd.lib.mk>

View File

@ -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 <bsd.lib.mk>

View File

@ -1,359 +0,0 @@
/*
* Copyright (c) 2004 David Xu <davidxu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stddef.h>
#include <unistd.h>
#include <proc_service.h>
#include <thread_db.h>
#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);
}

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2004 David Xu <davidxu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <proc_service.h>
#include <stddef.h>
#include <thread_db.h>
#include <unistd.h>
#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));
}

View File

@ -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 <sys/procfs.h>
#include <pthread.h>
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_ */

View File

@ -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 <sys/types.h>
#include <sys/queue.h>
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_ */