Reg : gdb crash is seen while attaching a process to gdb.

RAJESH DASARI raajeshdasari@gmail.com
Thu Apr 27 06:13:00 GMT 2017


Hi ,

I have raised a bug for the issue discussed in this mail chain,
https://sourceware.org/bugzilla/show_bug.cgi?id=21395 and i was able
to resolve the issue with minor code changes.

Could someone please provide  comments.

diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 9d22773..68641f8 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -634,9 +634,20 @@ mips_linux_new_thread (struct lwp_info *lp)
                                        &watch_readback_valid, 0))
     return;

+  long r;
+  r= ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror, NULL);
   tid = ptid_get_lwp (lp->ptid);
-  if (ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror, NULL) == -1)
-    perror_with_name (_("Couldn't write debug register"));
+  if ( r == -1L && errno == ESRCH )
+  {
+     /* sleep for a while to eliminate race condition on  update to kernel
+      * task structure with the process state (STOP state of thread).
+      */
+     usleep(10000);
+     if ( ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror, NULL) == -1 )
+     {
+        perror_with_name (_("Couldn't write debug register"));
+     }
+   }
 }

 /* Target to_insert_watchpoint implementation.  Try to insert a new
-- 
2.4.11



Thanks,
Rajesh Dasari.


On Fri, Apr 7, 2017 at 2:09 PM, RAJESH DASARI <raajeshdasari@gmail.com> wrote:
> Hi,
>
>
> I have recompiled the gdb with the given patch but still i see the issue ,
>
> These are my observation when i see the gdb crash.
>
> 1.  strace -e ptrace gdb -p 7978 <when i attach gdb with strace
> enabled, attaching , dettaching and all the debugging operations were
> successful>.
>
> 2. when i attach process with only gdb command like below
>  gdb -p 7878 ,
>     [New LWP 7879]
> Couldn't write debug register: No such process.
> (gdb) bt
> #0  0xf5655ea0 in ?? ()
> Backtrace stopped: previous frame identical to this frame (corrupt stack?)
>
> Any idea why i am seeing couldn't write debug registers error and
> Backtrace stopped: previous frame identical to this frame (corrupt
> stack?) errors.
>
> when i dettach the process in this state , i am getting the core dump
> which i had reported in my previous mail .
>
> Is this bug in gdb ,Could you someone please help me on how to proceed
> further on this issue.
>
> Regards,
> Rajesh.
>
> Thanks,
> Rajesh Dasari.
>
>
> On Mon, Mar 27, 2017 at 2:24 PM, Yao Qi <qiyaoltc@gmail.com> wrote:
>> RAJESH DASARI <raajeshdasari@gmail.com> writes:
>>
>>> Thanks for your quick response . Could you please share those patches
>>> , I will recompile the gdb with the patches and test the changes.
>>
>> Could you try the patch below on 7.12?  If the patch doesn't work,
>> please provide the GDB's stack backtrace on internal error.
>>
>> --
>> Yao (齐尧)
>> From 0621d3b4c0c665defc2166ee6240dc85f909275a Mon Sep 17 00:00:00 2001
>> From: Yao Qi <yao.qi@linaro.org>
>> Date: Mon, 27 Mar 2017 09:42:38 +0100
>> Subject: [PATCH] Fix refcount of thread_info
>>
>> I build GDB with asan, and run test case hook-stop.exp, and threadapply.exp,
>> I got the following asan error,
>>
>> =================================================================^M
>> ^[[1m^[[31m==2291==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000999c4 at pc 0x000000826022 bp 0x7ffd28a8ff70 sp 0x7ffd28a8ff60^M
>> ^[[1m^[[0m^[[1m^[[34mREAD of size 4 at 0x6160000999c4 thread T0^[[1m^[[0m^M
>>     #0 0x826021 in release_stop_context_cleanup ../../binutils-gdb/gdb/infrun.c:8203^M
>>     #1 0x72798a in do_my_cleanups ../../binutils-gdb/gdb/common/cleanups.c:154^M
>>     #2 0x727a32 in do_cleanups(cleanup*) ../../binutils-gdb/gdb/common/cleanups.c:176^M
>>     #3 0x826895 in normal_stop() ../../binutils-gdb/gdb/infrun.c:8381^M
>>     #4 0x815208 in fetch_inferior_event(void*) ../../binutils-gdb/gdb/infrun.c:4011^M
>>     #5 0x868aca in inferior_event_handler(inferior_event_type, void*) ../../binutils-gdb/gdb/inf-loop.c:44^M
>> ....
>> ^[[1m^[[32m0x6160000999c4 is located 68 bytes inside of 568-byte region [0x616000099980,0x616000099bb8)^M
>> ^[[1m^[[0m^[[1m^[[35mfreed by thread T0 here:^[[1m^[[0m^M
>>     #0 0x7fb0bc1312ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)^M
>>     #1 0xb8c62f in xfree(void*) ../../binutils-gdb/gdb/common/common-utils.c:100^M
>>     #2 0x83df67 in free_thread ../../binutils-gdb/gdb/thread.c:207^M
>>     #3 0x83dfd2 in init_thread_list() ../../binutils-gdb/gdb/thread.c:223^M
>>     #4 0x805494 in kill_command ../../binutils-gdb/gdb/infcmd.c:2595^M
>> ....
>>
>> Detaching from program: /home/yao.qi/SourceCode/gnu/build-with-asan/gdb/testsuite/outputs/gdb.threads/threadapply/threadapply, process 2399^M
>> =================================================================^M
>> ^[[1m^[[31m==2387==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000a98c0 at pc 0x00000083fd28 bp 0x7ffd401c3110 sp 0x7ffd401c3100^M
>> ^[[1m^[[0m^[[1m^[[34mREAD of size 4 at 0x6160000a98c0 thread T0^[[1m^[[0m^M
>>     #0 0x83fd27 in thread_alive ../../binutils-gdb/gdb/thread.c:741^M
>>     #1 0x844277 in thread_apply_all_command ../../binutils-gdb/gdb/thread.c:1804^M
>> ....
>> ^M
>> ^[[1m^[[32m0x6160000a98c0 is located 64 bytes inside of 568-byte region [0x6160000a9880,0x6160000a9ab8)^M
>> ^[[1m^[[0m^[[1m^[[35mfreed by thread T0 here:^[[1m^[[0m^M
>>     #0 0x7f59a7e322ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)^M
>>     #1 0xb8c62f in xfree(void*) ../../binutils-gdb/gdb/common/common-utils.c:100^M
>>     #2 0x83df67 in free_thread ../../binutils-gdb/gdb/thread.c:207^M
>>     #3 0x83dfd2 in init_thread_list() ../../binutils-gdb/gdb/thread.c:223^M
>>
>> This patch fixes the issue by always checking refcount before decreasing it.
>> If it is zero already, free the thread_info.
>>
>> gdb:
>>
>> 2017-03-27  Yao Qi  <yao.qi@linaro.org>
>>
>>         PR gdb/19942
>>         * gdbthread.h (free_thread): Declare.
>>         * infrun.c (release_stop_context_cleanup): If refcount is zero
>>         call free_thread.
>>         * thread.c (free_thread): Remove "static".
>>         (init_thread_list): If refcount is zero, call free_thread.
>>         (restore_current_thread_cleanup_dtor): Likewise.
>>         (set_thread_refcount): Likewise.
>> ---
>>  gdb/gdbthread.h |  3 +++
>>  gdb/infrun.c    |  7 ++++++-
>>  gdb/thread.c    | 21 +++++++++++++++++----
>>  3 files changed, 26 insertions(+), 5 deletions(-)
>>
>> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
>> index 455cfd8..f89c6e1 100644
>> --- a/gdb/gdbthread.h
>> +++ b/gdb/gdbthread.h
>> @@ -369,6 +369,9 @@ extern void delete_thread (ptid_t);
>>     exited, for example.  */
>>  extern void delete_thread_silent (ptid_t);
>>
>> +/* Free TP.  */
>> +extern void free_thread (struct thread_info *tp);
>> +
>>  /* Delete a step_resume_breakpoint from the thread database.  */
>>  extern void delete_step_resume_breakpoint (struct thread_info *);
>>
>> diff --git a/gdb/infrun.c b/gdb/infrun.c
>> index 5125ede..13b74bd 100644
>> --- a/gdb/infrun.c
>> +++ b/gdb/infrun.c
>> @@ -8200,7 +8200,12 @@ release_stop_context_cleanup (void *arg)
>>    struct stop_context *sc = (struct stop_context *) arg;
>>
>>    if (sc->thread != NULL)
>> -    sc->thread->refcount--;
>> +    {
>> +      if (sc->thread->refcount == 0)
>> +       free_thread (sc->thread);
>> +      else
>> +       sc->thread->refcount--;
>> +    }
>>    xfree (sc);
>>  }
>>
>> diff --git a/gdb/thread.c b/gdb/thread.c
>> index 1e39ac4..36dc40f 100644
>> --- a/gdb/thread.c
>> +++ b/gdb/thread.c
>> @@ -192,7 +192,7 @@ clear_thread_inferior_resources (struct thread_info *tp)
>>    thread_cancel_execution_command (tp);
>>  }
>>
>> -static void
>> +void
>>  free_thread (struct thread_info *tp)
>>  {
>>    if (tp->priv)
>> @@ -220,7 +220,10 @@ init_thread_list (void)
>>    for (tp = thread_list; tp; tp = tpnext)
>>      {
>>        tpnext = tp->next;
>> -      free_thread (tp);
>> +      if (tp->refcount == 0)
>> +       free_thread (tp);
>> +      else
>> +       tp->refcount--;
>>      }
>>
>>    thread_list = NULL;
>> @@ -1612,7 +1615,12 @@ restore_current_thread_cleanup_dtor (void *arg)
>>
>>    tp = find_thread_ptid (old->inferior_ptid);
>>    if (tp)
>> -    tp->refcount--;
>> +    {
>> +      if (tp->refcount == 0)
>> +       free_thread (tp);
>> +      else
>> +       tp->refcount--;
>> +    }
>>    inf = find_inferior_id (old->inf_id);
>>    if (inf != NULL)
>>      inf->removable = old->was_removable;
>> @@ -1629,7 +1637,12 @@ set_thread_refcount (void *data)
>>      = (struct thread_array_cleanup *) data;
>>
>>    for (k = 0; k != ta_cleanup->count; k++)
>> -    ta_cleanup->tp_array[k]->refcount--;
>> +    {
>> +      if (ta_cleanup->tp_array[k]->refcount == 0)
>> +       free_thread (ta_cleanup->tp_array[k]);
>> +      else
>> +       ta_cleanup->tp_array[k]->refcount--;
>> +    }
>>  }
>>
>>  struct cleanup *
>> --
>> 1.9.1



More information about the Gdb mailing list