* [PATCH 0/2] [GDBserver] Fix compiling conditional expressions accessing registers @ 2015-09-11 17:25 Pierre Langlois 2015-09-11 17:25 ` [PATCH 1/2] " Pierre Langlois 2015-09-11 17:25 ` [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions Pierre Langlois 0 siblings, 2 replies; 9+ messages in thread From: Pierre Langlois @ 2015-09-11 17:25 UTC (permalink / raw) To: gdb-patches; +Cc: Pierre Langlois Hi all, I noticed compiled conditions for fast tracepoints failed to read registers. We can uncover the issue by compiling and executing the following expression: `$rip == *set_point' on x86_64, with `set_point' being the tracepoint symbol. The expression should always be true but this shows it isn't: ~~~ (gdb) ftrace set_point if $rip == *set_point Fast tracepoint 2 at 0x4006b9: ... (gdb) tstart (gdb) continue Continuing. Breakpoint 3, end () at .. (gdb) tstatus Trace is running on the target. Collected 0 trace frames. ^^^^^^^^^^^^^^^^^^^^^^^^^ Trace buffer has 5242880 bytes of 5242880 bytes free (0% full). Trace will stop if GDB disconnects. Not looking at any trace frame. Trace started at 1441727485.544642 secs. ~~~ The following patches address this particular issue and adds a test case. However, the test cases uncovered other issues which have been marked as known failures, linking to PR/18955. I have ran the test suite on both x86_64-linux and i386-linux, in a remote configuration. Thanks, Pierre Pierre Langlois (2): [GDBserver] Fix compiling conditional expressions accessing registers [testsuite] Add test case for tracepoints with conditions gdb/gdbserver/linux-amd64-ipa.c | 9 -- gdb/gdbserver/linux-i386-ipa.c | 15 --- gdb/gdbserver/linux-x86-low.c | 4 +- gdb/gdbserver/tracepoint.c | 42 ++++--- gdb/gdbserver/tracepoint.h | 9 +- gdb/testsuite/gdb.trace/trace-condition.c | 66 +++++++++++ gdb/testsuite/gdb.trace/trace-condition.exp | 167 ++++++++++++++++++++++++++++ 7 files changed, 263 insertions(+), 49 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/trace-condition.c create mode 100644 gdb/testsuite/gdb.trace/trace-condition.exp -- 2.4.6 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] [GDBserver] Fix compiling conditional expressions accessing registers 2015-09-11 17:25 [PATCH 0/2] [GDBserver] Fix compiling conditional expressions accessing registers Pierre Langlois @ 2015-09-11 17:25 ` Pierre Langlois 2015-09-16 9:15 ` Yao Qi 2015-09-11 17:25 ` [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions Pierre Langlois 1 sibling, 1 reply; 9+ messages in thread From: Pierre Langlois @ 2015-09-11 17:25 UTC (permalink / raw) To: gdb-patches; +Cc: Pierre Langlois In order to compile conditions on fast tracepoints, we need to emit code to read registers. This is done with the `reg' opcode, and when generating native code for it we emit a call to `gdb_agent_get_raw_reg', which is a shared symbol between GDBserver and the IPA. However, compiled conditions accessing registers do not work at the moment. For example, while debugging the ftrace test case on x86_64 using GDBserver: ~~~ (gdb) ftrace set_point if $rip == *set_point Fast tracepoint 2 at 0x4006b9: ... (gdb) tstart (gdb) continue Continuing. Breakpoint 3, end () at .. (gdb) tstatus Trace is running on the target. Collected 0 trace frames. Trace buffer has 5242880 bytes of 5242880 bytes free (0% full). Trace will stop if GDB disconnects. Not looking at any trace frame. Trace started at 1441727485.544642 secs. ~~~ The condition on the tracepoint should always evaluate to TRUE, $rip being the program counter. It turns out there is an error when emitting a function call to `gdb_agent_get_raw_reg'. The call emitted by `amd64_emit_reg' should pass a pointer to the raw registers saved on the stack as a first argument, but instead it passes the fast tracepoint context object (`struct fast_tracepoint_ctx *'). As a result, `gdb_agent_get_raw_reg' always returns the wrong values. We can see this by setting a breakpoint on both `condition_true_at_tracepoint' and `gdb_agent_get_raw_reg'. We can see the pointer being passed to the latter is the context: ~~~ (gdb) ftrace set_point if $rip == *set_point Fast tracepoint 2 at 0x4006b9: ... (gdb) b condition_true_at_tracepoint Breakpoint 4 at ... (gdb) b gdb_agent_get_raw_reg Breakpoint 5 at ... (gdb) tstart (gdb) continue Continuing. Breakpoint 4, condition_true_at_tracepoint (ctx=0x7fffffffc038, ^^^^^^^^^^^^^^ tpoint=0x7ffff68e2010) at ... (gdb) continue Breakpoint 5, gdb_agent_get_raw_reg (raw_regs=0x7fffffffc038 "\001", ^^^^^^^^^^^^^^ regnum=16) at ... (gdb) ~~~ This patch fixes this issue by replacing `gdb_agent_get_raw_reg' with a `gdb_agent_get_reg' function which takes the tracepoint context object as argument instead of a raw buffer. Additionally, this patch makes this function architecture independent by initializing the context's regcache early and making `gdb_agent_get_reg' use `collect_register'. As a result, the fast tracepoint context object does not need to contain the raw register buffer. gdb/gdbserver/ChangeLog: * linux-amd64-ipa.c (gdb_agent_get_raw_reg): Remove. * linux-i386-ipa.c (gdb_agent_get_raw_reg): Remove. * linux-x86-low.c (amd64_emit_reg): Call get_reg_func_addr instead of get_raw_reg_func_addr. (i386_emit_reg): Likewise. * tracepoint.c (get_raw_reg): Rename to ... (get_reg): ... this. (struct ipa_sym_addresses) <addr_get_raw_reg>: Rename to ... (struct ipa_sym_addresses) <add_get_reg>: ... this. (symbol_list): Rename get_raw_reg to get_reg. (struct fast_tracepoint_ctx) <regcache_initted>, <regs>: Remove. (get_context_regcache): Do not initialize fctx->regcache. (gdb_collect): Remove ctx.regs and ctx.regcache_initted. Initialize ctx.regcache. (gdb_agent_get_reg): New exported function. (get_raw_reg_func_addr): Rename to ... (get_reg_func_addr): ... this. * tracepoint.h (gdb_agent_get_raw_reg): Remove. (get_raw_reg_func_addr): Rename to ... (get_reg_func_addr): ... this. --- gdb/gdbserver/linux-amd64-ipa.c | 9 --------- gdb/gdbserver/linux-i386-ipa.c | 15 --------------- gdb/gdbserver/linux-x86-low.c | 4 ++-- gdb/gdbserver/tracepoint.c | 42 +++++++++++++++++++++++++---------------- gdb/gdbserver/tracepoint.h | 9 ++------- 5 files changed, 30 insertions(+), 49 deletions(-) diff --git a/gdb/gdbserver/linux-amd64-ipa.c b/gdb/gdbserver/linux-amd64-ipa.c index a6dfb03..78125d7 100644 --- a/gdb/gdbserver/linux-amd64-ipa.c +++ b/gdb/gdbserver/linux-amd64-ipa.c @@ -68,15 +68,6 @@ supply_fast_tracepoint_registers (struct regcache *regcache, ((char *) buf) + x86_64_ft_collect_regmap[i]); } -IP_AGENT_EXPORT_FUNC ULONGEST -gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum) -{ - if (regnum >= X86_64_NUM_FT_COLLECT_GREGS) - return 0; - - return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]); -} - #ifdef HAVE_UST #include <ust/processor.h> diff --git a/gdb/gdbserver/linux-i386-ipa.c b/gdb/gdbserver/linux-i386-ipa.c index de8d394..6be87ad 100644 --- a/gdb/gdbserver/linux-i386-ipa.c +++ b/gdb/gdbserver/linux-i386-ipa.c @@ -98,21 +98,6 @@ supply_fast_tracepoint_registers (struct regcache *regcache, } } -IP_AGENT_EXPORT_FUNC ULONGEST -gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum) -{ - /* This should maybe be allowed to return an error code, or perhaps - better, have the emit_reg detect this, and emit a constant zero, - or something. */ - - if (regnum > i386_num_regs) - return 0; - else if (regnum >= I386_CS_REGNUM && regnum <= I386_GS_REGNUM) - return *(short *) (raw_regs + i386_ft_collect_regmap[regnum]); - else - return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]); -} - #ifdef HAVE_UST #include <ust/processor.h> diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 20d4257..3fb447d 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -2287,7 +2287,7 @@ amd64_emit_reg (int reg) i += 4; append_insns (&buildaddr, i, buf); current_insn_ptr = buildaddr; - amd64_emit_call (get_raw_reg_func_addr ()); + amd64_emit_call (get_reg_func_addr ()); } static void @@ -2896,7 +2896,7 @@ i386_emit_reg (int reg) "mov %eax,4(%esp)\n\t" "mov 8(%ebp),%eax\n\t" "mov %eax,(%esp)"); - i386_emit_call (get_raw_reg_func_addr ()); + i386_emit_call (get_reg_func_addr ()); EMIT_ASM32 (i386_reg_c, "xor %ebx,%ebx\n\t" "lea 0x8(%esp),%esp"); diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index fd010ae..113848c 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -126,7 +126,7 @@ trace_vdebug (const char *fmt, ...) # define traceframe_write_count IPA_SYM_EXPORTED_NAME (traceframe_write_count) # define traceframes_created IPA_SYM_EXPORTED_NAME (traceframes_created) # define trace_state_variables IPA_SYM_EXPORTED_NAME (trace_state_variables) -# define get_raw_reg IPA_SYM_EXPORTED_NAME (get_raw_reg) +# define get_reg IPA_SYM_EXPORTED_NAME (get_reg) # define get_trace_state_variable_value \ IPA_SYM_EXPORTED_NAME (get_trace_state_variable_value) # define set_trace_state_variable_value \ @@ -167,7 +167,7 @@ struct ipa_sym_addresses CORE_ADDR addr_traceframe_write_count; CORE_ADDR addr_traceframes_created; CORE_ADDR addr_trace_state_variables; - CORE_ADDR addr_get_raw_reg; + CORE_ADDR addr_get_reg; CORE_ADDR addr_get_trace_state_variable_value; CORE_ADDR addr_set_trace_state_variable_value; CORE_ADDR addr_ust_loaded; @@ -203,7 +203,7 @@ static struct IPA_SYM(traceframe_write_count), IPA_SYM(traceframes_created), IPA_SYM(trace_state_variables), - IPA_SYM(get_raw_reg), + IPA_SYM(get_reg), IPA_SYM(get_trace_state_variable_value), IPA_SYM(set_trace_state_variable_value), IPA_SYM(ust_loaded), @@ -1306,10 +1306,8 @@ struct fast_tracepoint_ctx struct tracepoint_hit_ctx base; struct regcache regcache; - int regcache_initted; unsigned char *regspace; - unsigned char *regs; struct tracepoint *tpoint; }; @@ -4724,13 +4722,6 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx) if (ctx->type == fast_tracepoint) { struct fast_tracepoint_ctx *fctx = (struct fast_tracepoint_ctx *) ctx; - if (!fctx->regcache_initted) - { - fctx->regcache_initted = 1; - init_register_cache (&fctx->regcache, ipa_tdesc, fctx->regspace); - supply_regblock (&fctx->regcache, NULL); - supply_fast_tracepoint_registers (&fctx->regcache, fctx->regs); - } regcache = &fctx->regcache; } #ifdef HAVE_UST @@ -5796,11 +5787,16 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) return; ctx.base.type = fast_tracepoint; - ctx.regs = regs; - ctx.regcache_initted = 0; /* Wrap the regblock in a register cache (in the stack, we don't want to malloc here). */ ctx.regspace = alloca (ipa_tdesc->registers_size); + + /* Initialize the regcache with registers from the stack set up by jump + pad. */ + init_register_cache (&ctx.regcache, ipa_tdesc, ctx.regspace); + supply_regblock (&ctx.regcache, NULL); + supply_fast_tracepoint_registers (&ctx.regcache, regs); + if (ctx.regspace == NULL) { trace_debug ("Trace buffer block allocation failed, skipping"); @@ -5853,14 +5849,28 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) } } +/* This function is called from native code generated for the emit_reg + agent expression bytecode. It returns the value of register number + REGNUM read from regcache contained into CTX. */ + +IP_AGENT_EXPORT_FUNC ULONGEST +gdb_agent_get_reg (struct fast_tracepoint_ctx *ctx, int regnum) +{ + ULONGEST reg; + + collect_register (&ctx->regcache, regnum, ®); + + return reg; +} + #endif #ifndef IN_PROCESS_AGENT CORE_ADDR -get_raw_reg_func_addr (void) +get_reg_func_addr (void) { - return ipa_sym_addrs.addr_get_raw_reg; + return ipa_sym_addrs.addr_get_reg; } CORE_ADDR diff --git a/gdb/gdbserver/tracepoint.h b/gdb/gdbserver/tracepoint.h index 30d0b58..3a96487 100644 --- a/gdb/gdbserver/tracepoint.h +++ b/gdb/gdbserver/tracepoint.h @@ -163,13 +163,8 @@ int agent_mem_read_string (struct eval_agent_expr_context *ctx, CORE_ADDR from, ULONGEST len); -/* The prototype the get_raw_reg function in the IPA. Each arch's - bytecode compiler emits calls to this function. */ -IP_AGENT_EXPORT_FUNC ULONGEST gdb_agent_get_raw_reg - (const unsigned char *raw_regs, int regnum); - -/* Returns the address of the get_raw_reg function in the IPA. */ -CORE_ADDR get_raw_reg_func_addr (void); +/* Returns the address of the get_reg function in the IPA. */ +CORE_ADDR get_reg_func_addr (void); /* Returns the address of the get_trace_state_variable_value function in the IPA. */ CORE_ADDR get_get_tsv_func_addr (void); -- 2.4.6 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] [GDBserver] Fix compiling conditional expressions accessing registers 2015-09-11 17:25 ` [PATCH 1/2] " Pierre Langlois @ 2015-09-16 9:15 ` Yao Qi 2015-09-16 11:50 ` Ulrich Weigand 0 siblings, 1 reply; 9+ messages in thread From: Yao Qi @ 2015-09-16 9:15 UTC (permalink / raw) To: Pierre Langlois; +Cc: gdb-patches, uweigand, cole945 Pierre Langlois <pierre.langlois@arm.com> writes: > This patch fixes this issue by replacing `gdb_agent_get_raw_reg' with a > `gdb_agent_get_reg' function which takes the tracepoint context object > as argument instead of a raw buffer. Additionally, this patch makes > this function architecture independent by initializing the context's > regcache early and making `gdb_agent_get_reg' use `collect_register'. > As a result, the fast tracepoint context object does not need to > contain the raw register buffer. The fix looks reasonable to me as it makes no sense to keep two copies of registers. I go through this patch, and it looks good to me. This patch invalidates Wei-cheng's patch here <https://sourceware.org/ml/gdb-patches/2015-06/msg00587.html> which is already approved but not committed. If Ulirch/Wei-cheng have no objections, this patch can go in. -- Yao (齐尧) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] [GDBserver] Fix compiling conditional expressions accessing registers 2015-09-16 9:15 ` Yao Qi @ 2015-09-16 11:50 ` Ulrich Weigand 2015-09-16 13:54 ` Pedro Alves 0 siblings, 1 reply; 9+ messages in thread From: Ulrich Weigand @ 2015-09-16 11:50 UTC (permalink / raw) To: Yao Qi; +Cc: Pierre Langlois, gdb-patches, cole945 Yao Qi wrote: > Pierre Langlois <pierre.langlois@arm.com> writes: > > > This patch fixes this issue by replacing `gdb_agent_get_raw_reg' with a > > `gdb_agent_get_reg' function which takes the tracepoint context object > > as argument instead of a raw buffer. Additionally, this patch makes > > this function architecture independent by initializing the context's > > regcache early and making `gdb_agent_get_reg' use `collect_register'. > > As a result, the fast tracepoint context object does not need to > > contain the raw register buffer. > > The fix looks reasonable to me as it makes no sense to keep two copies > of registers. I go through this patch, and it looks good to me. It seems to me this was intended as performance optimization to avoid having to do the full regcache setup every time a tracepoint is hit, in case we're not actually tracing registers ... Not sure whether this is a real performance concern for actual use cases though. I don't have any actual measurements ... > This patch invalidates Wei-cheng's patch here > <https://sourceware.org/ml/gdb-patches/2015-06/msg00587.html> which is > already approved but not committed. > > If Ulirch/Wei-cheng have no objections, this patch can go in. Except for the performance question above, I have no objections. Bye, Ulrich -- Dr. Ulrich Weigand GNU/Linux compilers and toolchain Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] [GDBserver] Fix compiling conditional expressions accessing registers 2015-09-16 11:50 ` Ulrich Weigand @ 2015-09-16 13:54 ` Pedro Alves 2015-09-16 15:03 ` Yao Qi 0 siblings, 1 reply; 9+ messages in thread From: Pedro Alves @ 2015-09-16 13:54 UTC (permalink / raw) To: Ulrich Weigand, Yao Qi; +Cc: Pierre Langlois, gdb-patches, cole945 On 09/16/2015 12:50 PM, Ulrich Weigand wrote: > Yao Qi wrote: >> Pierre Langlois <pierre.langlois@arm.com> writes: >> >>> This patch fixes this issue by replacing `gdb_agent_get_raw_reg' with a >>> `gdb_agent_get_reg' function which takes the tracepoint context object >>> as argument instead of a raw buffer. Additionally, this patch makes >>> this function architecture independent by initializing the context's >>> regcache early and making `gdb_agent_get_reg' use `collect_register'. >>> As a result, the fast tracepoint context object does not need to >>> contain the raw register buffer. >> >> The fix looks reasonable to me as it makes no sense to keep two copies >> of registers. I go through this patch, and it looks good to me. > > It seems to me this was intended as performance optimization to avoid > having to do the full regcache setup every time a tracepoint is hit, > in case we're not actually tracing registers ... > > Not sure whether this is a real performance concern for actual use > cases though. I don't have any actual measurements ... Yes, I was just now reading this, and was going to say the same. E.g., the original fast tracepoints code was tuned to avoid as much work as possible in the condition-fails scenario, when the condition only accesses a global. That is, e.g., "trace foo if debug_knob == 1". I no longer have the numbers captured at the time though. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] [GDBserver] Fix compiling conditional expressions accessing registers 2015-09-16 13:54 ` Pedro Alves @ 2015-09-16 15:03 ` Yao Qi 0 siblings, 0 replies; 9+ messages in thread From: Yao Qi @ 2015-09-16 15:03 UTC (permalink / raw) To: Pedro Alves; +Cc: Ulrich Weigand, Yao Qi, Pierre Langlois, gdb-patches, cole945 Pedro Alves <palves@redhat.com> writes: >> Not sure whether this is a real performance concern for actual use >> cases though. I don't have any actual measurements ... > > Yes, I was just now reading this, and was going to say the same. > > E.g., the original fast tracepoints code was tuned to avoid as much > work as possible in the condition-fails scenario, when the condition > only accesses a global. That is, e.g., "trace foo if debug_knob == 1". > I no longer have the numbers captured at the time though. I run tspeed.exp, and it shows this patch slows down fast tracepoint from 29ns to 144ns, so we need to commit Wei-chang's patch <https://sourceware.org/ml/gdb-patches/2015-06/msg00587.html> instead. -- Yao (齐尧) ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions 2015-09-11 17:25 [PATCH 0/2] [GDBserver] Fix compiling conditional expressions accessing registers Pierre Langlois 2015-09-11 17:25 ` [PATCH 1/2] " Pierre Langlois @ 2015-09-11 17:25 ` Pierre Langlois 2015-09-16 9:19 ` Yao Qi 2015-09-17 8:51 ` Yao Qi 1 sibling, 2 replies; 9+ messages in thread From: Pierre Langlois @ 2015-09-11 17:25 UTC (permalink / raw) To: gdb-patches; +Cc: Pierre Langlois This patch adds a test case for tracepoints with a condition expression. Each case will test a condition against the number of frames that should have been traced. Some of these tests fail on x86_64 and others on i386, which have been marked as known failures for now, see PR/18955. gdb/testsuite/ChangeLog: * gdb.trace/trace-condition.c: New file. * gdb.trace/trace-condition.exp: New file. --- gdb/testsuite/gdb.trace/trace-condition.c | 66 +++++++++++ gdb/testsuite/gdb.trace/trace-condition.exp | 167 ++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 gdb/testsuite/gdb.trace/trace-condition.c create mode 100644 gdb/testsuite/gdb.trace/trace-condition.exp diff --git a/gdb/testsuite/gdb.trace/trace-condition.c b/gdb/testsuite/gdb.trace/trace-condition.c new file mode 100644 index 0000000..2e965c9 --- /dev/null +++ b/gdb/testsuite/gdb.trace/trace-condition.c @@ -0,0 +1,66 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2015 Free Software Foundation, Inc. + + 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/>. */ + +#ifdef SYMBOL_PREFIX +#define SYMBOL(str) SYMBOL_PREFIX #str +#else +#define SYMBOL(str) #str +#endif + +int globvar; + +static void +begin (void) +{ +} + +/* Called from asm. */ +static void __attribute__((used)) +func (void) +{ +} + +static void +marker (int anarg) +{ + /* `set_point' is the label at which to set a fast tracepoint. The + insn at the label must be large enough to fit a fast tracepoint + jump. */ + asm (" .global " SYMBOL (set_point) "\n" + SYMBOL (set_point) ":\n" +#if (defined __x86_64__ || defined __i386__) + " call " SYMBOL (func) "\n" +#endif + ); +} + +static void +end (void) +{ +} + +int +main () +{ + begin (); + + for (globvar = 1; globvar < 11; ++globvar) + marker (globvar * 100); + + end (); + return 0; +} diff --git a/gdb/testsuite/gdb.trace/trace-condition.exp b/gdb/testsuite/gdb.trace/trace-condition.exp new file mode 100644 index 0000000..8bfd34a --- /dev/null +++ b/gdb/testsuite/gdb.trace/trace-condition.exp @@ -0,0 +1,167 @@ +# Copyright 2011-2015 Free Software Foundation, Inc. +# 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/>. + +load_lib "trace-support.exp" + +standard_testfile +set executable $testfile +set expfile $testfile.exp + +# Some targets have leading underscores on assembly symbols. +set additional_flags [gdb_target_symbol_prefix_flags] + +if [is_amd64_regs_target] { + set pcreg "\$rip" +} elseif [is_x86_like_target] { + set pcreg "\$eip" +} else { + set pcreg "\$pc" +} + +if [prepare_for_testing $expfile $executable $srcfile \ + [list debug $additional_flags]] { + untested "failed to prepare for trace tests" + return -1 +} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "target does not support trace" + return -1 +} + +set libipa [get_in_proc_agent] +gdb_load_shlibs $libipa + +# Can't use prepare_for_testing, because that splits compiling into +# building objects and then linking, and we'd fail with "linker input +# file unused because linking not done" when building the object. + +if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ + executable [list debug $additional_flags shlib=$libipa] ] != "" } { + untested "failed to compile ftrace tests" + return -1 +} + +clean_restart ${executable} + +if ![runto_main] { + fail "Can't run to main for ftrace tests" + return 0 +} + +gdb_reinitialize_dir $srcdir/$subdir + +if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } { + untested "Could not find IPA lib loaded" + return 1 +} + +proc test_tracepoints { trace_command condition num_frames { kfail_proc 0 } } { + global executable + + clean_restart ${executable} + + if ![runto_main] { + fail "Can't run to main for ftrace tests" + return 0 + } + + gdb_test "break begin" ".*" "" + + gdb_test "break end" ".*" "" + + gdb_test "${trace_command} set_point if ${condition}" "\(Fast t|T\)racepoint .*" \ + "${trace_command} with condition $condition" + + gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, begin .*" \ + "advance to trace begin" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test_multiple "continue" "advance through tracing" { + -re ".*Breakpoint \[0-9\]+, end .*" { + pass "advance through tracing" + } + -re "Program received signal SIGSEGV, Segmentation fault\\..*" { + if { $kfail_proc != 0 } { + $kfail_proc $trace_command + } + fail "advance through tracing" + } + } + + if { $kfail_proc != 0 } { + $kfail_proc $trace_command + } + gdb_test "tstatus" \ + ".*Trace .*Collected $num_frames .*" \ + "check $num_frames frames were collected." + + gdb_test "tstop" "" "" +} + +# These callbacks identify known failures for certain architectures. They +# are called either if GDBserver crashes or has not traced the correct +# number of frames. + +proc 18955_x86_64_failure { trace_command } { + if { $trace_command == "ftrace" } { + setup_kfail "gdb/18955" "x86_64-*-linux*" + } +} + +proc 18955_i386_failure { trace_command } { + if { $trace_command == "ftrace" } { + setup_kfail "gdb/18955" "i\[34567\]86-*-*" + } +} + +foreach trace_command { "trace" "ftrace" } { + # This condition is always true as the PC should be set to the tracepoint + # address when hit. + test_tracepoints $trace_command "$pcreg == *set_point" 10 + + # Can we read local variables? + test_tracepoints $trace_command "anarg == 100 || anarg == 200" 2 18955_x86_64_failure + # Can we read global variables? + test_tracepoints $trace_command "anarg == 100 && globvar == 1" 1 18955_x86_64_failure + + # Test various operations to cover as many opcodes as possible. + test_tracepoints $trace_command "21 + 21 == 42" 10 + test_tracepoints $trace_command "21 - 21 == 0" 10 + test_tracepoints $trace_command "21 * 2 == 42" 10 + test_tracepoints $trace_command "21 << 1 == 42" 10 + test_tracepoints $trace_command "42 >> 1 == 21" 10 + test_tracepoints $trace_command "-21 << 1 == -42" 10 + test_tracepoints $trace_command "-42 >> 1 == -21" 10 + test_tracepoints $trace_command "(0xabababab & 0x0000ffff) == 0xabab" 10 + test_tracepoints $trace_command "(0xabababab | 0x0000ffff) == 0xababffff" 10 + test_tracepoints $trace_command "(0xaaaaaaaa ^ 0x55555555) == 0xffffffff" 10 + test_tracepoints $trace_command "~0xaaaaaaaa == 0x55555555" 10 + test_tracepoints $trace_command "21 < 42" 10 + test_tracepoints $trace_command "42 <= 42" 10 + test_tracepoints $trace_command "42 >= 42" 10 + test_tracepoints $trace_command "42 > 21" 10 + test_tracepoints $trace_command "(21 < 42 ? 0 : 1) == 0" 10 18955_i386_failure + test_tracepoints $trace_command "(42 <= 42 ? 0 : 1) == 0" 10 + test_tracepoints $trace_command "(42 >= 42 ? 0 : 1) == 0" 10 + test_tracepoints $trace_command "(42 > 21 ? 0 : 1) == 0" 10 18955_i386_failure + test_tracepoints $trace_command "\$trace_timestamp >= 0" 10 +} -- 2.4.6 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions 2015-09-11 17:25 ` [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions Pierre Langlois @ 2015-09-16 9:19 ` Yao Qi 2015-09-17 8:51 ` Yao Qi 1 sibling, 0 replies; 9+ messages in thread From: Yao Qi @ 2015-09-16 9:19 UTC (permalink / raw) To: Pierre Langlois; +Cc: gdb-patches Pierre Langlois <pierre.langlois@arm.com> writes: > +clean_restart ${executable} > + > +if ![runto_main] { > + fail "Can't run to main for ftrace tests" > + return 0 > +} > + > +gdb_reinitialize_dir $srcdir/$subdir Don't need gdb_reinitialize_dir, as clean_restart did that already. The patch is OK. -- Yao (齐尧) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions 2015-09-11 17:25 ` [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions Pierre Langlois 2015-09-16 9:19 ` Yao Qi @ 2015-09-17 8:51 ` Yao Qi 1 sibling, 0 replies; 9+ messages in thread From: Yao Qi @ 2015-09-17 8:51 UTC (permalink / raw) To: Pierre Langlois; +Cc: gdb-patches Pierre Langlois <pierre.langlois@arm.com> writes: [Pierre finished his 3-month rotation program on GDB and is assigned to some other project. I take over his patches today.] > +proc test_tracepoints { trace_command condition num_frames { kfail_proc 0 } } { > + global executable > + > + clean_restart ${executable} > + > + if ![runto_main] { > + fail "Can't run to main for ftrace tests" > + return 0 > + } > + > + gdb_test "break begin" ".*" "" > + > + gdb_test "break end" ".*" "" > + > + gdb_test "${trace_command} set_point if ${condition}" "\(Fast t|T\)racepoint .*" \ > + "${trace_command} with condition $condition" > + > + gdb_test "continue" \ > + ".*Breakpoint \[0-9\]+, begin .*" \ > + "advance to trace begin" This will generate duplicated test results entries in gdb.sum. We need to use with_test_prefix to avoid that. > + > + gdb_test_no_output "tstart" "start trace experiment" > + > + gdb_test_multiple "continue" "advance through tracing" { > + -re ".*Breakpoint \[0-9\]+, end .*" { > + pass "advance through tracing" > + } > + -re "Program received signal SIGSEGV, Segmentation fault\\..*" { > + if { $kfail_proc != 0 } { > + $kfail_proc $trace_command > + } > + fail "advance through tracing" > + } > + } This is racy, "$gdb_prompt $" is needed at the end of each pattern. Patch below fixes all of them, and I'll push it in. -- Yao (齐尧) From 5aa114981fab1c3b80fe0a23fe3eee21fb3c0c99 Mon Sep 17 00:00:00 2001 From: Pierre Langlois <pierre.langlois@arm.com> Date: Fri, 11 Sep 2015 18:25:01 +0100 Subject: [PATCH] Add test case for tracepoints with conditions This patch adds a test case for tracepoints with a condition expression. Each case will test a condition against the number of frames that should have been traced. Some of these tests fail on x86_64 and others on i386, which have been marked as known failures for now, see PR/18955. gdb/testsuite/ChangeLog: 2015-09-17 Pierre Langlois <pierre.langlois@arm.com> Yao Qi <yao.qi@linaro.org> * gdb.trace/trace-condition.c: New file. * gdb.trace/trace-condition.exp: New file. --- gdb/testsuite/gdb.trace/trace-condition.c | 66 +++++++++++ gdb/testsuite/gdb.trace/trace-condition.exp | 168 ++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 gdb/testsuite/gdb.trace/trace-condition.c create mode 100644 gdb/testsuite/gdb.trace/trace-condition.exp diff --git a/gdb/testsuite/gdb.trace/trace-condition.c b/gdb/testsuite/gdb.trace/trace-condition.c new file mode 100644 index 0000000..2e965c9 --- /dev/null +++ b/gdb/testsuite/gdb.trace/trace-condition.c @@ -0,0 +1,66 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2015 Free Software Foundation, Inc. + + 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/>. */ + +#ifdef SYMBOL_PREFIX +#define SYMBOL(str) SYMBOL_PREFIX #str +#else +#define SYMBOL(str) #str +#endif + +int globvar; + +static void +begin (void) +{ +} + +/* Called from asm. */ +static void __attribute__((used)) +func (void) +{ +} + +static void +marker (int anarg) +{ + /* `set_point' is the label at which to set a fast tracepoint. The + insn at the label must be large enough to fit a fast tracepoint + jump. */ + asm (" .global " SYMBOL (set_point) "\n" + SYMBOL (set_point) ":\n" +#if (defined __x86_64__ || defined __i386__) + " call " SYMBOL (func) "\n" +#endif + ); +} + +static void +end (void) +{ +} + +int +main () +{ + begin (); + + for (globvar = 1; globvar < 11; ++globvar) + marker (globvar * 100); + + end (); + return 0; +} diff --git a/gdb/testsuite/gdb.trace/trace-condition.exp b/gdb/testsuite/gdb.trace/trace-condition.exp new file mode 100644 index 0000000..d10fa9a --- /dev/null +++ b/gdb/testsuite/gdb.trace/trace-condition.exp @@ -0,0 +1,168 @@ +# Copyright 2011-2015 Free Software Foundation, Inc. +# 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/>. + +load_lib "trace-support.exp" + +standard_testfile +set executable $testfile +set expfile $testfile.exp + +# Some targets have leading underscores on assembly symbols. +set additional_flags [gdb_target_symbol_prefix_flags] + +if [is_amd64_regs_target] { + set pcreg "\$rip" +} elseif [is_x86_like_target] { + set pcreg "\$eip" +} else { + set pcreg "\$pc" +} + +if [prepare_for_testing $expfile $executable $srcfile \ + [list debug $additional_flags]] { + untested "failed to prepare for trace tests" + return -1 +} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "target does not support trace" + return -1 +} + +set libipa [get_in_proc_agent] +gdb_load_shlibs $libipa + +# Can't use prepare_for_testing, because that splits compiling into +# building objects and then linking, and we'd fail with "linker input +# file unused because linking not done" when building the object. + +if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ + executable [list debug $additional_flags shlib=$libipa] ] != "" } { + untested "failed to compile ftrace tests" + return -1 +} + +clean_restart ${executable} + +if ![runto_main] { + fail "Can't run to main for ftrace tests" + return 0 +} + +if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } { + untested "Could not find IPA lib loaded" + return 1 +} + +proc test_tracepoints { trace_command condition num_frames { kfail_proc 0 } } { + global executable gdb_prompt + + clean_restart ${executable} + + if ![runto_main] { + fail "Can't run to main for ftrace tests" + return 0 + } + + gdb_test "break begin" ".*" "" + + gdb_test "break end" ".*" "" + + with_test_prefix "${trace_command}: ${condition}" { + + gdb_test "${trace_command} set_point if ${condition}" \ + "\(Fast t|T\)racepoint .*" \ + "set tracepoint" + + gdb_test "continue" ".*Breakpoint \[0-9\]+, begin .*" \ + "advance to trace begin" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test_multiple "continue" "advance through tracing" { + -re ".*Breakpoint \[0-9\]+, end .*$gdb_prompt $" { + pass "advance through tracing" + } + -re "Program received signal SIGSEGV, Segmentation fault\\..*$gdb_prompt $" { + if { $kfail_proc != 0 } { + $kfail_proc $trace_command + } + fail "advance through tracing" + } + } + + if { $kfail_proc != 0 } { + $kfail_proc $trace_command + } + gdb_test "tstatus" \ + ".*Trace .*Collected $num_frames .*" \ + "check $num_frames frames were collected." + + gdb_test "tstop" "" "" + } +} + +# These callbacks identify known failures for certain architectures. They +# are called either if GDBserver crashes or has not traced the correct +# number of frames. + +proc 18955_x86_64_failure { trace_command } { + if { $trace_command == "ftrace" } { + setup_kfail "gdb/18955" "x86_64-*-linux*" + } +} + +proc 18955_i386_failure { trace_command } { + if { $trace_command == "ftrace" } { + setup_kfail "gdb/18955" "i\[34567\]86-*-*" + } +} + +foreach trace_command { "trace" "ftrace" } { + # This condition is always true as the PC should be set to the tracepoint + # address when hit. + test_tracepoints $trace_command "$pcreg == *set_point" 10 + + # Can we read local variables? + test_tracepoints $trace_command "anarg == 100 || anarg == 200" 2 18955_x86_64_failure + # Can we read global variables? + test_tracepoints $trace_command "anarg == 100 && globvar == 1" 1 18955_x86_64_failure + + # Test various operations to cover as many opcodes as possible. + test_tracepoints $trace_command "21 + 21 == 42" 10 + test_tracepoints $trace_command "21 - 21 == 0" 10 + test_tracepoints $trace_command "21 * 2 == 42" 10 + test_tracepoints $trace_command "21 << 1 == 42" 10 + test_tracepoints $trace_command "42 >> 1 == 21" 10 + test_tracepoints $trace_command "-21 << 1 == -42" 10 + test_tracepoints $trace_command "-42 >> 1 == -21" 10 + test_tracepoints $trace_command "(0xabababab & 0x0000ffff) == 0xabab" 10 + test_tracepoints $trace_command "(0xabababab | 0x0000ffff) == 0xababffff" 10 + test_tracepoints $trace_command "(0xaaaaaaaa ^ 0x55555555) == 0xffffffff" 10 + test_tracepoints $trace_command "~0xaaaaaaaa == 0x55555555" 10 + test_tracepoints $trace_command "21 < 42" 10 + test_tracepoints $trace_command "42 <= 42" 10 + test_tracepoints $trace_command "42 >= 42" 10 + test_tracepoints $trace_command "42 > 21" 10 + test_tracepoints $trace_command "(21 < 42 ? 0 : 1) == 0" 10 18955_i386_failure + test_tracepoints $trace_command "(42 <= 42 ? 0 : 1) == 0" 10 + test_tracepoints $trace_command "(42 >= 42 ? 0 : 1) == 0" 10 + test_tracepoints $trace_command "(42 > 21 ? 0 : 1) == 0" 10 18955_i386_failure + test_tracepoints $trace_command "\$trace_timestamp >= 0" 10 +} -- 1.9.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-09-17 8:51 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-09-11 17:25 [PATCH 0/2] [GDBserver] Fix compiling conditional expressions accessing registers Pierre Langlois 2015-09-11 17:25 ` [PATCH 1/2] " Pierre Langlois 2015-09-16 9:15 ` Yao Qi 2015-09-16 11:50 ` Ulrich Weigand 2015-09-16 13:54 ` Pedro Alves 2015-09-16 15:03 ` Yao Qi 2015-09-11 17:25 ` [PATCH 2/2] [testsuite] Add test case for tracepoints with conditions Pierre Langlois 2015-09-16 9:19 ` Yao Qi 2015-09-17 8:51 ` Yao Qi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox