From: Yao Qi <yao@codesourcery.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH 3/7] range stepping: gdbserver on x86/linux
Date: Thu, 11 Apr 2013 06:18:00 -0000 [thread overview]
Message-ID: <1365648222-12540-4-git-send-email-yao@codesourcery.com> (raw)
In-Reply-To: <1365648222-12540-1-git-send-email-yao@codesourcery.com>
This patch adds the support of range stepping in GDBserver for
x86/linux.
gdb/gdbserver:
2013-03-11 Yao Qi <yao@codesourcery.com>
* gdbthread.h (struct thread_info) <start, end>: New fields.
(thread_in_range_stepping_p): Declare.
(thread_clear_range_stepping): Declare.
* inferiors.c (thread_clear_range_stepping): New.
(add_thread): Call thread_clear_range_stepping.
(thread_in_range_stepping_p): New.
* linux-low.c (linux_wait_1): Call thread_in_range_stepping_p
to check if report stop to GDB.
Call thread_clear_range_stepping.
(linux_supports_range_stepping): New.
(linux_target_ops): Initialize 'supports_range_stepping' to
linux_supports_range_stepping.
* linux-low.h (struct linux_target_ops)
<supports_range_stepping>: New field.
* linux-x86-low.c (x86_supports_range_stepping): New.
(the_low_target): Initialize 'supports_range_stepping' to
* server.c (handle_v_cont): Handle action 'r'.
(handle_v_requests): Append ";r" if target supports range
stepping.
* target.h (struct target_ops) <supports_range_stepping>>:
New field.
(target_supports_range_stepping): New macro.
---
gdb/gdbserver/gdbthread.h | 6 ++++++
gdb/gdbserver/inferiors.c | 19 +++++++++++++++++++
gdb/gdbserver/linux-low.c | 38 +++++++++++++++++++++++++++++++++++---
gdb/gdbserver/linux-low.h | 2 ++
gdb/gdbserver/linux-x86-low.c | 7 +++++++
gdb/gdbserver/server.c | 40 ++++++++++++++++++++++++++++++++++++++++
gdb/gdbserver/target.h | 6 ++++++
7 files changed, 115 insertions(+), 3 deletions(-)
diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
index 5d4955b..fbd768b 100644
--- a/gdb/gdbserver/gdbthread.h
+++ b/gdb/gdbserver/gdbthread.h
@@ -62,12 +62,18 @@ struct thread_info
/* Branch trace target information for this thread. */
struct btrace_target_info *btrace;
+
+ /* The start and end address of range stepping. */
+ CORE_ADDR start, end;
};
extern struct inferior_list all_threads;
void remove_thread (struct thread_info *thread);
void add_thread (ptid_t ptid, void *target_data);
+int thread_in_range_stepping_p (struct thread_info *thread,
+ CORE_ADDR pc);
+void thread_clear_range_stepping (struct thread_info *thread);
struct thread_info *find_thread_ptid (ptid_t ptid);
struct thread_info *gdb_id_to_thread (unsigned int);
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 6953d0e..2184a7b 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -85,6 +85,15 @@ remove_inferior (struct inferior_list *list,
list->tail = *cur;
}
+/* Clear the state of range stepping of THREAD. */
+
+void
+thread_clear_range_stepping (struct thread_info *thread)
+{
+ thread->start = 0;
+ thread->end = 0;
+}
+
void
add_thread (ptid_t thread_id, void *target_data)
{
@@ -103,6 +112,16 @@ add_thread (ptid_t thread_id, void *target_data)
new_thread->target_data = target_data;
set_inferior_regcache_data (new_thread, new_register_cache ());
+ thread_clear_range_stepping (new_thread);
+}
+
+/* Return true if THREAD is in range stepping. PC is the value of pc
+ of THREAD. */
+
+int
+thread_in_range_stepping_p (struct thread_info *thread, CORE_ADDR pc)
+{
+ return (pc >= thread->start && pc < thread->end);
}
ptid_t
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 72c51e0..e9879cc 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -2313,6 +2313,7 @@ linux_wait_1 (ptid_t ptid,
int maybe_internal_trap;
int report_to_gdb;
int trace_event;
+ int in_range_stepping;
/* Translate generic target options into linux options. */
options = __WALL;
@@ -2322,6 +2323,7 @@ linux_wait_1 (ptid_t ptid,
retry:
bp_explains_trap = 0;
trace_event = 0;
+ in_range_stepping = 0;
ourstatus->kind = TARGET_WAITKIND_IGNORE;
/* If we were only supposed to resume one thread, only wait for
@@ -2615,6 +2617,9 @@ Check if we're already there.\n",
goto retry;
}
+ in_range_stepping
+ = thread_in_range_stepping_p (current_inferior,
+ event_child->stop_pc);
/* If GDB wanted this thread to single step, we always want to
report the SIGTRAP, and let GDB handle it. Watchpoints should
always be reported. So should signals we can't explain. A
@@ -2624,9 +2629,12 @@ Check if we're already there.\n",
internal breakpoint and still reporting the event to GDB. If we
don't, we're out of luck, GDB won't see the breakpoint hit. */
report_to_gdb = (!maybe_internal_trap
- || current_inferior->last_resume_kind == resume_step
+ /* Report the event back to GDB if the inferior is
+ stepping and not in range stepping. */
+ || (current_inferior->last_resume_kind == resume_step
+ && !in_range_stepping)
|| event_child->stopped_by_watchpoint
- || (!step_over_finished
+ || (!step_over_finished && !in_range_stepping
&& !bp_explains_trap && !trace_event)
|| (gdb_breakpoint_here (event_child->stop_pc)
&& gdb_condition_true_at_breakpoint (event_child->stop_pc)
@@ -2647,6 +2655,12 @@ Check if we're already there.\n",
fprintf (stderr, "Step-over finished.\n");
if (trace_event)
fprintf (stderr, "Tracepoint event.\n");
+ if (thread_in_range_stepping_p (current_inferior,
+ event_child->stop_pc))
+ fprintf (stderr, "Range stepping pc 0x%s [0x%s, 0x%s).\n",
+ paddress (event_child->stop_pc),
+ paddress (current_inferior->start),
+ paddress (current_inferior->end));
}
/* We're not reporting this breakpoint to GDB, so apply the
@@ -2678,7 +2692,13 @@ Check if we're already there.\n",
if (debug_threads)
{
if (current_inferior->last_resume_kind == resume_step)
- fprintf (stderr, "GDB wanted to single-step, reporting event.\n");
+ {
+ if (!thread_in_range_stepping_p (current_inferior,
+ event_child->stop_pc))
+ fprintf (stderr, "Range stepping is done, reporting event.\n");
+ else
+ fprintf (stderr, "GDB wanted to single-step, reporting event.\n");
+ }
if (event_child->stopped_by_watchpoint)
fprintf (stderr, "Stopped by watchpoint.\n");
if (gdb_breakpoint_here (event_child->stop_pc))
@@ -2687,6 +2707,8 @@ Check if we're already there.\n",
fprintf (stderr, "Hit a non-gdbserver trap event.\n");
}
+ thread_clear_range_stepping (current_inferior);
+
/* Alright, we're going to report a stop. */
if (!non_stop && !stabilizing_threads)
@@ -5083,6 +5105,15 @@ linux_supports_agent (void)
return 1;
}
+static int
+linux_supports_range_stepping (void)
+{
+ if (*the_low_target.supports_range_stepping == NULL)
+ return 0;
+
+ return (*the_low_target.supports_range_stepping) ();
+}
+
/* Enumerate spufs IDs for process PID. */
static int
spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len)
@@ -5939,6 +5970,7 @@ static struct target_ops linux_target_ops = {
NULL,
NULL,
#endif
+ linux_supports_range_stepping,
};
static void
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index 27dd3b5..5d3e8cf 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -168,6 +168,8 @@ struct linux_target_ops
for use as a fast tracepoint. */
int (*get_min_fast_tracepoint_insn_len) (void);
+ /* Returns true if the low target supports range stepping. */
+ int (*supports_range_stepping) (void);
};
extern struct linux_target_ops the_low_target;
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 31657d3..1d1df95 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -3175,6 +3175,12 @@ x86_emit_ops (void)
return &i386_emit_ops;
}
+static int
+x86_supports_range_stepping (void)
+{
+ return 1;
+}
+
/* This is initialized assuming an amd64 target.
x86_arch_setup will correct it for i386 or amd64 targets. */
@@ -3214,4 +3220,5 @@ struct linux_target_ops the_low_target =
x86_install_fast_tracepoint_jump_pad,
x86_emit_ops,
x86_get_min_fast_tracepoint_insn_len,
+ x86_supports_range_stepping,
};
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 6bb36d8..aa4ddf6 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -2040,10 +2040,15 @@ handle_v_cont (char *own_buf)
p = &own_buf[5];
while (*p)
{
+ CORE_ADDR start = 0;
+ CORE_ADDR end = 0;
+
p++;
if (p[0] == 's' || p[0] == 'S')
resume_info[i].kind = resume_step;
+ else if (p[0] == 'r')
+ resume_info[i].kind = resume_step;
else if (p[0] == 'c' || p[0] == 'C')
resume_info[i].kind = resume_continue;
else if (p[0] == 't')
@@ -2063,6 +2068,21 @@ handle_v_cont (char *own_buf)
goto err;
resume_info[i].sig = gdb_signal_to_host (sig);
}
+ else if (p[0] == 'r')
+ {
+ char *p1;
+
+ p = p + 1;
+ p1 = strchr (p, ',');
+ decode_address (&start, p, p1 - p);
+
+ p = p1 + 1;
+ p1 = strchr (p, ':');
+ decode_address (&end, p, p1 - p);
+
+ resume_info[i].sig = 0;
+ p = p1;
+ }
else
{
resume_info[i].sig = 0;
@@ -2088,6 +2108,21 @@ handle_v_cont (char *own_buf)
goto err;
resume_info[i].thread = ptid;
+ if (end > 0)
+ {
+ struct thread_info *tp = find_thread_ptid (ptid);
+
+ /* GDB should not send range stepping for all threads of
+ a process, like 'vCont;rSTART,END:pPID.-1', TP can't
+ be NULL. */
+ gdb_assert (tp != NULL);
+
+ tp->start = start;
+ tp->end = end;
+
+ start = 0;
+ end = 0;
+ }
i++;
}
@@ -2311,6 +2346,11 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
if (strncmp (own_buf, "vCont?", 6) == 0)
{
strcpy (own_buf, "vCont;c;C;s;S;t");
+ if (target_supports_range_stepping ())
+ {
+ own_buf = own_buf + strlen (own_buf);
+ strcpy (own_buf, ";r");
+ }
return;
}
}
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index f257459..8c0790e 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -414,6 +414,8 @@ struct target_ops
to break a cyclic dependency. */
void (*read_btrace) (struct btrace_target_info *, struct buffer *, int type);
+ /* Return true if target supports range stepping. */
+ int (*supports_range_stepping) (void);
};
extern struct target_ops *the_target;
@@ -549,6 +551,10 @@ int kill_inferior (int);
#define target_read_btrace(tinfo, buffer, type) \
(*the_target->read_btrace) (tinfo, buffer, type)
+#define target_supports_range_stepping() \
+ (the_target->supports_range_stepping ? \
+ (*the_target->supports_range_stepping) () : 0)
+
/* Start non-stop mode, returns 0 on success, -1 on failure. */
int start_non_stop (int nonstop);
--
1.7.7.6
next prev parent reply other threads:[~2013-04-11 2:43 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-11 12:52 [PATCH 0/7] Range stepping Yao Qi
2013-03-11 12:53 ` [PATCH 3/7] range stepping: gdbserver on x86/linux Yao Qi
2013-05-14 18:30 ` Pedro Alves
2013-05-15 7:40 ` Yao Qi
2013-05-20 18:00 ` Pedro Alves
2013-05-22 10:06 ` Yao Qi
2013-03-11 12:53 ` [PATCH 2/7] Move rs->support_vCont_t to a separate struct Yao Qi
2013-03-11 12:53 ` [PATCH 7/7] range stepping: doc and NEWS Yao Qi
2013-03-11 13:38 ` Abid, Hafiz
2013-03-11 17:01 ` Eli Zaretskii
2013-05-14 18:32 ` Pedro Alves
2013-03-11 12:53 ` [PATCH 1/7] New macro THREAD_WITHIN_SINGLE_STEP_RANGE Yao Qi
2013-05-14 19:24 ` Pedro Alves
2013-03-11 12:53 ` [PATCH 4/7] range stepping: gdb Yao Qi
2013-05-14 18:31 ` Pedro Alves
2013-05-15 8:07 ` Yao Qi
2013-05-20 17:59 ` Pedro Alves
2013-03-11 12:53 ` [PATCH 6/7] range stepping: test case Yao Qi
2013-05-14 18:32 ` Pedro Alves
2013-05-15 8:27 ` Yao Qi
2013-05-20 18:29 ` Pedro Alves
2013-05-22 14:01 ` Yao Qi
2013-03-11 12:53 ` [PATCH 5/7] range stepping: New command 'maint set range stepping' Yao Qi
2013-03-11 17:05 ` Eli Zaretskii
2013-03-18 3:10 ` Yao Qi
2013-03-18 5:39 ` Eli Zaretskii
2013-05-14 18:31 ` Pedro Alves
2013-03-14 20:12 ` [PATCH 0/7] Range stepping Pedro Alves
2013-03-15 19:54 ` Pedro Alves
2013-03-22 2:25 ` Yao Qi
2013-03-22 20:24 ` Pedro Alves
2013-04-11 6:16 ` [PATCH 0/7 V2] " Yao Qi
2013-04-11 6:17 ` [PATCH 1/7] New macro THREAD_WITHIN_SINGLE_STEP_RANGE Yao Qi
2013-04-11 6:17 ` [PATCH 2/7] Move rs->support_vCont_t to a separate struct Yao Qi
2013-04-11 6:18 ` Yao Qi [this message]
2013-04-11 6:19 ` [PATCH 5/7] range stepping: New command 'maint set range stepping' Yao Qi
2013-04-11 23:00 ` Eli Zaretskii
2013-04-11 6:19 ` [PATCH 4/7] range stepping: gdb Yao Qi
2013-04-11 13:22 ` Yao Qi
2013-04-12 12:35 ` Yao Qi
2013-04-11 6:38 ` [PATCH 6/7] range stepping: test case Yao Qi
2013-04-11 7:30 ` [PATCH 7/7] range stepping: doc and NEWS Yao Qi
2013-04-11 23:00 ` Eli Zaretskii
2013-04-12 20:48 ` [PATCH 0/7 V2] Range stepping Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1365648222-12540-4-git-send-email-yao@codesourcery.com \
--to=yao@codesourcery.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox