From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 125148 invoked by alias); 11 Sep 2015 17:25:12 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 125115 invoked by uid 89); 11 Sep 2015 17:25:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,SPF_PASS autolearn=no version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (146.101.78.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 Sep 2015 17:25:09 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-31-7d0Gj-KNQLandgrLzTF7_g-3; Fri, 11 Sep 2015 18:25:04 +0100 Received: from e105615-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Fri, 11 Sep 2015 18:25:03 +0100 From: Pierre Langlois To: gdb-patches@sourceware.org Cc: Pierre Langlois Subject: [PATCH 1/2] [GDBserver] Fix compiling conditional expressions accessing registers Date: Fri, 11 Sep 2015 17:25:00 -0000 Message-Id: <1441992301-26779-2-git-send-email-pierre.langlois@arm.com> In-Reply-To: <1441992301-26779-1-git-send-email-pierre.langlois@arm.com> References: <1441992301-26779-1-git-send-email-pierre.langlois@arm.com> X-MC-Unique: 7d0Gj-KNQLandgrLzTF7_g-3 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg00240.txt.bz2 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 =3D=3D *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 =3D=3D *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=3D0x7fffffffc038, ^^^^^^^^^^^^^^ tpoint=3D0x7ffff68e2010) at ... (gdb) continue Breakpoint 5, gdb_agent_get_raw_reg (raw_regs=3D0x7fffffffc038 "\001", ^^^^^^^^^^^^^^ regnum=3D16) 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) : Rename to ... (struct ipa_sym_addresses) : ... this. (symbol_list): Rename get_raw_reg to get_reg. (struct fast_tracepoint_ctx) , : 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-ip= a.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 *regca= che, ((char *) buf) + x86_64_ft_collect_regmap[i]); } =20 -IP_AGENT_EXPORT_FUNC ULONGEST -gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum) -{ - if (regnum >=3D X86_64_NUM_FT_COLLECT_GREGS) - return 0; - - return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]); -} - #ifdef HAVE_UST =20 #include 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 *regca= che, } } =20 -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 >=3D I386_CS_REGNUM && regnum <=3D 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 =20 #include 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 +=3D 4; append_insns (&buildaddr, i, buf); current_insn_ptr =3D buildaddr; - amd64_emit_call (get_raw_reg_func_addr ()); + amd64_emit_call (get_reg_func_addr ()); } =20 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_co= unt) # define traceframes_created IPA_SYM_EXPORTED_NAME (traceframes_created) # define trace_state_variables IPA_SYM_EXPORTED_NAME (trace_state_variable= s) -# 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; =20 struct regcache regcache; - int regcache_initted; unsigned char *regspace; =20 - unsigned char *regs; struct tracepoint *tpoint; }; =20 @@ -4724,13 +4722,6 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx) if (ctx->type =3D=3D fast_tracepoint) { struct fast_tracepoint_ctx *fctx =3D (struct fast_tracepoint_ctx *) = ctx; - if (!fctx->regcache_initted) - { - fctx->regcache_initted =3D 1; - init_register_cache (&fctx->regcache, ipa_tdesc, fctx->regspace); - supply_regblock (&fctx->regcache, NULL); - supply_fast_tracepoint_registers (&fctx->regcache, fctx->regs); - } regcache =3D &fctx->regcache; } #ifdef HAVE_UST @@ -5796,11 +5787,16 @@ gdb_collect (struct tracepoint *tpoint, unsigned ch= ar *regs) return; =20 ctx.base.type =3D fast_tracepoint; - ctx.regs =3D regs; - ctx.regcache_initted =3D 0; /* Wrap the regblock in a register cache (in the stack, we don't want to malloc here). */ ctx.regspace =3D 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 =3D=3D NULL) { trace_debug ("Trace buffer block allocation failed, skipping"); @@ -5853,14 +5849,28 @@ gdb_collect (struct tracepoint *tpoint, unsigned ch= ar *regs) } } =20 +/* 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 =20 #ifndef IN_PROCESS_AGENT =20 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; } =20 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_cont= ext *ctx, CORE_ADDR from, ULONGEST len); =20 -/* 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); --=20 2.4.6