public inbox for gdb-prs@sourceware.org
help / color / mirror / Atom feed
* Re: remote/2301: Transmission gdb gdbserver remotestub corrupted
@ 2007-08-14 11:18 Daniel Jacobowitz
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2007-08-14 11:18 UTC (permalink / raw)
  To: nobody; +Cc: gdb-prs

The following reply was made to PR remote/2301; it has been noted by GNATS.

From: Daniel Jacobowitz <drow@false.org>
To: Nils.Hagge@siemens.com
Cc: gdb-gnats@sources.redhat.com, Manfred.Neugebauer@siemens.com
Subject: Re: remote/2301: Transmission gdb gdbserver remotestub corrupted
Date: Tue, 14 Aug 2007 07:11:20 -0400

 On Mon, Aug 13, 2007 at 03:29:48PM -0000, Nils.Hagge@siemens.com wrote:
 > by printing into "buf". The packet is sent via putpkt. And the response is waited for using getpkt using rs->buf. But in fact rs->buf and buf point to the same piece of memory!! In the case that transmission and reception of tcp packets is performed asynchronously, this would explain the problem!
 > 
 > Could someone please check, if I am right!
 
 GDB does not use asynchronous TCP.  If the packet is not fully sent,
 or at least read from program memory, by the time that getpkt returns,
 then the entire file is going to fail; and as far as I know, no
 operating system does this.  Do you have any reference for Windows
 confirming that it will do what you describe?
 
 -- 
 Daniel Jacobowitz
 CodeSourcery


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: remote/2301: Transmission gdb gdbserver remotestub corrupted
@ 2007-08-14 12:58 Daniel Jacobowitz
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2007-08-14 12:58 UTC (permalink / raw)
  To: nobody; +Cc: gdb-prs

The following reply was made to PR remote/2301; it has been noted by GNATS.

From: Daniel Jacobowitz <drow@false.org>
To: "Hagge, Nils" <nils.hagge@siemens.com>
Cc: "Neugebauer, Manfred" <manfred.neugebauer@siemens.com>,
	gdb-gnats@sourceware.org
Subject: Re: remote/2301: Transmission gdb gdbserver remotestub corrupted
Date: Tue, 14 Aug 2007 08:48:46 -0400

 On Tue, Aug 14, 2007 at 02:38:48PM +0200, Hagge, Nils wrote:
 > > I suggest you try a current snapshot of GDB instead of the
 > > cygwin-special version.
 > 
 > But this does not solve the problem, since it works, 
 > when I use two Linux systems. The problem only shows up using cygwin!
 > My requirement is to be able to use cygwin as well!
 
 You can compile a current snapshot of GDB on Cygwin.
 
 In fact you should.  The Cygwin version said:
   This GDB was configured as "i686-pc-cygwin".
 
 You're not debugging Cygwin, you're debugging Linux.  You need a GDB
 configured to debug Linux.
 
 -- 
 Daniel Jacobowitz
 CodeSourcery


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: remote/2301: Transmission gdb gdbserver remotestub corrupted
@ 2007-08-14 12:18 Daniel Jacobowitz
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2007-08-14 12:18 UTC (permalink / raw)
  To: nobody; +Cc: gdb-prs

The following reply was made to PR remote/2301; it has been noted by GNATS.

From: Daniel Jacobowitz <drow@false.org>
To: "Hagge, Nils" <nils.hagge@siemens.com>
Cc: "Neugebauer, Manfred" <manfred.neugebauer@siemens.com>,
	gdb-gnats@sourceware.org
Subject: Re: remote/2301: Transmission gdb gdbserver remotestub corrupted
Date: Tue, 14 Aug 2007 08:15:47 -0400

 On Tue, Aug 14, 2007 at 01:34:58PM +0200, Hagge, Nils wrote:
 > This means that the checksum is generated, after the first bytes "Hc"
 > are
 > Destroyed, since F8+20+2D+31 = 176 --> mod 256 --> 76 (see above!). As a
 > Coincidence the checksum checking fails, nevertheless, since in the
 > remote stub
 > The checksum is calculated from the 7-bit values --> F8 is treated as
 > 78,
 > Thus on the target 78+20+2D+31 = F6 is compared to 76, which generates a
 > 
 > "bad checksum" error.
 > 
 > Do you want me to prepare a more detailed log?
 
 No, I want evidence of _what_ is destroying the buffer.  If the
 checksum is being generated after the bytes are corrupted then
 this can't have anything to do with TCP since the packet has not been
 sent yet.
 
 I suggest you try a current snapshot of GDB instead of the
 cygwin-special version.
 
 -- 
 Daniel Jacobowitz
 CodeSourcery


^ permalink raw reply	[flat|nested] 4+ messages in thread

* remote/2301: Transmission gdb gdbserver remotestub corrupted
@ 2007-08-13 15:38 Nils.Hagge
  0 siblings, 0 replies; 4+ messages in thread
From: Nils.Hagge @ 2007-08-13 15:38 UTC (permalink / raw)
  To: gdb-gnats; +Cc: Manfred.Neugebauer


>Number:         2301
>Category:       remote
>Synopsis:       Transmission gdb gdbserver remotestub corrupted
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    unassigned
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 13 15:38:01 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator:     Nils Hagge
>Release:        gdb 6.5.50
>Organization:
>Environment:
Cygwin/windows xp
>Description:
On the remote system x.x.x.225 (SuSE 10.2), I did

gdbserver localhost:8799 /home/user/HalloWelt

On the host x.x.x.245 (Cygwin/Windows XP)

$ gdb
GNU gdb 6.5.50.20060706-cvs (cygwin-special)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-cygwin".
(gdb) set debug remote 1
(gdb) target remote 192.168.20.225:8799
Remote debugging using 192.168.20.225:8799
Sending packet: $qSupported#37...Ack
Packet received:
Packet qSupported (supported-packets) is NOT supported
Sending packet: $o -1#76...Nak [bytes 24/F8/20/2D/31/23/37/36]
Sending packet: $o -1#76...Nak
Sending packet: $o -1#76...Nak
Sending packet: $o -1#76...Nak
Timed out.
Timed out.
Timed out.
Ignoring packet error, continuing...
Sending packet: $qC#b4...Ack
Packet received:
Sending packet: $qOffsets#4b...Ack
Packet received:
Sending packet: $?#3f...Ack
Packet received: T0505:00000000;04:d056f9bf;08:20810408;
    134 [main] gdb 8984 _cygtls::handle_exceptions: Error while dumping state (p
robably corrupted stack)
Segmentation fault (core dumped)

--------------

The problem is obvioulsly the packet "$o -1#76" being sent to the debugger stub. It took me a while to figure out that this command is corrupted, i.e. is not the intented one. Using wireshark I found out that "o" is not "o" but a F8 character modified by the terminal. The whole sequence is: 24/F8/20/2D/31/23/37/36. The F8 character causes the cksum calculation to fail, since gdbserver perfoms an 8-bit addition, and the stub does a 7-bit addition. This is in general not a problem when only 7-bit ascii is used. 

Using the debug output and examining the source code of remote.c I derived that the strange command must originate from "MARK A". But it should have been "$Hc-1#09"
At "MARK B" the command "$qC#b4" is generated which arrives correctly at the remote system.

----------------
remote.c:
/* Stub for catch_exception.  */

static void
remote_start_remote (struct ui_out *uiout, void *from_tty_p)
{
  int from_tty = * (int *) from_tty_p;

  immediate_quit++;		/* Allow user to interrupt it.  */

  /* Ack any packet which the remote side has already sent.  */
  serial_write (remote_desc, "+", 1);  

  /* Let the stub know that we want it to return the thread.  */
  set_thread (-1, 0); /// MARK A

  inferior_ptid = remote_current_thread (inferior_ptid); /// MARK B

  get_offsets ();		/* Get text, data & bss offsets.  */

  putpkt ("?");			/* Initiate a query from remote machine.  */
  immediate_quit--;

  start_remote (from_tty);	/* Initialize gdb process mechanisms.  */
}
------------------------

Thus, when the following routine is called, the
first two characters of "Hc-1" must have been destroyed asynchronously. And the checksum is generated from the corrupted characters "correctly."

------------------------

/* Send a packet to the remote machine, with error checking.  The data
   of the packet is in BUF.  The string in BUF can be at most
   get_remote_packet_size () - 5 to account for the $, # and checksum,
   and for a possible /0 if we are debugging (remote_debug) and want
   to print the sent packet as a string.  */

static int
putpkt_binary (char *buf, int cnt)
{
  int i;
  unsigned char csum = 0;
  char *buf2 = alloca (cnt + 6);

  int ch;
  int tcount = 0;
  char *p;

  /* Copy the packet into buffer BUF2, encapsulating it
     and giving it a checksum.  */

  p = buf2;
  *p++ = '$';

  for (i = 0; i < cnt; i++)
    {
      csum += buf[i];
      *p++ = buf[i];
    }
  *p++ = '#';
  *p++ = tohex ((csum >> 4) & 0xf);
  *p++ = tohex (csum & 0xf);

  /* Send it over and over until we get a positive ack.  */

  while (1)
    {
      int started_error_output = 0;

      if (remote_debug)                       // (**)
	{
	  *p = '\0';
	  fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
	  fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
	  fprintf_unfiltered (gdb_stdlog, "...");
	  gdb_flush (gdb_stdlog);
	}
      if (serial_write (remote_desc, buf2, p - buf2))
	perror_with_name (_("putpkt: write failed"));

      /* Read until either a timeout occurs (-2) or '+' is read.  */
      while (1)
	{
	  ch = readchar (remote_timeout);

	  if (remote_debug)
	    {
	      switch (ch)
		{
		case '+':
		case '-':
		case SERIAL_TIMEOUT:
		case '$':
		  if (started_error_output)
		    {
		      putchar_unfiltered ('\n');
		      started_error_output = 0;
		    }
		}
	    }

	  switch (ch)
	    {
	    case '+':
	      if (remote_debug)
		fprintf_unfiltered (gdb_stdlog, "Ack\n");
	      return 1;
	    case '-':
	      if (remote_debug)
		fprintf_unfiltered (gdb_stdlog, "Nak\n");
	    case SERIAL_TIMEOUT:
	      tcount++;
	      if (tcount > 3)
		return 0;
	      break;		/* Retransmit buffer.  */
	    case '$':
	      {
	        if (remote_debug)
		  fprintf_unfiltered (gdb_stdlog,
				      "Packet instead of Ack, ignoring it\n");
		/* It's probably an old response sent because an ACK
		   was lost.  Gobble up the packet and ack it so it
		   doesn't get retransmitted when we resend this
		   packet.  */
		skip_frame ();
		serial_write (remote_desc, "+", 1);
		continue;	/* Now, go look for +.  */
	      }
	    default:
	      if (remote_debug)
		{
		  if (!started_error_output)
		    {
		      started_error_output = 1;
		      fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
		    }
		  fputc_unfiltered (ch & 0177, gdb_stdlog);
		}
	      continue;
	    }
	  break;		/* Here to retransmit.  */
	}

#if 0
      /* This is wrong.  If doing a long backtrace, the user should be
         able to get out next time we call QUIT, without anything as
         violent as interrupt_query.  If we want to provide a way out of
         here without getting to the next QUIT, it should be based on
         hitting ^C twice as in remote_wait.  */
      if (quit_flag)
	{
	  quit_flag = 0;
	  interrupt_query ();
	}
#endif
    }
}
---------------

The command Hc-1 is produced by the following routine: 

--------------------
static void
set_thread (int th, int gen)
{
  struct remote_state *rs = get_remote_state ();
  char *buf = rs->buf;
  int state = gen ? general_thread : continue_thread;

  if (state == th)
    return;

  buf[0] = 'H';
  buf[1] = gen ? 'g' : 'c';
  if (th == MAGIC_NULL_PID)
    {
      buf[2] = '0';
      buf[3] = '\0';
    }
  else if (th < 0)
    xsnprintf (&buf[2], get_remote_packet_size () - 2, "-%x", -th);
  else
    xsnprintf (&buf[2], get_remote_packet_size () - 2, "%x", th);
  putpkt (buf);
  getpkt (&rs->buf, &rs->buf_size, 0);
  if (gen)
    general_thread = th;
  else
    continue_thread = th;
}
---

by printing into "buf". The packet is sent via putpkt. And the response is waited for using getpkt using rs->buf. But in fact rs->buf and buf point to the same piece of memory!! In the case that transmission and reception of tcp packets is performed asynchronously, this would explain the problem!

Could someone please check, if I am right!

Thanks
>How-To-Repeat:

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-08-14 12:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-14 11:18 remote/2301: Transmission gdb gdbserver remotestub corrupted Daniel Jacobowitz
  -- strict thread matches above, loose matches on Subject: below --
2007-08-14 12:58 Daniel Jacobowitz
2007-08-14 12:18 Daniel Jacobowitz
2007-08-13 15:38 Nils.Hagge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).