aboutsummaryrefslogtreecommitdiff
path: root/gdb/dec-thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/dec-thread.c')
-rw-r--r--gdb/dec-thread.c705
1 files changed, 0 insertions, 705 deletions
diff --git a/gdb/dec-thread.c b/gdb/dec-thread.c
deleted file mode 100644
index d5cfad2..0000000
--- a/gdb/dec-thread.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "defs.h"
-#include "command.h"
-#include "gdbcmd.h"
-#include "target.h"
-#include "observer.h"
-#include <sys/procfs.h>
-#include "gregset.h"
-#include "regcache.h"
-#include "inferior.h"
-#include "gdbthread.h"
-
-#include <pthread_debug.h>
-
-/* Print debugging traces if set to non-zero. */
-static int debug_dec_thread = 0;
-
-/* Non-zero if the dec-thread layer is active. */
-static int dec_thread_active = 0;
-
-/* The pthread_debug context. */
-pthreadDebugContext_t debug_context;
-
-/* The dec-thread target_ops structure. */
-static struct target_ops dec_thread_ops;
-
-/* Print a debug trace if DEBUG_DEC_THREAD is set (its value is adjusted
- by the user using "set debug dec-thread ..."). */
-
-static void
-debug (char *format, ...)
-{
- if (debug_dec_thread)
- {
- va_list args;
-
- va_start (args, format);
- printf_unfiltered ("DEC Threads: ");
- vprintf_unfiltered (format, args);
- printf_unfiltered ("\n");
- va_end (args);
- }
-}
-
-/* pthread debug callbacks. */
-
-static int
-suspend_clbk (void *caller_context)
-{
- return ESUCCESS;
-}
-
-static int
-resume_clbk (void *caller_context)
-{
- return ESUCCESS;
-}
-
-static int
-hold_clbk (void *caller_context, pthreadDebugKId_t kernel_tid)
-{
- return ESUCCESS;
-}
-
-static int
-unhold_clbk (void *caller_context, pthreadDebugKId_t kernel_tid)
-{
- return ESUCCESS;
-}
-
-static int
-read_clbk (void *caller_context, void *address, void *buffer,
- unsigned long size)
-{
- int status = target_read_memory ((CORE_ADDR) address, buffer, size);
-
- if (status != 0)
- return EINVAL;
-
- return ESUCCESS;
-}
-
-static int
-write_clbk (void *caller_context, void *address, void *buffer,
- unsigned long size)
-{
- int status = target_write_memory ((CORE_ADDR) address, buffer, size);
-
- if (status != 0)
- return EINVAL;
-
- return ESUCCESS;
-}
-
-/* Get integer regs. */
-
-static int
-get_reg_clbk(void *caller_context, pthreadDebugGetRegRtn_t regs,
- pthreadDebugKId_t kernel_tid)
-{
- debug ("get_reg_clbk");
-
- /* Not sure that we actually need to do anything in this callback. */
- return ESUCCESS;
-}
-
-/* Set integer regs. */
-
-static int
-set_reg_clbk(void *caller_context, const pthreadDebugRegs_t *regs,
- pthreadDebugKId_t kernel_tid)
-{
- debug ("set_reg_clbk");
-
- /* Not sure that we actually need to do anything in this callback. */
- return ESUCCESS;
-}
-
-static int
-output_clbk (void *caller_context, char *line)
-{
- printf_filtered ("%s\n", line);
- return ESUCCESS;
-}
-
-static int
-error_clbk (void *caller_context, char *line)
-{
- fprintf_filtered (gdb_stderr, "%s\n", line);
- return ESUCCESS;
-}
-
-/* Get floating-point regs. */
-
-static int
-get_fpreg_clbk (void *caller_context, pthreadDebugFregs_p fregs,
- pthreadDebugKId_t kernel_tid)
-{
- debug ("get_fpreg_clbk");
-
- /* Not sure that we actually need to do anything in this callback. */
- return ESUCCESS;
-}
-
-/* Set floating-point regs. */
-
-static int
-set_fpreg_clbk (void *caller_context, const pthreadDebugFregs_t *fregs,
- pthreadDebugKId_t kernel_tid)
-{
- debug ("set_fpreg_clbk");
-
- /* Not sure that we actually need to do anything in this callback. */
- return ESUCCESS;
-}
-
-static void *
-malloc_clbk (void *caller_context, size_t size)
-{
- return xmalloc (size);
-}
-
-static void
-free_clbk (void *caller_context, void *address)
-{
- xfree (address);
-}
-
-static int
-kthdinfo_clbk (pthreadDebugClient_t caller_context,
- pthreadDebugKId_t kernel_tid,
- pthreadDebugKThreadInfo_p thread_info)
-{
- return ENOTSUP;
-}
-
-static int
-speckthd_clbk (pthreadDebugClient_t caller_context,
- pthreadDebugSpecialType_t type,
- pthreadDebugKId_t *kernel_tid)
-{
- return ENOTSUP;
-}
-
-static pthreadDebugCallbacks_t debug_callbacks =
-{
- PTHREAD_DEBUG_VERSION,
- (pthreadDebugGetMemRtn_t) read_clbk,
- (pthreadDebugSetMemRtn_t) write_clbk,
- suspend_clbk,
- resume_clbk,
- kthdinfo_clbk,
- hold_clbk,
- unhold_clbk,
- (pthreadDebugGetFregRtn_t) get_fpreg_clbk,
- (pthreadDebugSetFregRtn_t) set_fpreg_clbk,
- (pthreadDebugGetRegRtn_t) get_reg_clbk,
- (pthreadDebugSetRegRtn_t) set_reg_clbk,
- (pthreadDebugOutputRtn_t) output_clbk,
- (pthreadDebugOutputRtn_t) error_clbk,
- malloc_clbk,
- free_clbk,
- speckthd_clbk
-};
-
-/* Activate thread support if appropriate. Do nothing if thread
- support is already active. */
-
-static void
-enable_dec_thread (void)
-{
- struct bound_minimal_symbol msym;
- void* caller_context;
- int status;
-
- /* If already active, nothing more to do. */
- if (dec_thread_active)
- return;
-
- msym = lookup_minimal_symbol ("__pthread_dbg_symtable", NULL, NULL);
- if (msym.minsym == NULL)
- {
- debug ("enable_dec_thread: No __pthread_dbg_symtable");
- return;
- }
-
- status = pthreadDebugContextInit (&caller_context, &debug_callbacks,
- (void *) SYMBOL_VALUE_ADDRESS (msym.minsym),
- &debug_context);
- if (status != ESUCCESS)
- {
- debug ("enable_dec_thread: pthreadDebugContextInit -> %d",
- status);
- return;
- }
-
- push_target (&dec_thread_ops);
- dec_thread_active = 1;
-
- debug ("enable_dec_thread: Thread support enabled.");
-}
-
-/* Deactivate thread support. Do nothing if thread support is
- already inactive. */
-
-static void
-disable_dec_thread (void)
-{
- if (!dec_thread_active)
- return;
-
- pthreadDebugContextDestroy (debug_context);
- unpush_target (&dec_thread_ops);
- dec_thread_active = 0;
-}
-
-/* A structure that contains a thread ID and is associated
- pthreadDebugThreadInfo_t data. */
-
-struct dec_thread_info
-{
- pthreadDebugId_t thread;
- pthreadDebugThreadInfo_t info;
-};
-typedef struct dec_thread_info dec_thread_info_s;
-
-/* The list of user threads. */
-
-DEF_VEC_O (dec_thread_info_s);
-VEC(dec_thread_info_s) *dec_thread_list;
-
-/* Release the memory used by the given VECP thread list pointer.
- Then set *VECP to NULL. */
-
-static void
-free_dec_thread_info_vec (VEC(dec_thread_info_s) **vecp)
-{
- int i;
- struct dec_thread_info *item;
- VEC(dec_thread_info_s) *vec = *vecp;
-
- for (i = 0; VEC_iterate (dec_thread_info_s, vec, i, item); i++)
- xfree (item);
- VEC_free (dec_thread_info_s, vec);
- *vecp = NULL;
-}
-
-/* Return a thread's ptid given its associated INFO. */
-
-static ptid_t
-ptid_build_from_info (struct dec_thread_info info)
-{
- int pid = ptid_get_pid (inferior_ptid);
-
- return ptid_build (pid, 0, (long) info.thread);
-}
-
-/* Return non-zero if PTID is still alive.
-
- Assumes that DEC_THREAD_LIST is up to date. */
-static int
-dec_thread_ptid_is_alive (ptid_t ptid)
-{
- pthreadDebugId_t tid = ptid_get_tid (ptid);
- int i;
- struct dec_thread_info *info;
-
- if (tid == 0)
- /* This is the thread corresponding to the process. This ptid
- is always alive until the program exits. */
- return 1;
-
- /* Search whether an entry with the same tid exists in the dec-thread
- list of threads. If it does, then the thread is still alive.
- No match found means that the thread must be dead, now. */
- for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
- if (info->thread == tid)
- return 1;
- return 0;
-}
-
-/* Recompute the list of user threads and store the result in
- DEC_THREAD_LIST. */
-
-static void
-update_dec_thread_list (void)
-{
- pthreadDebugId_t thread;
- pthreadDebugThreadInfo_t info;
- int res;
-
- free_dec_thread_info_vec (&dec_thread_list);
- res = pthreadDebugThdSeqInit (debug_context, &thread);
- while (res == ESUCCESS)
- {
-
- res = pthreadDebugThdGetInfo (debug_context, thread, &info);
- if (res != ESUCCESS)
- warning (_("unable to get thread info, ignoring thread %ld"),
- thread);
- else if (info.kind == PTHREAD_DEBUG_THD_KIND_INITIAL
- || info.kind == PTHREAD_DEBUG_THD_KIND_NORMAL)
- {
- struct dec_thread_info *item =
- xmalloc (sizeof (struct dec_thread_info));
-
- item->thread = thread;
- item->info = info;
- VEC_safe_push (dec_thread_info_s, dec_thread_list, item);
- }
- res = pthreadDebugThdSeqNext (debug_context, &thread);
- }
- pthreadDebugThdSeqDestroy (debug_context);
-}
-
-/* Implement the update_thread_list target_ops method. */
-
-static void
-dec_thread_update_thread_list (struct target_ops *ops)
-{
- int i;
- struct dec_thread_info *info;
- struct thread_info *tp, *tmp;
-
- update_dec_thread_list ();
-
- /* Delete GDB-side threads no longer found in dec_thread_list. */
- ALL_NON_EXITED_THREADS_SAFE (tp, tmp)
- {
- for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
- {
- if (ptid_equal (info->ptid, tp->ptid))
- break;
- }
- if (i == VEC_length (dec_thread_info_s, dec_thread_list))
- {
- /* Not found. */
- delete_thread (tp->ptid);
- }
- }
-
- /* And now add new threads. */
- for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
- {
- ptid_t ptid = ptid_build_from_info (*info);
-
- if (!in_thread_list (ptid))
- add_thread (ptid);
- }
-}
-
-/* The "to_detach" method of the dec_thread_ops. */
-
-static void
-dec_thread_detach (struct target_ops *ops, const char *args, int from_tty)
-{
- struct target_ops *beneath = find_target_beneath (ops);
-
- debug ("dec_thread_detach");
-
- disable_dec_thread ();
- beneath->to_detach (beneath, args, from_tty);
-}
-
-/* Return the ptid of the thread that is currently active. */
-
-static ptid_t
-get_active_ptid (void)
-{
- int i;
- struct dec_thread_info *info;
-
- for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
- i++)
- if (info->info.state == PTHREAD_DEBUG_STATE_RUNNING)
- return ptid_build_from_info (*info);
-
- /* No active thread found. This can happen when the program
- has just exited. */
- return null_ptid;
-}
-
-/* The "to_wait" method of the dec_thread_ops. */
-
-static ptid_t
-dec_thread_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *status, int options)
-{
- ptid_t active_ptid;
- struct target_ops *beneath = find_target_beneath (ops);
-
- debug ("dec_thread_wait");
-
- ptid = beneath->to_wait (beneath, ptid, status, options);
-
- /* The ptid returned by the target beneath us is the ptid of the process.
- We need to find which thread is currently active and return its ptid. */
- dec_thread_update_thread_list (ops);
- active_ptid = get_active_ptid ();
- if (ptid_equal (active_ptid, null_ptid))
- return ptid;
- return active_ptid;
-}
-
-/* Fetch the general purpose and floating point registers for the given
- thread TID, and store the result in GREGSET and FPREGSET. Return
- zero if successful. */
-
-static int
-dec_thread_get_regsets (pthreadDebugId_t tid, gdb_gregset_t *gregset,
- gdb_fpregset_t *fpregset)
-{
- int res;
- pthreadDebugRegs_t regs;
- pthreadDebugFregs_t fregs;
-
- res = pthreadDebugThdGetReg (debug_context, tid, &regs);
- if (res != ESUCCESS)
- {
- debug ("dec_thread_get_regsets: pthreadDebugThdGetReg -> %d", res);
- return -1;
- }
- memcpy (gregset->regs, &regs, sizeof (regs));
-
- res = pthreadDebugThdGetFreg (debug_context, tid, &fregs);
- if (res != ESUCCESS)
- {
- debug ("dec_thread_get_regsets: pthreadDebugThdGetFreg -> %d", res);
- return -1;
- }
- memcpy (fpregset->regs, &fregs, sizeof (fregs));
-
- return 0;
-}
-
-/* The "to_fetch_registers" method of the dec_thread_ops.
-
- Because the dec-thread debug API doesn't allow us to fetch
- only one register, we simply ignore regno and fetch+supply all
- registers. */
-
-static void
-dec_thread_fetch_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
-{
- pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
- gregset_t gregset;
- fpregset_t fpregset;
- int res;
-
- debug ("dec_thread_fetch_registers (tid=%ld, regno=%d)", tid, regno);
-
-
- if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
- {
- struct target_ops *beneath = find_target_beneath (ops);
-
- beneath->to_fetch_registers (beneath, regcache, regno);
- return;
- }
-
- res = dec_thread_get_regsets (tid, &gregset, &fpregset);
- if (res != 0)
- return;
-
- supply_gregset (regcache, &gregset);
- supply_fpregset (regcache, &fpregset);
-}
-
-/* Store the registers given in GREGSET and FPREGSET into the associated
- general purpose and floating point registers of thread TID. Return
- zero if successful. */
-
-static int
-dec_thread_set_regsets (pthreadDebugId_t tid, gdb_gregset_t gregset,
- gdb_fpregset_t fpregset)
-{
- int res;
- pthreadDebugRegs_t regs;
- pthreadDebugFregs_t fregs;
-
- memcpy (&regs, gregset.regs, sizeof (regs));
- res = pthreadDebugThdSetReg (debug_context, tid, &regs);
- if (res != ESUCCESS)
- {
- debug ("dec_thread_set_regsets: pthreadDebugThdSetReg -> %d", res);
- return -1;
- }
-
- memcpy (&fregs, fpregset.regs, sizeof (fregs));
- res = pthreadDebugThdSetFreg (debug_context, tid, &fregs);
- if (res != ESUCCESS)
- {
- debug ("dec_thread_set_regsets: pthreadDebugThdSetFreg -> %d", res);
- return -1;
- }
-
- return 0;
-}
-
-/* The "to_store_registers" method of the dec_thread_ops.
-
- Because the dec-thread debug API doesn't allow us to store
- just one register, we store all the registers. */
-
-static void
-dec_thread_store_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
-{
- pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
- gregset_t gregset;
- fpregset_t fpregset;
- int res;
-
- debug ("dec_thread_store_registers (tid=%ld, regno=%d)", tid, regno);
-
- if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
- {
- struct target_ops *beneath = find_target_beneath (ops);
-
- beneath->to_store_registers (beneath, regcache, regno);
- return;
- }
-
- /* FIXME: brobecker/2008-05-28: I wonder if we could simply check
- in which register set the register is and then only store the
- registers for that register set, instead of storing both register
- sets. */
- fill_gregset (regcache, &gregset, -1);
- fill_fpregset (regcache, &fpregset, -1);
-
- res = dec_thread_set_regsets (tid, gregset, fpregset);
- if (res != 0)
- warning (_("failed to store registers."));
-}
-
-/* The "to_mourn_inferior" method of the dec_thread_ops. */
-
-static void
-dec_thread_mourn_inferior (struct target_ops *ops)
-{
- struct target_ops *beneath = find_target_beneath (ops);
-
- debug ("dec_thread_mourn_inferior");
-
- disable_dec_thread ();
- beneath->to_mourn_inferior (beneath);
-}
-
-/* The "to_thread_alive" method of the dec_thread_ops. */
-static int
-dec_thread_thread_alive (struct target_ops *ops, ptid_t ptid)
-{
- debug ("dec_thread_thread_alive (tid=%ld)", ptid_get_tid (ptid));
-
- /* The thread list maintained by GDB is up to date, since we update
- it everytime we stop. So check this list. */
- return in_thread_list (ptid);
-}
-
-/* The "to_pid_to_str" method of the dec_thread_ops. */
-
-static char *
-dec_thread_pid_to_str (struct target_ops *ops, ptid_t ptid)
-{
- static char *ret = NULL;
-
- if (ptid_get_tid (ptid) == 0)
- {
- struct target_ops *beneath = find_target_beneath (ops);
-
- return beneath->to_pid_to_str (beneath, ptid);
- }
-
- /* Free previous return value; a new one will be allocated by
- xstrprintf(). */
- xfree (ret);
-
- ret = xstrprintf (_("Thread %ld"), ptid_get_tid (ptid));
- return ret;
-}
-
-/* A "new-objfile" observer. Used to activate/deactivate dec-thread
- support. */
-
-static void
-dec_thread_new_objfile_observer (struct objfile *objfile)
-{
- if (objfile != NULL)
- enable_dec_thread ();
- else
- disable_dec_thread ();
-}
-
-/* The "to_get_ada_task_ptid" method of the dec_thread_ops. */
-
-static ptid_t
-dec_thread_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
-{
- int i;
- struct dec_thread_info *info;
-
- debug ("dec_thread_get_ada_task_ptid (struct target_ops *self,"
- " lwp=0x%lx, thread=0x%lx)",
- lwp, thread);
-
- for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
- i++)
- if (info->info.teb == (pthread_t) thread)
- return ptid_build_from_info (*info);
-
- warning (_("Could not find thread id from THREAD = 0x%lx"), thread);
- return inferior_ptid;
-}
-
-static void
-init_dec_thread_ops (void)
-{
- dec_thread_ops.to_shortname = "dec-threads";
- dec_thread_ops.to_longname = _("DEC threads support");
- dec_thread_ops.to_doc = _("DEC threads support");
- dec_thread_ops.to_detach = dec_thread_detach;
- dec_thread_ops.to_wait = dec_thread_wait;
- dec_thread_ops.to_fetch_registers = dec_thread_fetch_registers;
- dec_thread_ops.to_store_registers = dec_thread_store_registers;
- dec_thread_ops.to_mourn_inferior = dec_thread_mourn_inferior;
- dec_thread_ops.to_thread_alive = dec_thread_thread_alive;
- dec_thread_ops.to_update_thread_list = dec_thread_update_thread_list;
- dec_thread_ops.to_pid_to_str = dec_thread_pid_to_str;
- dec_thread_ops.to_stratum = thread_stratum;
- dec_thread_ops.to_get_ada_task_ptid = dec_thread_get_ada_task_ptid;
- dec_thread_ops.to_magic = OPS_MAGIC;
-}
-
-void
-_initialize_dec_thread (void)
-{
- init_dec_thread_ops ();
- complete_target_initialization (&dec_thread_ops);
-
- observer_attach_new_objfile (dec_thread_new_objfile_observer);
-
- add_setshow_boolean_cmd ("dec-thread", class_maintenance, &debug_dec_thread,
- _("Set debugging of DEC threads module."),
- _("Show debugging of DEC threads module."),
- _("Enables debugging output (used to debug GDB)."),
- NULL, NULL,
- &setdebuglist, &showdebuglist);
-}