-/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
- Copyright 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
+ debugger.
+
+ Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009
+ 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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* This module implements a sort of half target that sits between the
machine-independent parts of GDB and the ptrace interface (infptrace.c) to
#include "inferior.h"
#include "regcache.h"
#include <fcntl.h>
-#include <sys/stat.h>
+#include <string.h>
+#include "gdb_stat.h"
#include "gdbcore.h"
+#include "hppa-tdep.h"
+#include "observer.h"
extern int child_suppress_run;
-extern struct target_ops child_ops; /* target vector for inftarg.c */
extern void _initialize_hpux_thread (void);
static CORE_ADDR P_cma__g_known_threads;
static CORE_ADDR P_cma__g_current_thread;
-static void hpux_thread_resume (ptid_t ptid, int step,
- enum target_signal signo);
-
static void init_hpux_thread_ops (void);
static struct target_ops hpux_thread_ops;
}
}
- error ("Can't find TCB %d", thread);
+ error (_("Can't find TCB %d"), thread);
return NULL;
}
\f
/* Most target vector functions from here on actually just pass through to
inftarg.c, as they don't need to do anything specific for threads. */
-/* ARGSUSED */
static void
hpux_thread_open (char *arg, int from_tty)
{
- child_ops.to_open (arg, from_tty);
+ deprecated_child_ops.to_open (arg, from_tty);
}
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
static void
-hpux_thread_attach (char *args, int from_tty)
+hpux_thread_attach (struct target_ops *ops, char *args, int from_tty)
{
- child_ops.to_attach (args, from_tty);
+ deprecated_child_ops.to_attach (&deprecated_child_ops, args, from_tty);
/* XXX - might want to iterate over all the threads and register them. */
}
started via the normal ptrace (PTRACE_TRACEME). */
static void
-hpux_thread_detach (char *args, int from_tty)
+hpux_thread_detach (struct target_ops *ops, char *args, int from_tty)
{
- child_ops.to_detach (args, from_tty);
+ deprecated_child_ops.to_detach (&deprecated_child_ops, args, from_tty);
}
/* Resume execution of process PID. If STEP is nozero, then
for procfs. */
static void
-hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
+hpux_thread_resume (struct target_ops *ops,
+ ptid_t ptid, int step, enum target_signal signo)
{
struct cleanup *old_chain;
ptid = main_ptid;
inferior_ptid = main_ptid;
-#if 0
- if (pid != -1)
- {
- pid = thread_to_lwp (pid, -2);
- if (pid == -2) /* Inactive thread */
- error ("This version of Solaris can't start inactive threads.");
- }
-#endif
-
- child_ops.to_resume (ptid, step, signo);
+ deprecated_child_ops.to_resume (&deprecated_child_ops, ptid, step, signo);
cached_thread = 0;
to a LWP id, and vice versa on the way out. */
static ptid_t
-hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+hpux_thread_wait (struct target_ops *ops,
+ ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
ptid_t rtnval;
struct cleanup *old_chain;
if (!ptid_equal (ptid, minus_one_ptid))
ptid = main_ptid;
- rtnval = child_ops.to_wait (ptid, ourstatus);
+ rtnval = deprecated_child_ops.to_wait (&deprecated_child_ops,
+ ptid, ourstatus, options);
rtnval = find_active_thread ();
return rtnval;
}
-static char regmap[NUM_REGS] =
+static char regmap[] =
{
-2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */
28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */
};
static void
-hpux_thread_fetch_registers (int regno)
+hpux_thread_fetch_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
cma__t_int_tcb tcb, *tcb_ptr;
struct cleanup *old_chain;
int i;
if (tcb_ptr->state == cma__c_state_running)
{
- child_ops.to_fetch_registers (regno);
+ deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
+ regcache, regno);
do_cleanups (old_chain);
if (regno == -1)
{
first_regno = 0;
- last_regno = NUM_REGS - 1;
+ last_regno = gdbarch_num_regs (gdbarch) - 1;
}
else
{
for (regno = first_regno; regno <= last_regno; regno++)
{
if (regmap[regno] == -1)
- child_ops.to_fetch_registers (regno);
+ deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
+ regcache, regno);
else
{
- unsigned char *buf = alloca (max_register_size (current_gdbarch));
+ unsigned char buf[MAX_REGISTER_SIZE];
CORE_ADDR sp;
sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
- if (regno == FLAGS_REGNUM)
+ if (regno == HPPA_FLAGS_REGNUM)
/* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
- memset (buf, '\000', REGISTER_RAW_SIZE (regno));
- else if (regno == SP_REGNUM)
- store_address (buf, sizeof sp, sp);
- else if (regno == PC_REGNUM)
- read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
+ memset (buf, '\000', register_size (gdbarch, regno));
+ else if (regno == HPPA_SP_REGNUM)
+ store_unsigned_integer (buf, sizeof sp, sp);
+ else if (regno == HPPA_PCOQ_HEAD_REGNUM)
+ read_memory (sp - 20, buf, register_size (gdbarch, regno));
else
- read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
+ read_memory (sp + regmap[regno], buf,
+ register_size (gdbarch, regno));
- supply_register (regno, buf);
+ regcache_raw_supply (regcache, regno, buf);
}
}
}
static void
-hpux_thread_store_registers (int regno)
+hpux_thread_store_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
cma__t_int_tcb tcb, *tcb_ptr;
struct cleanup *old_chain;
int i;
if (tcb_ptr->state == cma__c_state_running)
{
- child_ops.to_store_registers (regno);
+ deprecated_child_ops.to_store_registers (&deprecated_child_ops,
+ regcache, regno);
do_cleanups (old_chain);
if (regno == -1)
{
first_regno = 0;
- last_regno = NUM_REGS - 1;
+ last_regno = gdbarch_num_regs (gdbarch) - 1;
}
else
{
for (regno = first_regno; regno <= last_regno; regno++)
{
if (regmap[regno] == -1)
- child_ops.to_store_registers (regno);
+ deprecated_child_ops.to_store_registers (regcache, regno);
else
{
- unsigned char *buf = alloca (max_register_size (current_gdbarch));
+ unsigned char buf[MAX_REGISTER_SIZE];
CORE_ADDR sp;
sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
- if (regno == FLAGS_REGNUM)
- child_ops.to_store_registers (regno); /* Let lower layer handle this... */
- else if (regno == SP_REGNUM)
+ if (regno == HPPA_FLAGS_REGNUM)
+ {
+ /* Let lower layer handle this... */
+ deprecated_child_ops.to_store_registers
+ (&deprecated_child_ops, regcache, regno);
+ }
+ else if (regno == HPPA_SP_REGNUM)
+ {
+ regcache_raw_collect (regcache, regno, buf);
+ write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
+ register_size (gdbarch, regno));
+ tcb_ptr->static_ctx.sp
+ = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
+ }
+ else if (regno == HPPA_PCOQ_HEAD_REGNUM)
{
- write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
- &deprecated_registers[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno));
- tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
- (extract_address (&deprecated_registers[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno)) + 160);
+ regcache_raw_collect (regcache, regno, buf);
+ write_memory (sp - 20, buf,
+ register_size (gdbarch, regno));
}
- else if (regno == PC_REGNUM)
- write_memory (sp - 20,
- &deprecated_registers[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno));
else
- write_memory (sp + regmap[regno],
- &deprecated_registers[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno));
+ {
+ regcache_raw_collect (regcache, regno, buf);
+ write_memory (sp + regmap[regno], buf,
+ register_size (gdbarch, regno));
+ }
}
}
debugged. */
static void
-hpux_thread_prepare_to_store (void)
+hpux_thread_prepare_to_store (struct regcache *regcache)
{
- child_ops.to_prepare_to_store ();
+ deprecated_child_ops.to_prepare_to_store (regcache);
}
static int
inferior_ptid = main_ptid;
retval =
- child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
+ deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
do_cleanups (old_chain);
static void
hpux_thread_files_info (struct target_ops *ignore)
{
- child_ops.to_files_info (ignore);
+ deprecated_child_ops.to_files_info (ignore);
}
static void
-hpux_thread_kill_inferior (void)
+hpux_thread_kill_inferior (struct target_ops *ops)
{
- child_ops.to_kill ();
+ deprecated_child_ops.to_kill (&deprecated_child_ops);
}
static void
hpux_thread_notice_signals (ptid_t ptid)
{
- child_ops.to_notice_signals (ptid);
+ deprecated_child_ops.to_notice_signals (ptid);
}
/* Fork an inferior process, and start debugging it with /proc. */
static void
-hpux_thread_create_inferior (char *exec_file, char *allargs, char **env)
+hpux_thread_create_inferior (struct target_ops *ops, char *exec_file,
+ char *allargs, char **env, int from_tty)
{
- child_ops.to_create_inferior (exec_file, allargs, env);
+ deprecated_child_ops.to_create_inferior (&deprecated_child_ops,
+ exec_file, allargs, env, from_tty);
if (hpux_thread_active)
{
those variables don't show up until the library gets mapped and the symbol
table is read in. */
-/* This new_objfile event is now managed by a chained function pointer.
- * It is the callee's responsability to call the next client on the chain.
- */
-
-/* Saved pointer to previous owner of the new_objfile event. */
-static void (*target_new_objfile_chain) (struct objfile *);
-
-void
+static void
hpux_thread_new_objfile (struct objfile *objfile)
{
struct minimal_symbol *ms;
if (!objfile)
{
hpux_thread_active = 0;
- goto quit;
+ return;
}
ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
if (!ms)
- goto quit;
+ return;
P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
if (!ms)
- goto quit;
+ return;
P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
hpux_thread_active = 1;
-quit:
- /* Call predecessor on chain, if any. */
- if (target_new_objfile_chain)
- target_new_objfile_chain (objfile);
}
/* Clean up after the inferior dies. */
static void
hpux_thread_mourn_inferior (void)
{
- child_ops.to_mourn_inferior ();
+ deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
}
/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
}
static int
-hpux_thread_alive (ptid_t ptid)
+hpux_thread_alive (struct target_ops *ops, ptid_t ptid)
{
return 1;
}
static void
-hpux_thread_stop (void)
+hpux_thread_stop (ptid_t ptid)
{
- child_ops.to_stop ();
+ deprecated_child_ops.to_stop (ptid);
}
\f
/* Convert a pid to printable form. */
hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
- hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
+ hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
hpux_thread_ops.to_files_info = hpux_thread_files_info;
hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
hpux_thread_ops.to_thread_alive = hpux_thread_alive;
hpux_thread_ops.to_stop = hpux_thread_stop;
hpux_thread_ops.to_stratum = process_stratum;
- hpux_thread_ops.to_has_all_memory = 1;
- hpux_thread_ops.to_has_memory = 1;
- hpux_thread_ops.to_has_stack = 1;
- hpux_thread_ops.to_has_registers = 1;
- hpux_thread_ops.to_has_execution = 1;
+ hpux_thread_ops.to_has_all_memory = default_child_has_all_memory;
+ hpux_thread_ops.to_has_memory = default_child_has_memory;
+ hpux_thread_ops.to_has_stack = default_child_has_stack;
+ hpux_thread_ops.to_has_registers = default_child_has_registers;
+ hpux_thread_ops.to_has_execution = default_child_has_execution;
hpux_thread_ops.to_magic = OPS_MAGIC;
}
add_target (&hpux_thread_ops);
child_suppress_run = 1;
- /* Hook into new_objfile notification. */
- target_new_objfile_chain = target_new_objfile_hook;
- target_new_objfile_hook = hpux_thread_new_objfile;
+ /* Hook into new_objfile notification. */
+ observer_attach_new_objfile (hpux_thread_new_objfile);
}