From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6724 invoked by alias); 14 Feb 2013 10:13:24 -0000 Received: (qmail 6714 invoked by uid 22791); 14 Feb 2013 10:13:23 -0000 X-SWARE-Spam-Status: No, hits=-2.8 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_SPAMHAUS_DROP,KHOP_THREADED,RCVD_IN_DNSWL_LOW,TW_XZ X-Spam-Check-By: sourceware.org Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 14 Feb 2013 10:13:11 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Thu, 14 Feb 2013 10:13:09 +0000 Received: from [10.1.69.62] ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Thu, 14 Feb 2013 10:13:08 +0000 Message-ID: <511CB8B4.70708@arm.com> Date: Thu, 14 Feb 2013 10:13:00 -0000 From: Yufeng Zhang User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:8.0) Gecko/20111105 Thunderbird/8.0 MIME-Version: 1.0 To: Pedro Alves CC: Marcus Shawcroft , GDB Patches Subject: Re: [native AAarch64 GNU/Linux] Access debug register mirror from the corresponding process. References: <20130207163339.19427.73350.stgit@brno.lan> <20130207165907.GB15297@host2.jankratochvil.net> <51195E18.1010008@redhat.com> <511A372F.80006@redhat.com> <511BA106.8030103@arm.com> <511BADDB.3030703@redhat.com> <511BB8DE.3060704@redhat.com> <511BE1EF.3020408@arm.com> <511BE39D.3010006@redhat.com> In-Reply-To: <511BE39D.3010006@redhat.com> X-MC-Unique: 113021410130904801 Content-Type: multipart/mixed; boundary="------------050005070503060007020500" X-IsSubscribed: yes 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 X-SW-Source: 2013-02/txt/msg00341.txt.bz2 This is a multi-part message in MIME format. --------------050005070503060007020500 Content-Type: text/plain; charset=WINDOWS-1252; format=flowed Content-Transfer-Encoding: quoted-printable Content-length: 2390 On 02/13/13 19:03, Pedro Alves wrote: > On 02/13/2013 06:56 PM, Yufeng Zhang wrote: >> On 02/13/13 16:01, Pedro Alves wrote: >>> On 02/13/2013 03:21 PM, Marcus Shawcroft wrote: >>>>> I'll send you an aarch64 version of this patch, unless you've >>>>> already started porting the necessary bits over. >>>> >>>> We were just about to get started... but if you have a patch in hand >>>> that would be great! >>> >>> Here it is. Completely untested, of course. But hopefully not >>> too far off. >> >> Not far off at all; thanks! I have tested your patch and made some furt= her changes; please find the attached patch. The two patches together seem= to be working. > > Those changes look fine. Please merge them, and go ahead > post/commit the resulting patch. > Thanks. The attached is the merged patch. I'll commit it in a couple=20 of hours if no more comment is received. Thanks, Yufeng 2013-02-14 Pedro Alves Yufeng Zhang * aarch64-linux-nat.c (aarch64_init_debug_reg_state): Delete. (aarch64_inferior_data, struct aarch64_inferior_data): Delete. (struct aarch64_process_info): New. (aarch64_process_list): New global. (aarch64_find_process_pid, aarch64_add_process) (aarch64_process_info_get): New functions. (aarch64_inferior_data_get): Delete. (aarch64_process_info_get): New function. (aarch64_forget_process): New function. (aarch64_get_debug_reg_state): New parameter 'pid'. Reimplement. (aarch64_linux_prepare_to_resume): Pass the lwp's pid to aarch64_get_debug_reg_state. (aarch64_notify_debug_reg_change): Use iterate_over_lwps instead of linux_nat_iterate_watchpoint_lwps. (aarch64_linux_new_fork): New function. (aarch64_linux_child_post_startup_inferior): Use aarch64_forget_process instead of aarch64_init_debug_reg_state. (aarch64_handle_breakpoint, aarch64_linux_insert_hw_breakpoint) (aarch64_linux_remove_hw_breakpoint) (aarch64_handle_aligned_watchpoint) (aarch64_handle_unaligned_watchpoint) (aarch64_linux_insert_watchpoint) (aarch64_linux_remove_watchpoint) (aarch64_linux_stopped_data_address): Adjust to pass the current process id to aarch64_debug_reg_state. (_initialize_aarch64_linux_nat): Install aarch64_linux_new_fork as linux_nat_new_fork hook, and aarch64_forget_process as linux_nat_forget_process hook; remove the call to register_inferior_data_with_cleanup.= --------------050005070503060007020500 Content-Type: text/x-patch; name=aarch64-dregs.patch Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="aarch64-dregs.patch" Content-length: 11925 diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 507ba81..846f156 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -189,75 +189,103 @@ struct aarch64_debug_reg_state unsigned int dr_ref_count_wp[AARCH64_HWP_MAX_NUM]; }; =20 -/* Clear the reference counts and forget everything we knew about the - debug registers. */ +/* Per-process data. We don't bind this to a per-inferior registry + because of targets like x86 GNU/Linux that need to keep track of + processes that aren't bound to any inferior (e.g., fork children, + checkpoints). */ =20 -static void -aarch64_init_debug_reg_state (struct aarch64_debug_reg_state *state) +struct aarch64_process_info { - int i; + /* Linked list. */ + struct aarch64_process_info *next; =20 - for (i =3D 0; i < AARCH64_HBP_MAX_NUM; ++i) - { - state->dr_addr_bp[i] =3D 0; - state->dr_ctrl_bp[i] =3D 0; - state->dr_ref_count_bp[i] =3D 0; - } + /* The process identifier. */ + pid_t pid; =20 - for (i =3D 0; i < AARCH64_HWP_MAX_NUM; ++i) - { - state->dr_addr_wp[i] =3D 0; - state->dr_ctrl_wp[i] =3D 0; - state->dr_ref_count_wp[i] =3D 0; - } + /* Copy of aarch64 hardware debug registers. */ + struct aarch64_debug_reg_state state; +}; + +static struct aarch64_process_info *aarch64_process_list =3D NULL; + +/* Find process data for process PID. */ + +static struct aarch64_process_info * +aarch64_find_process_pid (pid_t pid) +{ + struct aarch64_process_info *proc; + + for (proc =3D aarch64_process_list; proc; proc =3D proc->next) + if (proc->pid =3D=3D pid) + return proc; + + return NULL; } =20 -/* Per-inferior data key. */ -static const struct inferior_data *aarch64_inferior_data; +/* Add process data for process PID. Returns newly allocated info + object. */ =20 -/* Per-inferior data. */ -struct aarch64_inferior_data +static struct aarch64_process_info * +aarch64_add_process (pid_t pid) { - /* Copy of AArch64 hardware debug registers for performance reasons. */ - struct aarch64_debug_reg_state state; -}; + struct aarch64_process_info *proc; =20 -/* Per-inferior hook for register_inferior_data_with_cleanup. */ + proc =3D xcalloc (1, sizeof (*proc)); + proc->pid =3D pid; =20 -static void -aarch64_inferior_data_cleanup (struct inferior *inf, void *arg) + proc->next =3D aarch64_process_list; + aarch64_process_list =3D proc; + + return proc; +} + +/* Get data specific info for process PID, creating it if necessary. + Never returns NULL. */ + +static struct aarch64_process_info * +aarch64_process_info_get (pid_t pid) { - struct aarch64_inferior_data *inf_data =3D arg; + struct aarch64_process_info *proc; + + proc =3D aarch64_find_process_pid (pid); + if (proc =3D=3D NULL) + proc =3D aarch64_add_process (pid); =20 - xfree (inf_data); + return proc; } =20 -/* Get data specific for INFERIOR_PTID LWP. Return special data area - for processes being detached. */ +/* Called whenever GDB is no longer debugging process PID. It deletes + data structures that keep track of debug register state. */ =20 -static struct aarch64_inferior_data * -aarch64_inferior_data_get (void) +static void +aarch64_forget_process (pid_t pid) { - struct inferior *inf =3D current_inferior (); - struct aarch64_inferior_data *inf_data; + struct aarch64_process_info *proc, **proc_link; =20 - inf_data =3D inferior_data (inf, aarch64_inferior_data); - if (inf_data =3D=3D NULL) + proc =3D aarch64_process_list; + proc_link =3D &aarch64_process_list; + + while (proc !=3D NULL) { - inf_data =3D xzalloc (sizeof (*inf_data)); - set_inferior_data (inf, aarch64_inferior_data, inf_data); - } + if (proc->pid =3D=3D pid) + { + *proc_link =3D proc->next; =20 - return inf_data; + xfree (proc); + return; + } + + proc_link =3D &proc->next; + proc =3D *proc_link; + } } =20 -/* Get debug registers state for INFERIOR_PTID, see - aarch64_inferior_data_get. */ +/* Get debug registers state for process PID. */ =20 static struct aarch64_debug_reg_state * -aarch64_get_debug_reg_state (void) +aarch64_get_debug_reg_state (pid_t pid) { - return &aarch64_inferior_data_get ()->state; + return &aarch64_process_info_get (pid)->state; } =20 /* Per-thread arch-specific data we want to keep. */ @@ -308,7 +336,7 @@ struct aarch64_dr_update_callback_param unsigned int idx; }; =20 -/* Callback for linux_nat_iterate_watchpoint_lwps. Records the +/* Callback for iterate_over_lwps. Records the information about the change of one hardware breakpoint/watchpoint setting for the thread LWP. The information is passed in via PTR. @@ -382,12 +410,12 @@ aarch64_notify_debug_reg_change (const struct aarch64= _debug_reg_state *state, int is_watchpoint, unsigned int idx) { struct aarch64_dr_update_callback_param param; + ptid_t pid_ptid =3D pid_to_ptid (ptid_get_pid (inferior_ptid)); =20 param.is_watchpoint =3D is_watchpoint; param.idx =3D idx; =20 - linux_nat_iterate_watchpoint_lwps (debug_reg_change_callback, - (void *) ¶m); + iterate_over_lwps (pid_ptid, debug_reg_change_callback, (void *) ¶m); } =20 /* Print the values of the cached breakpoint/watchpoint registers. */ @@ -655,7 +683,8 @@ aarch64_linux_prepare_to_resume (struct lwp_info *lwp) || DR_HAS_CHANGED (info->dr_changed_wp)) { int tid =3D GET_LWP (lwp->ptid); - struct aarch64_debug_reg_state *state =3D aarch64_get_debug_reg_stat= e (); + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (lwp->ptid)); =20 if (debug_hw_points) fprintf_unfiltered (gdb_stdlog, "prepare_to_resume thread %d\n", tid); @@ -688,6 +717,32 @@ aarch64_linux_new_thread (struct lwp_info *lp) =20 lp->arch_private =3D info; } + +/* linux_nat_new_fork hook. */ + +static void +aarch64_linux_new_fork (struct lwp_info *parent, pid_t child_pid) +{ + pid_t parent_pid; + struct aarch64_debug_reg_state *parent_state; + struct aarch64_debug_reg_state *child_state; + + /* NULL means no watchpoint has ever been set in the parent. In + that case, there's nothing to do. */ + if (parent->arch_private =3D=3D NULL) + return; + + /* GDB core assumes the child inherits the watchpoints/hw + breakpoints of the parent, and will remove them all from the + forked off process. Copy the debug registers mirrors into the + new process so that all breakpoints and watchpoints can be + removed together. */ + + parent_pid =3D ptid_get_pid (parent->ptid); + parent_state =3D aarch64_get_debug_reg_state (parent_pid); + child_state =3D aarch64_get_debug_reg_state (child_pid); + *child_state =3D *parent_state; +} =0C =20 /* Called by libthread_db. Returns a pointer to the thread local @@ -776,9 +831,7 @@ static void (*super_post_startup_inferior) (ptid_t ptid= ); static void aarch64_linux_child_post_startup_inferior (ptid_t ptid) { - struct aarch64_debug_reg_state *state =3D aarch64_get_debug_reg_state (); - - aarch64_init_debug_reg_state (state); + aarch64_forget_process (ptid_get_pid (ptid)); aarch64_linux_get_debug_reg_capacity (); super_post_startup_inferior (ptid); } @@ -1132,7 +1185,7 @@ aarch64_handle_breakpoint (int type, CORE_ADDR addr, = int len, int is_insert) if (!aarch64_point_is_aligned (0 /* is_watchpoint */ , addr, len)) return -1; =20 - state =3D aarch64_get_debug_reg_state (); + state =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); =20 if (is_insert) return aarch64_dr_state_insert_one_point (state, type, addr, len); @@ -1161,8 +1214,13 @@ aarch64_linux_insert_hw_breakpoint (struct gdbarch *= gdbarch, ret =3D aarch64_handle_breakpoint (type, addr, len, 1 /* is_insert */); =20 if (debug_hw_points > 1) - aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (), - "insert_hw_watchpoint", addr, len, type); + { + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); + + aarch64_show_debug_reg_state (state, + "insert_hw_watchpoint", addr, len, type); + } =20 return ret; } @@ -1187,8 +1245,13 @@ aarch64_linux_remove_hw_breakpoint (struct gdbarch *= gdbarch, ret =3D aarch64_handle_breakpoint (type, addr, len, 0 /* is_insert */); =20 if (debug_hw_points > 1) - aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (), - "remove_hw_watchpoint", addr, len, type); + { + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); + + aarch64_show_debug_reg_state (state, + "remove_hw_watchpoint", addr, len, type); + } =20 return ret; } @@ -1200,7 +1263,8 @@ static int aarch64_handle_aligned_watchpoint (int type, CORE_ADDR addr, int len, int is_insert) { - struct aarch64_debug_reg_state *state =3D aarch64_get_debug_reg_state (); + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); =20 if (is_insert) return aarch64_dr_state_insert_one_point (state, type, addr, len); @@ -1219,7 +1283,8 @@ static int aarch64_handle_unaligned_watchpoint (int type, CORE_ADDR addr, int len, int is_insert) { - struct aarch64_debug_reg_state *state =3D aarch64_get_debug_reg_state (); + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); =20 while (len > 0) { @@ -1283,8 +1348,13 @@ aarch64_linux_insert_watchpoint (CORE_ADDR addr, int= len, int type, ret =3D aarch64_handle_watchpoint (type, addr, len, 1 /* is_insert */); =20 if (debug_hw_points > 1) - aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (), - "insert_watchpoint", addr, len, type); + { + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); + + aarch64_show_debug_reg_state (state, + "insert_watchpoint", addr, len, type); + } =20 return ret; } @@ -1310,8 +1380,13 @@ aarch64_linux_remove_watchpoint (CORE_ADDR addr, int= len, int type, ret =3D aarch64_handle_watchpoint (type, addr, len, 0 /* is_insert */); =20 if (debug_hw_points > 1) - aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (), - "remove_watchpoint", addr, len, type); + { + struct aarch64_debug_reg_state *state + =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); + + aarch64_show_debug_reg_state (state, + "remove_watchpoint", addr, len, type); + } =20 return ret; } @@ -1374,7 +1449,7 @@ aarch64_linux_stopped_data_address (struct target_ops= *target, return 0; =20 /* Check if the address matches any watched address. */ - state =3D aarch64_get_debug_reg_state (); + state =3D aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); for (i =3D aarch64_num_wp_regs - 1; i >=3D 0; --i) { const unsigned int len =3D aarch64_watchpoint_length (state->dr_ctrl= _wp[i]); @@ -1465,10 +1540,6 @@ _initialize_aarch64_linux_nat (void) t->to_stopped_data_address =3D aarch64_linux_stopped_data_address; t->to_watchpoint_addr_within_range =3D aarch64_linux_watchpoint_addr_within_range; - if (aarch64_inferior_data =3D=3D NULL) - aarch64_inferior_data - =3D register_inferior_data_with_cleanup (NULL, - aarch64_inferior_data_cleanup); =20 /* Override the GNU/Linux inferior startup hook. */ super_post_startup_inferior =3D t->to_post_startup_inferior; @@ -1477,5 +1548,7 @@ _initialize_aarch64_linux_nat (void) /* Register the target. */ linux_nat_add_target (t); linux_nat_set_new_thread (t, aarch64_linux_new_thread); + linux_nat_set_new_fork (t, aarch64_linux_new_fork); + linux_nat_set_forget_process (t, aarch64_forget_process); linux_nat_set_prepare_to_resume (t, aarch64_linux_prepare_to_resume); }= --------------050005070503060007020500--