This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch 0/1] Threaded Watchpoints
- From: Luis Machado <luisgpm at linux dot vnet dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 13 Aug 2007 10:51:17 -0300
- Subject: [patch 0/1] Threaded Watchpoints
- Reply-to: luisgpm at linux dot vnet dot ibm dot com
Folks,
I took the freedom of refreshing Jeff Johnston's patch for threaded
watchpoints for HEAD in order to keep this feature moving, and
eventually include it for GDB 6.7.
I remember from previous threads that there was some discussion about
the observer implemented by Jeff. Based on comments and suggestions i'll
re-work the patch.
I'm also working on the ppc side of this patch and will submit soon.
Best regards,
--
Luis Machado
IBM Linux Technology Center
e-mail: luisgpm@vnet.linux.ibm.com
2007-08-13 Jeff Johnston <jjohnstn@redhat.com>
* linux-nat.c: (stop_wait_callback, linux-nat-wait): Notify
observers of a sigtrap.
(delete_lwp): Free the saved_trap_data if present.
* linux-nat.h (struct lwp_info): Add saved_trap_data field.
(struct linux_watchpoint): New struct.
* linux-thread-db.c: Add support to always keep lwp info in ptids.
(attach_thread): Notify observers of a linux
new thread.
(thread_db_wait): Call check_event if SIGILL occurs.
* infrun.c: (handle_inferior_event): For platforms that
hit watchpoints prior to the data write, mark the watchpoints
so we know to check them after we step through the write.
* breakpoint.c (bpstat_stop_status): Fix up watchpoint code.
(insert_watchpoints_for_new_thread): New function.
(mark_triggered_watchpoints): Ditto.
* breakpoint.h (insert_watchpoints_for_new_thread): New prototype.
(mark_triggered_watchpoints): Ditto.
* i386-linux-nat.c (i386_linux_dr_get, i386_linux_dr_set): Use
TIDGET to get PTRACE lpw, otherwise fall back to PIDGET.
* amd64-linux-nat.c (amd64_linux_dr_get, amd64_linux_dr_set): Ditto.
* ia64-linux-nat.c: Add support for removing and inserting watchpoints
on all threads.
* s390-nat.c: Ditto.
* Makefile.in: Add observer.h and linux-nat.h to ia64-linux-nat.o
and s390-nat.o.
* doc/observer.texi: Add two new observers for linux_new_thread
and sigtrap.
Index: gdb/doc/observer.texi
===================================================================
--- gdb.orig/doc/observer.texi 2007-08-10 14:32:29.000000000 -0700
+++ gdb/doc/observer.texi 2007-08-13 06:21:29.000000000 -0700
@@ -123,6 +123,16 @@
The shared library specified by @var{solib} has been unloaded.
@end deftypefun
+@deftypefun void linux_new_thread (ptid_t @var{ptid})
+A new linux thread described by @var{ptid} has been officially attached
+to by gdb.
+@end deftypefun
+
+@deftypefun void sigtrap (void * @var{data})
+A low-level SIGTRAP has been discovered. This notification can be used to save
+additional state necessary if the trap is deferred for later handling.
+@end deftypefun
+
@deftypefun void new_objfile (struct objfile *@var{objfile})
The symbol file specified by @var{objfile} has been loaded.
Called with @var{objfile} equal to @code{NULL} to indicate
Index: gdb/infrun.c
===================================================================
--- gdb.orig/infrun.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/infrun.c 2007-08-13 06:21:29.000000000 -0700
@@ -1777,9 +1777,19 @@
single step over a watchpoint without disabling the watchpoint. */
if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
{
+ CORE_ADDR addr = 0;
+
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
- resume (1, 0);
+
+ target_stopped_data_address (¤t_target, &addr);
+ mark_triggered_watchpoints (addr);
+ registers_changed ();
+ target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); /* Single step */
+
+ ecs->waiton_ptid = ecs->ptid;
+ ecs->wp = &(ecs->ws);
+ ecs->infwait_state = infwait_nonstep_watch_state;
prepare_to_wait (ecs);
return;
}
@@ -1790,6 +1800,8 @@
if (gdbarch_have_nonsteppable_watchpoint (current_gdbarch)
&& STOPPED_BY_WATCHPOINT (ecs->ws))
{
+ CORE_ADDR addr = 0;
+
/* At this point, we are stopped at an instruction which has
attempted to write to a piece of memory under control of
a watchpoint. The instruction hasn't actually executed
@@ -1797,15 +1809,12 @@
now, we would get the old value, and therefore no change
would seem to have occurred.
- In order to make watchpoints work `right', we really need
- to complete the memory write, and then evaluate the
- watchpoint expression. The following code does that by
- removing the watchpoint (actually, all watchpoints and
- breakpoints), single-stepping the target, re-inserting
- watchpoints, and then falling through to let normal
- single-step processing handle proceed. Since this
- includes evaluating watchpoints, things will come to a
- stop in the correct manner. */
+ In order to make watchpoints work `right', we mark the
+ triggered watchpoints so that after we single step,
+ we will check for a value change. */
+
+ target_stopped_data_address (¤t_target, &addr);
+ mark_triggered_watchpoints (addr);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
@@ -1876,6 +1885,41 @@
}
}
+ if (stop_signal == TARGET_SIGNAL_TRAP
+ && trap_expected
+ && gdbarch_single_step_through_delay_p (current_gdbarch)
+ && currently_stepping (ecs))
+ {
+ /* We're trying to step of a breakpoint. Turns out that we're
+ also on an instruction that needs to be stepped multiple
+ times before it's been fully executing. E.g., architectures
+ with a delay slot. It needs to be stepped twice, once for
+ the instruction and once for the delay slot. */
+ int step_through_delay
+ = gdbarch_single_step_through_delay (current_gdbarch,
+ get_current_frame ());
+ if (debug_infrun && step_through_delay)
+ fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
+ if (step_range_end == 0 && step_through_delay)
+ {
+ /* The user issued a continue when stopped at a breakpoint.
+ Set up for another trap and get out of here. */
+ ecs->another_trap = 1;
+ keep_going (ecs);
+ return;
+ }
+ else if (step_through_delay)
+ {
+ /* The user issued a step when stopped at a breakpoint.
+ Maybe we should stop, maybe we should not - the delay
+ slot *might* correspond to a line of source. In any
+ case, don't decide that here, just set ecs->another_trap,
+ making sure we single-step again before breakpoints are
+ re-inserted. */
+ ecs->another_trap = 1;
+ }
+ }
+
/* Look at the cause of the stop, and decide what to do.
The alternatives are:
1) break; to really stop and return to the debugger,
@@ -1928,6 +1972,8 @@
See more comments in inferior.h. */
if (stop_soon == STOP_QUIETLY_NO_SIGSTOP)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
stop_stepping (ecs);
if (stop_signal == TARGET_SIGNAL_STOP)
stop_signal = TARGET_SIGNAL_0;
Index: gdb/breakpoint.c
===================================================================
--- gdb.orig/breakpoint.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/breakpoint.c 2007-08-13 06:21:29.000000000 -0700
@@ -808,6 +808,90 @@
}
}
+/* External function to insert all existing watchpoints on a newly
+ attached thread. IWPFN is a callback function to perform
+ the target insert watchpoint. This function is used to support
+ platforms where a watchpoint must be inserted/removed on each
+ individual thread (e.g. ia64-linux and s390-linux). For
+ ia64 and s390 linux, this function is called via a new thread
+ observer. */
+int
+insert_watchpoints_for_new_thread (ptid_t new_thread,
+ insert_watchpoint_ftype *iwpfn)
+{
+ struct bp_location *b;
+ int val = 0;
+ int return_val = 0;
+ struct ui_file *tmp_error_stream = mem_fileopen ();
+ make_cleanup_ui_file_delete (tmp_error_stream);
+
+ /* Explicitly mark the warning -- this will only be printed if
+ there was an error. */
+ fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+
+ ALL_BP_LOCATIONS (b)
+ {
+ /* Skip disabled breakpoints. */
+ if (!breakpoint_enabled (b->owner))
+ continue;
+
+ /* For every active watchpoint, we need to insert the watchpoint on
+ the new thread. */
+ if (b->loc_type == bp_loc_hardware_watchpoint)
+ {
+ struct value *v = b->owner->val_chain;
+
+ /* Look at each value on the value chain. */
+ for (; v; v = value_next(v))
+ {
+ /* If it's a memory location, and GDB actually needed
+ its contents to evaluate the expression, then we
+ must watch it. */
+ if (VALUE_LVAL (v) == lval_memory
+ && ! value_lazy (v))
+ {
+ struct type *vtype = check_typedef (value_type (v));
+
+ /* We only watch structs and arrays if user asked
+ for it explicitly, never if they just happen to
+ appear in the middle of some value chain. */
+ if (v == b->owner->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR addr;
+ int len, type;
+
+ addr = VALUE_ADDRESS (v) + value_offset (v);
+ len = TYPE_LENGTH (value_type (v));
+ type = hw_write;
+ if (b->owner->type == bp_read_watchpoint)
+ type = hw_read;
+ else if (b->owner->type == bp_access_watchpoint)
+ type = hw_access;
+ val = (*iwpfn) (new_thread, addr, len, type);
+ }
+ }
+ }
+ }
+
+ if (val)
+ return_val = val;
+ }
+
+ /* Failure to insert a watchpoint on any memory value in the
+ value chain brings us here. */
+ if (return_val)
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "%s\n",
+ "Could not insert hardware watchpoints on new thread.");
+ target_terminal_ours_for_output ();
+ error_stream (tmp_error_stream);
+ }
+ return return_val;
+}
+
/* Helper routine: free the value chain for a breakpoint (watchpoint). */
static void
@@ -1296,6 +1380,7 @@
{
struct bp_location *b;
int val;
+ int return_val = 0;
ALL_BP_LOCATIONS (b)
{
@@ -1303,10 +1388,10 @@
{
val = remove_breakpoint (b, mark_uninserted);
if (val != 0)
- return val;
+ return_val = val;
}
}
- return 0;
+ return return_val;
}
int
@@ -2209,8 +2294,13 @@
break;
case bp_thread_event:
- /* Not sure how we will get here.
- GDB should not stop for these breakpoints. */
+ /* We can only get here legitimately if something further on the bs
+ list has caused the stop status to be noisy. A valid example
+ of this is a new thread event and a software watchpoint have
+ both occurred. */
+ if (bs->next)
+ return PRINT_UNKNOWN;
+
printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
return PRINT_NOTHING;
break;
@@ -2658,6 +2748,54 @@
}
}
+/* Check watchpoints for a match with a stopped data address.
+
+ STOPPED_DATA_ADDRESS is the address of a triggered watchpoint.
+ A match with an existing watchpoint will cause that watchpoint
+ to be marked as triggered.
+
+ This function is only used for platforms where a watchpoint
+ triggers prior to the data being accessed. */
+
+void
+mark_triggered_watchpoints (CORE_ADDR stopped_data_address)
+{
+ struct breakpoint *b, *temp;
+ CORE_ADDR addr = stopped_data_address;
+ struct value *v;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ if (b->type == bp_hardware_watchpoint
+ || b->type == bp_read_watchpoint
+ || b->type == bp_access_watchpoint)
+ {
+ for (v = b->val_chain; v; v = value_next(v))
+ {
+ if (VALUE_LVAL (v) == lval_memory
+ && ! value_lazy (v))
+ {
+ struct type *vtype = check_typedef (value_type (v));
+
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR vaddr;
+
+ vaddr = VALUE_ADDRESS (v) + value_offset (v);
+ /* Exact match not required. Within range is
+ sufficient. */
+ if (addr >= vaddr &&
+ addr < vaddr + TYPE_LENGTH (value_type (v)))
+ b->watchpoint_triggered = 1;
+ }
+ }
+ }
+ }
+ }
+}
+
/* Get a bpstat associated with having just stopped at address
BP_ADDR in thread PTID. STOPPED_BY_WATCHPOINT is 1 if the
target thinks we stopped due to a hardware watchpoint, 0 if we
@@ -2788,82 +2926,61 @@
bs->stop = 1;
bs->print = 1;
- if (b->type == bp_watchpoint ||
- b->type == bp_hardware_watchpoint)
- {
- char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
- b->number);
- struct cleanup *cleanups = make_cleanup (xfree, message);
- int e = catch_errors (watchpoint_check, bs, message,
- RETURN_MASK_ALL);
- do_cleanups (cleanups);
- switch (e)
- {
- case WP_DELETED:
- /* We've already printed what needs to be printed. */
- /* Actually this is superfluous, because by the time we
- call print_it_typical() the wp will be already deleted,
- and the function will return immediately. */
- bs->print_it = print_it_done;
- /* Stop. */
- break;
- case WP_VALUE_CHANGED:
- /* Stop. */
- ++(b->hit_count);
- break;
- case WP_VALUE_NOT_CHANGED:
- /* Don't stop. */
- bs->print_it = print_it_noop;
- bs->stop = 0;
- continue;
- default:
- /* Can't happen. */
- /* FALLTHROUGH */
- case 0:
- /* Error from catch_errors. */
- printf_filtered (_("Watchpoint %d deleted.\n"), b->number);
- if (b->related_breakpoint)
- b->related_breakpoint->disposition = disp_del_at_next_stop;
- b->disposition = disp_del_at_next_stop;
- /* We've already printed what needs to be printed. */
- bs->print_it = print_it_done;
-
- /* Stop. */
- break;
- }
- }
- else if (b->type == bp_read_watchpoint ||
- b->type == bp_access_watchpoint)
+ if (b->type == bp_watchpoint
+ || b->type == bp_read_watchpoint
+ || b->type == bp_access_watchpoint
+ || b->type == bp_hardware_watchpoint)
{
CORE_ADDR addr;
struct value *v;
- int found = 0;
+ int must_check_value = 0;
- if (!target_stopped_data_address (¤t_target, &addr))
- continue;
- for (v = b->val_chain; v; v = value_next (v))
+ if (b->type == bp_watchpoint
+ || b->watchpoint_triggered
+ || (b->type == bp_hardware_watchpoint
+ && !target_stopped_data_address_p (¤t_target)))
{
- if (VALUE_LVAL (v) == lval_memory
- && ! value_lazy (v))
+ /* We either have a software watchpoint, a triggered watchpoint
+ which we have stepped over, or we cannot ascertain what data
+ address causes a write watchpoint. In all these
+ cases, we must check the watchpoint value. */
+ b->watchpoint_triggered = 0;
+ must_check_value = 1;
+ }
+ else
+ {
+ /* At this point, we know target_stopped_data_address () works or
+ we have a read or access watchpoint and have no alternatives. */
+ if (!target_stopped_data_address (¤t_target, &addr))
{
- struct type *vtype = check_typedef (value_type (v));
-
- if (v == b->val_chain
- || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
- && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ continue;
+ }
+ for (v = b->val_chain; v; v = value_next(v))
+ {
+ if (VALUE_LVAL (v) == lval_memory
+ && ! value_lazy (v))
{
- CORE_ADDR vaddr;
+ struct type *vtype = check_typedef (value_type (v));
- vaddr = VALUE_ADDRESS (v) + value_offset (v);
- /* Exact match not required. Within range is
- sufficient. */
- if (addr >= vaddr &&
- addr < vaddr + TYPE_LENGTH (value_type (v)))
- found = 1;
+ if (v == b->val_chain
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+ CORE_ADDR vaddr;
+
+ vaddr = VALUE_ADDRESS (v) + value_offset (v);
+ /* Exact match not required. Within range is
+ sufficient. */
+ if (addr >= vaddr &&
+ addr < vaddr + TYPE_LENGTH (value_type (v)))
+ must_check_value = 1;
+ }
}
}
}
- if (found)
+ if (must_check_value)
{
char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
b->number);
@@ -2892,6 +3009,15 @@
break;
case WP_VALUE_NOT_CHANGED:
/* Stop. */
+ if (b->type == bp_hardware_watchpoint
+ || b->type == bp_watchpoint)
+ {
+ /* Don't stop: write watchpoints shouldn't fire if
+ the value hasn't changed. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ continue;
+ }
++(b->hit_count);
break;
default:
@@ -2907,7 +3033,7 @@
break;
}
}
- else /* found == 0 */
+ else /* must_check_value == 0 */
{
/* This is a case where some watchpoint(s) triggered,
but not at the address of this watchpoint (FOUND
@@ -4208,6 +4334,7 @@
b->exec_pathname = NULL;
b->ops = NULL;
b->pending = 0;
+ b->watchpoint_triggered = 0;
/* Add this breakpoint to the end of the chain
so that a list of breakpoints will come out in order
Index: gdb/breakpoint.h
===================================================================
--- gdb.orig/breakpoint.h 2007-08-10 14:32:29.000000000 -0700
+++ gdb/breakpoint.h 2007-08-13 06:21:29.000000000 -0700
@@ -422,6 +422,11 @@
/* Is breakpoint pending on shlib loads? */
int pending;
+
+ /* Has a watchpoint been triggered? This is only used for
+ non-continuable watchpoints which trigger prior to the data
+ being modified. */
+ int watchpoint_triggered;
};
/* The following stuff is an abstract data type "bpstat" ("breakpoint
@@ -687,6 +692,14 @@
extern int insert_breakpoints (void);
+/* The following provides a callback mechanism to insert watchpoints
+ for a new thread. This is needed, for example, on ia64 linux. */
+typedef int (insert_watchpoint_ftype) (ptid_t, CORE_ADDR, int, int);
+extern int insert_watchpoints_for_new_thread (ptid_t ptid,
+ insert_watchpoint_ftype *iwpfn);
+
+extern void mark_triggered_watchpoints (CORE_ADDR);
+
extern int remove_breakpoints (void);
/* This function can be used to physically insert eventpoints from the
Index: gdb/linux-nat.c
===================================================================
--- gdb.orig/linux-nat.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/linux-nat.c 2007-08-13 06:21:29.000000000 -0700
@@ -36,6 +36,7 @@
#include "gdbthread.h"
#include "gdbcmd.h"
#include "regcache.h"
+#include "observer.h"
#include "regset.h"
#include "inf-ptrace.h"
#include "auxv.h"
@@ -706,6 +707,9 @@
else
lwp_list = lp->next;
+ if (lp->saved_trap_data)
+ xfree (lp->saved_trap_data);
+
xfree (lp);
}
@@ -1503,6 +1507,13 @@
user will delete or disable the breakpoint, but the
thread will have already tripped on it. */
+ /* Notify any observers that we have a SIGTRAP.
+ This is needed on platforms that must save more state
+ than just the trap. For example, ia64 linux uses
+ siginfo to determine if a watchpoint has occurred and
+ this information gets trashed by a SIGSTOP. */
+ observer_notify_sigtrap (lp);
+
/* Now resume this LWP and get the SIGSTOP event. */
errno = 0;
ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
@@ -2060,6 +2071,14 @@
target_pid_to_str (lp->ptid));
}
+ /* For platforms such as ia64, a hardware watchpoint is
+ determined by looking at special information available
+ at the time time of the trap (siginfo). This information
+ is not preserved if we choose to take an event on another
+ thread and later come back to this event, thus we must
+ notify an observer so the information can be stored. */
+ observer_notify_sigtrap (lp);
+
/* Handle GNU/Linux's extended waitstatus for trace events. */
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
{
Index: gdb/linux-nat.h
===================================================================
--- gdb.orig/linux-nat.h 2007-08-10 14:32:29.000000000 -0700
+++ gdb/linux-nat.h 2007-08-13 06:21:29.000000000 -0700
@@ -63,6 +63,18 @@
/* Next LWP in list. */
struct lwp_info *next;
+
+ /* Optional saved trap state for when a trap gets pushed back
+ due to multiple events occurring at the same time. */
+ void *saved_trap_data;
+};
+
+/* Watchpoint description. */
+struct linux_watchpoint
+{
+ CORE_ADDR addr;
+ int len;
+ int type;
};
/* Attempt to initialize libthread_db. */
Index: gdb/Makefile.in
===================================================================
--- gdb.orig/Makefile.in 2007-08-10 14:32:29.000000000 -0700
+++ gdb/Makefile.in 2007-08-13 06:21:33.000000000 -0700
@@ -555,6 +555,7 @@
p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
prologue-value.c \
regcache.c reggroups.c remote.c remote-fileio.c \
+ scm-exp.c scm-lang.c scm-valprint.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c \
solib.c solib-null.c source.c \
@@ -787,6 +788,8 @@
remote_h = remote.h
rs6000_tdep_h = rs6000-tdep.h $(defs_h)
s390_tdep_h = s390-tdep.h
+scm_lang_h = scm-lang.h $(scm_tags_h)
+scm_tags_h = scm-tags.h
score_tdep_h = score-tdep.h
sentinel_frame_h = sentinel-frame.h
serial_h = serial.h
@@ -810,7 +813,7 @@
srec_h = srec.h
stabsread_h = stabsread.h
stack_h = stack.h
-symfile_h = symfile.h
+symfile_h = symfile.h $(symtab_h)
symtab_h = symtab.h
target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) $(vec_h)
target_descriptions_h = target-descriptions.h
@@ -833,6 +836,7 @@
wrapper_h = wrapper.h $(gdb_h)
xcoffsolib_h = xcoffsolib.h
xml_support_h = xml-support.h $(gdb_obstack_h) $(vec_h)
+xml_tdesc_h = xml-tdesc.h
xtensa_tdep_h = xtensa-tdep.h
#
@@ -958,6 +962,7 @@
varobj.o vec.o wrapper.o \
jv-lang.o jv-valprint.o jv-typeprint.o \
m2-lang.o p-lang.o p-typeprint.o p-valprint.o \
+ scm-exp.o scm-lang.o scm-valprint.o \
sentinel-frame.o \
complaints.o typeprint.o \
ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
@@ -1702,7 +1707,7 @@
$(gdbcore_h) $(hashtab_h) $(gdb_obstack_h) $(ada_lang_h) \
$(completer_h) $(gdb_stat_h) $(ui_out_h) $(block_h) $(infcall_h) \
$(dictionary_h) $(exceptions_h) $(annotate_h) $(valprint_h) \
- $(source_h)
+ $(source_h) $(observer_h)
ada-typeprint.o: ada-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) \
$(symtab_h) $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) \
$(target_h) $(command_h) $(gdbcmd_h) $(language_h) $(demangle_h) \
@@ -1758,7 +1763,7 @@
amd64-linux-nat.o: amd64-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(regcache_h) $(linux_nat_h) $(gdb_assert_h) $(gdb_string_h) \
$(gdb_proc_service_h) $(gregset_h) $(amd64_tdep_h) \
- $(i386_linux_tdep_h) $(amd64_nat_h) $(target_h) $(amd64_linux_tdep_h)
+ $(i386_linux_tdep_h) $(amd64_nat_h) $(amd64_linux_tdep_h)
amd64-linux-tdep.o: amd64-linux-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \
$(regcache_h) $(osabi_h) $(symtab_h) $(gdb_string_h) $(amd64_tdep_h) \
$(solib_svr4_h) $(gdbtypes_h) $(reggroups_h) $(amd64_linux_tdep_h)
@@ -1817,6 +1822,8 @@
$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(objfiles_h) \
$(dwarf2_frame_h) $(gdbtypes_h) $(prologue_value_h) \
$(target_descriptions_h) $(user_regs_h)
+arm-wince-tdep.o: arm-wince-tdep.c $(defs_h) $(osabi_h) $(solib_svr4_h) \
+ $(target_h) $(gdb_string_h) $(arm_tdep_h)
auxv.o: auxv.c $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) \
$(inferior_h) $(valprint_h) $(gdb_assert_h) $(auxv_h) \
$(elf_common_h)
@@ -1845,8 +1852,8 @@
$(gdb_string_h) $(demangle_h) $(annotate_h) $(symfile_h) \
$(objfiles_h) $(source_h) $(linespec_h) $(completer_h) $(gdb_h) \
$(ui_out_h) $(cli_script_h) $(gdb_assert_h) $(block_h) $(solib_h) \
- $(solist_h) $(observer_h) $(exceptions_h) $(gdb_events_h) $(mi_common_h) \
- $(memattr_h) $(ada_lang_h)
+ $(solist_h) $(observer_h) $(exceptions_h) $(gdb_events_h) \
+ $(mi_common_h) $(memattr_h) $(ada_lang_h) $(top_h)
bsd-kvm.o: bsd-kvm.c $(defs_h) $(cli_cmds_h) $(command_h) $(frame_h) \
$(regcache_h) $(target_h) $(value_h) $(gdbcore_h) $(gdb_assert_h) \
$(readline_h) $(bsd_kvm_h)
@@ -1975,7 +1982,8 @@
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
$(terminal_h) $(event_loop_h) $(event_top_h) $(interps_h) \
- $(exceptions_h) $(gdbcmd_h) $(readline_h) $(readline_history_h)
+ $(exceptions_h) $(cli_script_h) $(gdbcmd_h) $(readline_h) \
+ $(readline_history_h)
exceptions.o: exceptions.c $(defs_h) $(exceptions_h) $(breakpoint_h) \
$(target_h) $(inferior_h) $(annotate_h) $(ui_out_h) $(gdb_assert_h) \
$(gdb_string_h) $(serial_h)
@@ -2071,7 +2079,7 @@
$(osabi_h) $(frame_h) $(frame_unwind_h) $(trad_frame_h) $(symtab_h) \
$(objfiles_h) $(inferior_h) $(infcall_h) $(observer_h) \
$(hppa_tdep_h) $(solib_som_h) $(solib_pa64_h) $(regset_h) \
- $(regcache_h) $(exceptions_h) $(gdb_string_h)
+ $(regcache_h) $(exceptions_h) $(gdb_string_h) $(hppa_tdep_h)
hppa-linux-nat.o: hppa-linux-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
$(gdb_string_h) $(inferior_h) $(hppa_tdep_h) $(gregset_h) \
$(target_h) $(linux_nat_h)
@@ -2114,7 +2122,8 @@
$(i386_linux_tdep_h) $(glibc_tdep_h) $(solib_svr4_h) $(symtab_h)
i386-nat.o: i386-nat.c $(defs_h) $(breakpoint_h) $(command_h) $(gdbcmd_h)
i386nbsd-nat.o: i386nbsd-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
- $(target_h) $(i386_tdep_h) $(i386bsd_nat_h) $(bsd_kvm_h)
+ $(target_h) $(i386_tdep_h) $(i386bsd_nat_h) $(nbsd_nat_h) \
+ $(bsd_kvm_h)
i386nbsd-tdep.o: i386nbsd-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) \
$(gdbcore_h) $(regcache_h) $(regset_h) $(osabi_h) $(symtab_h) \
$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h) \
@@ -2148,7 +2157,7 @@
$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h)
ia64-linux-nat.o: ia64-linux-nat.c $(defs_h) $(gdb_string_h) $(inferior_h) \
$(target_h) $(gdbcore_h) $(regcache_h) $(ia64_tdep_h) $(gdb_wait_h) \
- $(gregset_h) $(linux_nat_h)
+ $(gregset_h) $(observer_h) $(linux_nat_h)
ia64-linux-tdep.o: ia64-linux-tdep.c $(defs_h) $(ia64_tdep_h) \
$(arch_utils_h) $(gdbcore_h) $(regcache_h) $(osabi_h) $(solib_svr4_h) \
$(symtab_h)
@@ -2203,7 +2212,8 @@
jv-lang.o: jv-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(gdbtypes_h) $(symtab_h) \
$(symfile_h) $(objfiles_h) $(gdb_string_h) $(value_h) $(c_lang_h) \
- $(jv_lang_h) $(gdbcore_h) $(block_h) $(demangle_h) $(dictionary_h)
+ $(jv_lang_h) $(gdbcore_h) $(block_h) $(demangle_h) $(dictionary_h) \
+ $(gdb_assert_h)
jv-typeprint.o: jv-typeprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(demangle_h) $(jv_lang_h) $(gdb_string_h) $(typeprint_h) \
$(c_lang_h) $(cp_abi_h)
@@ -2220,7 +2230,7 @@
linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
$(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \
$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
- $(objc_lang_h) $(linespec_h) $(exceptions_h)
+ $(objc_lang_h) $(linespec_h) $(exceptions_h) $(language_h)
linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \
$(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \
$(linux_nat_h)
@@ -2239,10 +2249,13 @@
m2-lang.o: m2-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(m2_lang_h) $(c_lang_h) \
$(valprint_h)
-m2-typeprint.o: m2-typeprint.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
- $(expression_h) $(value_h) $(gdbcore_h) $(target_h) $(m2_lang_h)
+m2-typeprint.o: m2-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) \
+ $(symtab_h) $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) \
+ $(m2_lang_h) $(target_h) $(language_h) $(demangle_h) $(c_lang_h) \
+ $(typeprint_h) $(cp_abi_h) $(gdb_string_h)
m2-valprint.o: m2-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
- $(m2_lang_h) $(c_lang_h)
+ $(expression_h) $(value_h) $(valprint_h) $(language_h) \
+ $(typeprint_h) $(c_lang_h) $(m2_lang_h) $(target_h)
m32c-tdep.o: m32c-tdep.c $(defs_h) $(gdb_assert_h) $(elf_bfd_h) \
$(elf_m32c_h) $(gdb_sim_m32c_h) $(dis_asm_h) $(gdbtypes_h) \
$(regcache_h) $(arch_utils_h) $(frame_h) $(frame_unwind_h) \
@@ -2384,7 +2397,7 @@
monitor.o: monitor.c $(defs_h) $(gdbcore_h) $(target_h) $(exceptions_h) \
$(gdb_string_h) $(command_h) $(serial_h) $(monitor_h) $(gdbcmd_h) \
$(inferior_h) $(gdb_regex_h) $(srec_h) $(regcache_h)
-ms1-tdep.o: ms1-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) $(frame_base_h) \
+mt-tdep.o: mt-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) $(frame_base_h) \
$(symtab_h) $(dis_asm_h) $(arch_utils_h) $(gdbtypes_h) \
$(gdb_string_h) $(regcache_h) $(reggroups_h) $(gdbcore_h) \
$(trad_frame_h) $(inferior_h) $(dwarf2_frame_h) $(infcall_h) \
@@ -2498,8 +2511,6 @@
remote-fileio.o: remote-fileio.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) \
$(remote_h) $(gdb_fileio_h) $(gdb_wait_h) $(gdb_stat_h) \
$(exceptions_h) $(remote_fileio_h)
-remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
- $(serial_h) $(regcache_h)
remote-m32r-sdi.o: remote-m32r-sdi.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
$(inferior_h) $(target_h) $(regcache_h) $(gdb_string_h) $(serial_h)
remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \
@@ -2527,13 +2538,22 @@
rs6000-aix-tdep.o: rs6000-aix-tdep.c $(defs_h) $(gdb_string_h) $(osabi_h) \
$(regcache_h) $(regset_h) $(rs6000_tdep_h) $(ppc_tdep_h)
s390-nat.o: s390-nat.c $(defs_h) $(regcache_h) $(inferior_h) \
- $(s390_tdep_h) $(target_h) $(linux_nat_h)
+ $(s390_tdep_h) $(target_h) $(observer_h) $(linux_nat_h)
s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) \
$(floatformat_h) $(regcache_h) $(trad_frame_h) $(frame_base_h) \
$(frame_unwind_h) $(dwarf2_frame_h) $(reggroups_h) $(regset_h) \
$(value_h) $(gdb_assert_h) $(dis_asm_h) $(solib_svr4_h) \
$(prologue_value_h) $(s390_tdep_h)
+scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
+ $(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
+ $(scm_tags_h)
+scm-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
+ $(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
+ $(scm_tags_h) $(source_h) $(gdb_string_h) $(gdbcore_h) $(infcall_h)
+scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
+ $(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
+ $(scm_lang_h) $(valprint_h) $(gdbcore_h) $(c_lang_h)
score-tdep.o: score-tdep.c $(defs_h) $(gdb_assert_h) $(inferior_h) \
$(symtab_h) $(objfiles_h) $(gdbcore_h) $(target_h) \
$(arch_utils_h) $(regcache_h) $(dis_asm_h) $(frame_unwind_h) \
@@ -2626,7 +2646,7 @@
$(gregset_h) $(sparc64_tdep_h) $(sparc_tdep_h) \
$(sparc_nat_h) $(inferior_h) $(target_h) $(linux_nat_h)
sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(frame_h) \
- $(frame_unwind_h) $(dwarf2-frame_h) $(regset_h) $(regcache_h) \
+ $(frame_unwind_h) $(dwarf2_frame_h) $(regset_h) $(regcache_h) \
$(gdbarch_h) $(gdbcore_h) $(osabi_h) $(solib_svr4_h) $(symtab_h) \
$(trad_frame_h) $(tramp_frame_h) $(sparc64_tdep_h)
sparc64-nat.o: sparc64-nat.c $(defs_h) $(gdbarch_h) $(sparc64_tdep_h) \
@@ -2727,7 +2747,7 @@
$(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \
$(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \
$(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h) \
- $(solist_h)
+ $(solist_h) $(ada_lang_h)
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
@@ -2808,7 +2828,7 @@
$(frame_unwind_h) $(osabi_h) $(symtab_h) $(trad_frame_h) \
$(vax_tdep_h) $(gdb_string_h)
vax-tdep.o: vax-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) \
- $(float_format_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
+ $(floatformat_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
$(gdbcore_h) $(gdbtypes_h) $(osabi_h) $(regcache_h) $(regset_h) \
$(trad_frame_h) $(value_h) $(gdb_string_h) $(vax_tdep_h)
vec.o: vec.c $(defs_h) $(vec_h)
@@ -2817,6 +2837,7 @@
$(regcache_h) $(top_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \
$(gdb_string_h) $(gdbthread_h) $(gdbcmd_h) $(exec_h) $(solist_h) \
$(solib_h) $(i386_tdep_h) $(i387_tdep_h)
+win32-termcap.o: win32-termcap.c
wrapper.o: wrapper.c $(defs_h) $(value_h) $(exceptions_h) $(wrapper_h) \
$(ui_out_h)
xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \
@@ -2836,9 +2857,6 @@
$(gdbcmd_h) $(gdbcore_h) $(value_h) $(dis_asm_h) $(inferior_h) \
$(gdb_string_h) $(gdb_assert_h) $(arch_utils_h) $(floatformat_h) \
$(regcache_h) $(doublest_h) $(osabi_h) $(objfiles_h)
-xtensa-linux-tdep.o: xtensa-linux-tdep.c $(defs_h) $(inferior_h) \
- $(gdbcore_h) $(regcache_h) $(osabi_h) $(gdb_string_h) \
- $(xtensa_tdep_h) $(xtensa_linux_tdep_h)
xtensa-tdep.o: xtensa-tdep.c $(defs_h) $(doublest_h) $(frame_h) \
$(frame_unwind_h) $(frame_base_h) $(inferior_h) $(symtab_h) \
$(value_h) $(gdbcmd_h) $(gdbcore_h) $(dis_asm_h) $(symfile_h) \
@@ -2878,7 +2896,7 @@
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
Index: gdb/linux-thread-db.c
===================================================================
--- gdb.orig/linux-thread-db.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/linux-thread-db.c 2007-08-13 06:21:29.000000000 -0700
@@ -36,6 +36,7 @@
#include "target.h"
#include "regcache.h"
#include "solib-svr4.h"
+#include "observer.h"
#include "gdbcore.h"
#include "observer.h"
#include "linux-nat.h"
@@ -675,6 +676,7 @@
{
struct thread_info *tp;
td_err_e err;
+ ptid_t new_ptid;
/* If we're being called after a TD_CREATE event, we may already
know about this thread. There are two ways this can happen. We
@@ -893,7 +895,8 @@
thread_db_find_new_threads ();
if (ourstatus->kind == TARGET_WAITKIND_STOPPED
- && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
+ && (ourstatus->value.sig == TARGET_SIGNAL_TRAP
+ || ourstatus->value.sig == TARGET_SIGNAL_ILL))
/* Check for a thread event. */
check_event (ptid);
Index: gdb/i386-linux-nat.c
===================================================================
--- gdb.orig/i386-linux-nat.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/i386-linux-nat.c 2007-08-13 06:22:11.000000000 -0700
@@ -587,10 +587,9 @@
int tid;
unsigned long value;
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid);
/* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
ptrace call fails breaks debugging remote targets. The correct
@@ -615,10 +614,9 @@
{
int tid;
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid);
errno = 0;
ptrace (PTRACE_POKEUSER, tid,
Index: gdb/ia64-linux-nat.c
===================================================================
--- gdb.orig/ia64-linux-nat.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/ia64-linux-nat.c 2007-08-13 06:21:29.000000000 -0700
@@ -29,6 +29,7 @@
#include "regcache.h"
#include "ia64-tdep.h"
#include "linux-nat.h"
+#include "observer.h"
#include <signal.h>
#include <sys/ptrace.h>
@@ -552,10 +553,10 @@
return onecount <= 1;
}
+/* Internal routine to insert one watchpoint for a specified thread. */
static int
-ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
+ia64_linux_insert_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
{
- ptid_t ptid = inferior_ptid;
int idx;
long dbr_addr, dbr_mask;
int max_watchpoints = 4;
@@ -600,10 +601,39 @@
return 0;
}
+/* Internal callback routine which can be used via iterate_over_lwps
+ to insert a specific watchpoint from all active threads. */
static int
-ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
+ia64_linux_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+ struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+ return ia64_linux_insert_one_watchpoint (lwp->ptid, args->addr,
+ args->len, args->type);
+}
+
+/* Insert a watchpoint for all threads. */
+int
+ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+ struct linux_watchpoint args;
+
+ args.addr = addr;
+ args.len = len;
+ args.type = rw;
+
+ /* For ia64, watchpoints must be inserted/removed on each thread so
+ we iterate over the lwp list. */
+ if (iterate_over_lwps (&ia64_linux_insert_watchpoint_callback, &args))
+ return -1;
+
+ return 0;
+}
+
+/* Internal routine to remove one watchpoint for a specified thread. */
+static int
+ia64_linux_remove_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
{
- ptid_t ptid = inferior_ptid;
int idx;
long dbr_addr, dbr_mask;
int max_watchpoints = 4;
@@ -625,13 +655,56 @@
return -1;
}
+/* Internal callback routine which can be used via iterate_over_lwps
+ to remove a specific watchpoint from all active threads. */
+static int
+ia64_linux_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+ struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+ return ia64_linux_remove_one_watchpoint (lwp->ptid, args->addr,
+ args->len);
+}
+
+/* Remove a watchpoint for all threads. */
+int
+ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+ struct linux_watchpoint args;
+
+ args.addr = addr;
+ args.len = len;
+ args.type = rw;
+
+ /* For ia64, watchpoints must be inserted/removed on each thread so
+ we iterate over the lwp list. */
+ if (iterate_over_lwps (&ia64_linux_remove_watchpoint_callback, &args))
+ return -1;
+
+ return 0;
+}
+
+/* Callback to find lwp_info struct for a given lwp. */
+static int
+find_lwp_info (struct lwp_info *lp, void *data)
+{
+ int lwp = *(int *)data;
+
+ if (lwp == TIDGET (lp->ptid))
+ return 1;
+
+ return 0;
+}
+
static int
ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
{
CORE_ADDR psr;
int tid;
struct siginfo siginfo;
+ struct siginfo *siginfo_p;
ptid_t ptid = inferior_ptid;
+ struct lwp_info *lp;
struct regcache *regcache = get_current_regcache ();
tid = TIDGET(ptid);
@@ -639,10 +712,19 @@
tid = PIDGET (ptid);
errno = 0;
- ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+ /* Check to see if we have already cached the siginfo for this
+ event. */
+ lp = iterate_over_lwps (find_lwp_info, &tid);
+ if (lp && lp->saved_trap_data != NULL)
+ siginfo_p = (struct siginfo *)lp->saved_trap_data;
+ else
+ {
+ siginfo_p = &siginfo;
+ ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, siginfo_p);
+ }
- if (errno != 0 || siginfo.si_signo != SIGTRAP ||
- (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
+ if (errno != 0 || siginfo_p->si_signo != SIGTRAP ||
+ (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
return 0;
regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr);
@@ -650,7 +732,7 @@
for the next instruction */
regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
- *addr_p = (CORE_ADDR)siginfo.si_addr;
+ *addr_p = (CORE_ADDR)siginfo_p->si_addr;
return 1;
}
@@ -798,6 +880,31 @@
offset, len);
}
+/* Observer function for a new thread attach. We need to insert
+ existing watchpoints on the new thread. */
+static void
+ia64_linux_new_thread (ptid_t ptid)
+{
+ insert_watchpoints_for_new_thread (ptid,
+ &ia64_linux_insert_one_watchpoint);
+}
+
+/* For ia64 linux, we must save the siginfo data as part of the state
+ of a queued SIGTRAP. This is because siginfo is used to determine
+ if a watchpoint has occurred and the information will be lost if
+ a SIGSTOP is issued to the thread. */
+void
+ia64_linux_save_sigtrap_info (void *queue_data)
+{
+ struct lwp_info *lp = (struct lwp_info *)queue_data;
+
+ if (lp->saved_trap_data == NULL)
+ lp->saved_trap_data = xmalloc (sizeof(struct siginfo));
+
+ ptrace (PTRACE_GETSIGINFO, ptid_get_lwp (lp->ptid), (PTRACE_TYPE_ARG3) 0,
+ lp->saved_trap_data);
+}
+
void _initialize_ia64_linux_nat (void);
void
@@ -836,4 +943,7 @@
/* Register the target. */
linux_nat_add_target (t);
+
+ observer_attach_linux_new_thread (ia64_linux_new_thread);
+ observer_attach_sigtrap (ia64_linux_save_sigtrap_info);
}
Index: gdb/amd64-linux-nat.c
===================================================================
--- gdb.orig/amd64-linux-nat.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/amd64-linux-nat.c 2007-08-13 06:22:11.000000000 -0700
@@ -242,10 +242,9 @@
int tid;
unsigned long value;
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid);
/* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
ptrace call fails breaks debugging remote targets. The correct
@@ -270,10 +269,9 @@
{
int tid;
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid);
errno = 0;
ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
Index: gdb/s390-nat.c
===================================================================
--- gdb.orig/s390-nat.c 2007-08-10 14:32:29.000000000 -0700
+++ gdb/s390-nat.c 2007-08-13 06:21:29.000000000 -0700
@@ -29,6 +29,7 @@
#include "linux-nat.h"
#include "s390-tdep.h"
+#include "observer.h"
#include <asm/ptrace.h>
#include <sys/ptrace.h>
@@ -113,14 +114,14 @@
(char *)regp + regmap_fpregset[i]);
}
-/* Find the TID for the current inferior thread to use with ptrace. */
+/* Find the TID for use with ptrace. */
static int
-s390_inferior_tid (void)
+s390_tid (ptid_t ptid)
{
/* GNU/Linux LWP ID's are process ID's. */
- int tid = TIDGET (inferior_ptid);
+ int tid = TIDGET (ptid);
if (tid == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = PIDGET (ptid); /* Not a threaded program. */
return tid;
}
@@ -204,7 +205,7 @@
static void
s390_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
{
- int tid = s390_inferior_tid ();
+ int tid = s390_tid (inferior_ptid);
if (regnum == -1
|| (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
@@ -220,7 +221,7 @@
static void
s390_linux_store_inferior_registers (struct regcache *regcache, int regnum)
{
- int tid = s390_inferior_tid ();
+ int tid = s390_tid (inferior_ptid);
if (regnum == -1
|| (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
@@ -262,7 +263,7 @@
parea.len = sizeof (per_lowcore);
parea.process_addr = (addr_t) & per_lowcore;
parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
- if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
+ if (ptrace (PTRACE_PEEKUSR_AREA, s390_tid (inferior_ptid), &parea) < 0)
perror_with_name (_("Couldn't retrieve watchpoint status"));
return per_lowcore.perc_storage_alteration == 1
@@ -270,9 +271,9 @@
}
static void
-s390_fix_watch_points (void)
+s390_fix_watch_points (ptid_t ptid)
{
- int tid = s390_inferior_tid ();
+ int tid = s390_tid (ptid);
per_struct per_info;
ptrace_area parea;
@@ -309,6 +310,16 @@
perror_with_name (_("Couldn't modify watchpoint status"));
}
+/* Callback routine to use with iterate_over_lwps to insert a specified
+ watchpoint on all threads. */
+static int
+s390_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+ s390_fix_watch_points (lwp->ptid);
+ return 0;
+}
+
+/* Insert a specified watchpoint on all threads. */
static int
s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
{
@@ -322,10 +333,24 @@
area->next = watch_base;
watch_base = area;
- s390_fix_watch_points ();
+ /* For the S390, a watchpoint must be inserted/removed for each
+ thread so we iterate over the list of existing lwps. */
+ if (iterate_over_lwps (&s390_insert_watchpoint_callback, NULL))
+ return -1;
+
return 0;
}
+/* Callback routine to use with iterate_over_lwps to remove a specified
+ watchpoint from all threads. */
+static int
+s390_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+ s390_fix_watch_points (lwp->ptid);
+ return 0;
+}
+
+/* Remove a specified watchpoint from all threads. */
static int
s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
{
@@ -347,7 +372,11 @@
*parea = area->next;
xfree (area);
- s390_fix_watch_points ();
+ /* For the S390, a watchpoint must be inserted/removed for each
+ thread so we iterate over the list of existing lwps. */
+ if (iterate_over_lwps (&s390_remove_watchpoint_callback, NULL))
+ return -1;
+
return 0;
}
@@ -363,6 +392,15 @@
return 1;
}
+/* New thread observer that inserts all existing watchpoints on the
+ new thread. */
+static void
+s390_linux_new_thread (ptid_t ptid)
+{
+ /* Add existing watchpoints to new thread. */
+ s390_fix_watch_points (ptid);
+}
+
void _initialize_s390_nat (void);
@@ -388,4 +426,6 @@
/* Register the target. */
linux_nat_add_target (t);
+
+ observer_attach_linux_new_thread (s390_linux_new_thread);
}