public inbox for gdb-prs@sourceware.org
help / color / mirror / Atom feed
* remote/2301: Transmission gdb gdbserver remotestub corrupted
@ 2007-08-13 15:38 Nils.Hagge
       [not found] ` <20070814111120.GA28029@caradoc.them.org>
  0 siblings, 1 reply; 2+ 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] 2+ messages in thread

* pending/2302: AW: remote/2301: Transmission gdb gdbserver remotestub corrupted
       [not found]     ` <20070814121547.GA6006@caradoc.them.org>
@ 2007-08-14 12:48       ` Hagge, Nils
  0 siblings, 0 replies; 2+ messages in thread
From: Hagge, Nils @ 2007-08-14 12:48 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Neugebauer, Manfred, gdb-gnats


>Number:         2302
>Category:       pending
>Synopsis:       AW: remote/2301: Transmission gdb gdbserver remotestub corrupted
>Confidential:   yes
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          change-request
>Submitter-Id:   unknown
>Arrival-Date:   Tue Aug 14 12:48:02 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator:     
>Release:        
>Organization:
>Environment:
>Description:
 > No, I want evidence of _what_ is destroying the buffer.  If the
 > checksum is being generated after the bytes are corrupted then
 
 But the problem is at the moment, that I do not know what/who destroys
 the packet. If I knew it, I could have solved it possibly by myself ;-)
 
 > this can't have anything to do with TCP since the packet has not been
 > sent yet.
 >=20
 > 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,=20
 when I use two Linux systems. The problem only shows up using cygwin!
 My requirement is to be able to use cygwin as well!
 
 Regards,
 Nils
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:


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

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

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-13 15:38 remote/2301: Transmission gdb gdbserver remotestub corrupted Nils.Hagge
     [not found] ` <20070814111120.GA28029@caradoc.them.org>
     [not found]   ` <99265762C22EE44F872C2E3E491CC4D603284BDB@KHED165A.ww004.siemens.net>
     [not found]     ` <20070814121547.GA6006@caradoc.them.org>
2007-08-14 12:48       ` pending/2302: AW: " Hagge, Nils

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).