From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4870 invoked by alias); 10 Oct 2008 11:30:09 -0000 Received: (qmail 4856 invoked by uid 22791); 10 Oct 2008 11:30:07 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 10 Oct 2008 11:29:30 +0000 Received: (qmail 13570 invoked from network); 10 Oct 2008 11:29:28 -0000 Received: from unknown (HELO orlando.local) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 10 Oct 2008 11:29:28 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH] fix gdbserver crash Date: Fri, 10 Oct 2008 11:30:00 -0000 User-Agent: KMail/1.9.9 MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_Yyz7IIeWhArNte6" Message-Id: <200810101229.28200.pedro@codesourcery.com> 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: 2008-10/txt/msg00311.txt.bz2 --Boundary-00=_Yyz7IIeWhArNte6 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 3624 Hi, gdbserver crashes in this situation: [gdbserver] ./gdbserver :9999 /home/pedro/gdb/tests/threads_same_loop_100_32 1 [gdbserver] Process /home/pedro/gdb/tests/threads_same_loop_100_32 created; pid = 7773 [gdbserver] Listening on port 9999 [ gdb ] (gdb) tar extended-remote :9999 [gdbserver] Remote debugging from host 127.0.0.1 [ gdb ] Remote debugging using :9999 [ gdb ] 0x00000000f7ef0810 in ?? () [ gdb ] (gdb) kill [ gdb ] Kill the program being debugged? (y or n) y (kill isn't important here, normal exit would be the same) [gdbserver] Killing inferior [ gdb ] (gdb) r [ gdb ] Starting program: [gdbserver] Process /home/pedro/gdb/tests/threads_same_loop_100_32 created; pid = 7799 [gdbserver] Cannot exec /home/pedro/gdb/tests/threads_same_loop_100_32: Bad address. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [ gdb ] Running the default executable on the remote target failed; try "set remote exec-file"? [ gdb ] (gdb) set remote exec-file /home/pedro/gdb/tests/threads_same_loop_100_32 [ gdb ] (gdb) r [ gdb ] Starting program: [ gdb ] Ignoring packet error, continuing... [gdbserver] Child exited with retcode = 7f [gdbserver] *** glibc detected *** /home/pedro/gdb/csl_trunk/build/gdb/gdbserver/gdbserver: double free or corruption (out): 0x00007f25148b3d30 *** [gdbserver] ======= Backtrace: ========= [gdbserver] Program received signal SIGSEGV, Segmentation fault. 0x00007f2514589c6f in abort () from /lib/libc.so.6 (gdb) bt #0 0x00007f2514589c6f in abort () from /lib/libc.so.6 #1 0x00007f25145c2a7b in __libc_message () from /lib/libc.so.6 #2 0x00007f25145ca08a in _int_free () from /lib/libc.so.6 #3 0x00007f25145cdc1c in free () from /lib/libc.so.6 #4 0x000000000040943e in handle_v_run ( own_buf=0x61b0f0 "vRun;2f686f6d652f706564726f2f6764622f74657374732f746872656164735f73616d655f6c6f6f705f3130305f3332", status=0x7fff1ccdbf56 "Wv", signal=0x7fff1ccdbf48) at ../../../src/gdb/gdbserver/server.c:1112 #5 0x000000000040963f in handle_v_requests ( own_buf=0x61b0f0 "vRun;2f686f6d652f706564726f2f6764622f74657374732f746872656164735f73616d655f6c6f6f705f3130305f3332", status=0x7fff1ccdbf56 "Wv", signal=0x7fff1ccdbf48, packet_len=97, new_packet_len=0x7fff1ccdbf20) at ../../../src/gdb/gdbserver/server.c:1175 #6 0x000000000040a817 in main (argc=4, argv=0x7fff1ccdc048) at ../../../src/gdb/gdbserver/server.c:1778 (gdb) The crash comes from this bit missing: Index: src/gdb/gdbserver/server.c =================================================================== --- src.orig/gdb/gdbserver/server.c 2008-10-10 12:11:26.000000000 +0100 +++ src/gdb/gdbserver/server.c 2008-10-10 12:11:39.000000000 +0100 @@ -1103,6 +1103,7 @@ handle_v_run (char *own_buf, char *statu } new_argv[0] = strdup (program_argv[0]); + new_argv[1] = NULL; } /* Free the old argv. */ So on the next vRun, we are trying to free a dangling pointer. `exec' had already failed due to that bad pointer before: [gdbserver] Cannot exec /home/pedro/gdb/tests/threads_same_loop_100_32: Bad address. The above fixes it, but, we're also ignoring all but argv[0] from the last run. Was that intended? Since I started gdbserver like: gdbserver :9999 PROG ARG I was a bit surprised to see that the ARG didn't get passed to the new inferior too in this case (vRun with set remote exec-file ""), only PROG was. The attached fixes the crash and adjusts it so the whole last argv is passed. OK? Or if not OK, is the above patchlet better then? -- Pedro Alves --Boundary-00=_Yyz7IIeWhArNte6 Content-Type: text/x-diff; charset="utf-8"; name="vrun_crash.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="vrun_crash.diff" Content-length: 1549 2008-10-10 Pedro Alves * server.c (handle_v_run): If GDB didn't specify an argv, use the whole argv from the last run, not just argv[0]. --- gdb/gdbserver/server.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) Index: src/gdb/gdbserver/server.c =================================================================== --- src.orig/gdb/gdbserver/server.c 2008-10-10 12:18:02.000000000 +0100 +++ src/gdb/gdbserver/server.c 2008-10-10 12:18:09.000000000 +0100 @@ -1096,23 +1096,31 @@ handle_v_run (char *own_buf, char *statu if (new_argv[0] == NULL) { + /* GDB didn't specify a program to run. Try to use the argv + from the last run: either from the last vRun with a non-empty + argv, or from what the user specified if gdbserver was + started as: `gdbserver :1234 PROG ARGS'. */ + if (program_argv == NULL) { write_enn (own_buf); return 0; } - new_argv[0] = strdup (program_argv[0]); + /* We can reuse the old args. We don't need this then. */ + free (new_argv); } - - /* Free the old argv. */ - if (program_argv) + else { - for (pp = program_argv; *pp != NULL; pp++) - free (*pp); - free (program_argv); + /* Free the old argv. */ + if (program_argv) + { + for (pp = program_argv; *pp != NULL; pp++) + free (*pp); + free (program_argv); + } + program_argv = new_argv; } - program_argv = new_argv; *signal = start_inferior (program_argv, status); if (*status == 'T') --Boundary-00=_Yyz7IIeWhArNte6--