Suggest newer gdbserver if it has no qXfer:exec-file:read

Message ID 20160323211547.GA17400@host1.jankratochvil.net
State New, archived
Headers

Commit Message

Jan Kratochvil March 23, 2016, 9:15 p.m. UTC
  On Tue, 22 Mar 2016 14:56:46 +0100, Pedro Alves wrote:
> - Random stubs may not know at all the executable that is running -- the
>   remote end is often just bare metal raw memory, no concept of elf, etc.
>   So it's not just a matter of implementing a packet - more tooling might
>   and I suspect will, be necessary.  OTOH, there are OSs where it's just not
>   possible, by design, to retrieve the name of the executable a process
>   is running, like OpenBSD (I find it odd not to allow a ptracer access
>   to that, but, alas).

IIUC for such an embedded target without any filesystem qXfer:exec-file:read
would need to generate a bogus filename which would be then
recognized/accepted by vFile:open.

Sending packet: $qXfer:exec-file:read:67:0,fff#f7...Packet received: l/root/redhat/threadit
Reading /root/redhat/threadit from remote target...
Sending packet: $vFile:open:2f726f6f742f7265646861742f7468726561646974,0,0#7e...Packet received: F5
Sending packet: $vFile:pread:5,3fff,0#98...Packet received: F27f8;\177ELF\002\001\001\000

Just stating that, nothing interesting.


> - I think the important points are:
> 
>   - The user did not specify the executable manually.
> 
>   - The target/server does not support automatic executable
>     retrieval. 
> 
> - I see that at least the following choices to correct the situation:
> 
>   #1 - Upgrade server to some version that supports automatic automatic
>        executable retrieval.
> 
>   #2 - Hack on stub/server yourself to add support for automatic 
>        executable retrieval, if possible on the target.
> 
>   #3 - Use the "file" command.
> 
> If you're connecting with a new gdb to an older gdbserver, it usually
> means that installing a newer gdbserver is more than a couple
> seconds work, and may not even be possible.  I think #3 will be the
> path most often taken.
> 
> So I'd suggest:
> 
>    warning: No executable has been specified and target does not support
>    determining executable automatically.  Try using the \"file\" command.
> 
> Seeing this, users that can hack on a remote stub will probably
> realize that there's now some way for gdb to automatically retrieve
> the executable.  We don't need to expose implementation details for those
> users; they'll be savvy enough to find the necessary info in the RSP
> manual.  For other users, talking about implementation details may
> largely be noise.

I still do not see there any hint that a newer FSF gdbserver would also fix the
problem.

Particularly because the "file" command is not the whole truth, plain
executable is sufficient mostly only for embedded systems.  For normal OSes
one needs also the shared libraries and those all are IMO not easy to access
without new FSF gdbserver.  But that's a whole new bug/issue:

With current FSF GDB HEAD and old FSF gdbserver I expected I could do:
	gdb -ex 'file target:/root/redhat/threadit' -ex 'target remote :1234' 
(supplying that unsupported qXfer:exec-file:read by "file")
But that does not work because:
	Sending packet: $vFile:setfs:0#bf...Packet received: OK
	Packet vFile:setfs (hostio-setfs) is supported
	...
	Sending packet: $vFile:setfs:104#24...Packet received: OK
	"target:/root/redhat/threadit": could not open as an executable file: Invalid argument

GDB documentation says:
	The valid responses to Host I/O packets are:
	An empty response indicates that this operation is not recognized.

OT: I do not see why "empty response" is response "OK" but apparently it is.

You can see that gdbserver above said "setfs" is unsupported but GDB
recognized it as a response gdbserver does support it.  Later
remote_hostio_set_filesystem() reports -1 as it is confused by the invalid
empty response for setfs while it sees no PACKET_DISABLE indication.
And GDB errors on it as remote_hostio_set_filesystem() returns 0 on
PACKET_DISABLE.

Are you aware of this general PACKET_DISABLE bug?  I can prepare some more
general real patch if not.

With the attached hack in packet_ok() I really can debug fine:
with unpatched old FSF gdbserver and patched FSF GDB HEAD:
	gdb -ex 'file target:/root/redhat/threadit' -ex 'target remote :1234' 
	Sending packet: $vFile:setfs:0#bf...Packet received: OK
	Packet vFile:setfs (hostio-setfs) is NOT supported
	...
	(gdb) info sharedlibrary 
	From                To                  Syms Read   Shared Object Library
	0x00007ffff7ddbae0  0x00007ffff7df627a  Yes (*)     target:/lib64/ld-linux-x86-64.so.2
	0x00007ffff7bc48a0  0x00007ffff7bcf514  Yes (*)     target:/lib64/libpthread.so.0


> Thinking of local/remote parity (and perhaps some day using gdbserver
> for local debugging), that text is also generic enough that it could
> be emitted by common code instead.

That's a good idea.  So we may be talking about two messages.


Attached patch prints messages as:

Remote debugging using :1234
warning: Remote gdbserver does not support determining executable automatically.
FSF gdbserver version 7.10 or later would support that.
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
warning: Could not load vsyscall page because no executable was specified
0x00007ffff7ddcc80 in ?? ()
(gdb) _


Thanks,
Jan
gdb/ChangeLog
2016-03-23  Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Pedro Alves  <palves@redhat.com>

	* exec.c (exec_file_locate_attach): Print warning for unsupported
	target_pid_to_exec_file.
	* remote.c (remote_pid_to_exec_file): Print warning for unsupported
	PACKET_qXfer_exec_file.
	* symfile-mem.c (add_vsyscall_page): Remove the "file" command
	message part.
  

Comments

Jan Kratochvil March 24, 2016, 4:59 p.m. UTC | #1
On Wed, 23 Mar 2016 22:15:47 +0100, Jan Kratochvil wrote:
> With current FSF GDB HEAD and old FSF gdbserver I expected I could do:
> 	gdb -ex 'file target:/root/redhat/threadit' -ex 'target remote :1234' 
> (supplying that unsupported qXfer:exec-file:read by "file")
> But that does not work because:
> 	Sending packet: $vFile:setfs:0#bf...Packet received: OK
> 	Packet vFile:setfs (hostio-setfs) is supported
> 	...
> 	Sending packet: $vFile:setfs:104#24...Packet received: OK
> 	"target:/root/redhat/threadit": could not open as an executable file: Invalid argument

Filed as:
	7.10 regression: gdb remote.c due to "setfs" with gdbserver <=7.9
	https://sourceware.org/bugzilla/show_bug.cgi?id=19863
  
Pedro Alves April 5, 2016, 4:32 p.m. UTC | #2
Closing the loop on this one:

On 03/23/2016 09:15 PM, Jan Kratochvil wrote:
> On Tue, 22 Mar 2016 14:56:46 +0100, Pedro Alves wrote:
>> - Random stubs may not know at all the executable that is running -- the
>>   remote end is often just bare metal raw memory, no concept of elf, etc.
>>   So it's not just a matter of implementing a packet - more tooling might
>>   and I suspect will, be necessary.  OTOH, there are OSs where it's just not
>>   possible, by design, to retrieve the name of the executable a process
>>   is running, like OpenBSD (I find it odd not to allow a ptracer access
>>   to that, but, alas).
> 
> IIUC for such an embedded target without any filesystem qXfer:exec-file:read
> would need to generate a bogus filename which would be then
> recognized/accepted by vFile:open.
> 
> Sending packet: $qXfer:exec-file:read:67:0,fff#f7...Packet received: l/root/redhat/threadit
> Reading /root/redhat/threadit from remote target...
> Sending packet: $vFile:open:2f726f6f742f7265646861742f7468726561646974,0,0#7e...Packet received: F5
> Sending packet: $vFile:pread:5,3fff,0#98...Packet received: F27f8;\177ELF\002\001\001\000
> 
> Just stating that, nothing interesting.

That'd assume that there's a structured elf on the target, while on bare
metal, you don't have that; no sections, no segments, etc.  Nothing other
than unstructured raw memory, much like what the "dump memory" would
give you.

Thanks,
Pedro Alves
  
Pedro Alves April 5, 2016, 4:57 p.m. UTC | #3
On 03/23/2016 09:15 PM, Jan Kratochvil wrote:
> On Tue, 22 Mar 2016 14:56:46 +0100, Pedro Alves wrote:

>> - I think the important points are:
>>
>>   - The user did not specify the executable manually.
>>
>>   - The target/server does not support automatic executable
>>     retrieval. 
>>
>> - I see that at least the following choices to correct the situation:
>>
>>   #1 - Upgrade server to some version that supports automatic automatic
>>        executable retrieval.
>>
>>   #2 - Hack on stub/server yourself to add support for automatic 
>>        executable retrieval, if possible on the target.
>>
>>   #3 - Use the "file" command.
>>
>> If you're connecting with a new gdb to an older gdbserver, it usually
>> means that installing a newer gdbserver is more than a couple
>> seconds work, and may not even be possible.  I think #3 will be the
>> path most often taken.
>>
>> So I'd suggest:
>>
>>    warning: No executable has been specified and target does not support
>>    determining executable automatically.  Try using the \"file\" command.
>>
>> Seeing this, users that can hack on a remote stub will probably
>> realize that there's now some way for gdb to automatically retrieve
>> the executable.  We don't need to expose implementation details for those
>> users; they'll be savvy enough to find the necessary info in the RSP
>> manual.  For other users, talking about implementation details may
>> largely be noise.
> 
> I still do not see there any hint that a newer FSF gdbserver would also fix the
> problem.

That's because I don't think it's a good approach.  If we followed
that direction going forward, we'd end up with:

 warning: Remote gdbserver does not support determining executable automatically.
 FSF gdbserver version 7.10 or later would support that.
 warning: Remote gdbserver does not support foo.
 FSF gdbserver version 6.5 or later would support that.
 warning: Remote gdbserver does not support bar.
 FSF gdbserver version 6.8 or later would support that.

Old version numbers shown on purpose -- that's what 7.10
will feel like in a couple years.  I think it's not a good
idea to show version numbers, nor am I convinced mentioning
gdbserver is a good idea either.  There's bare metal targets, and
then there's also other servers like qemu, Valgrind, RR, etc.

Sorry for pushing back, but I think warnings should be centered
on features, not tools and versions.

> Attached patch prints messages as:
> 
> Remote debugging using :1234
> warning: Remote gdbserver does not support determining executable automatically.
> FSF gdbserver version 7.10 or later would support that.
> warning: No executable has been specified and target does not support
> determining executable automatically.  Try using the "file" command.
> warning: Could not load vsyscall page because no executable was specified
> 0x00007ffff7ddcc80 in ?? ()
> (gdb) _
> 



> diff --git a/gdb/exec.c b/gdb/exec.c
> index 90811c0..a10ab9b 100644
> --- a/gdb/exec.c
> +++ b/gdb/exec.c
> @@ -151,7 +151,13 @@ exec_file_locate_attach (int pid, int from_tty)
>    /* Try to determine a filename from the process itself.  */
>    exec_file = target_pid_to_exec_file (pid);
>    if (exec_file == NULL)
> -    return;
> +    {
> +      warning (_("No executable has been specified and target does not "
> +		 "support\n"
> +		 "determining executable automatically.  "
> +		 "Try using the \"file\" command."));
> +      return;
> +    }

This bit is OK.

> diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
> index 8eb5176..79739a6 100644
> --- a/gdb/symfile-mem.c
> +++ b/gdb/symfile-mem.c
> @@ -214,8 +214,7 @@ add_vsyscall_page (struct target_ops *target, int from_tty)
>  	  format should fix this.  */
>  	{
>  	  warning (_("Could not load vsyscall page "
> -		     "because no executable was specified\n"
> -		     "try using the \"file\" command first."));
> +		     "because no executable was specified"));
>  	  return;

This bit is OK.  Please split them out and push them.

Please don't push the other hunks in.  I think we'll need more
discussion on those and I'd rather if we found some other way
to address this, if we must.

Thanks,
Pedro Alves
  
Jan Kratochvil April 5, 2016, 5:14 p.m. UTC | #4
On Tue, 05 Apr 2016 18:32:05 +0200, Pedro Alves wrote:
> On 03/23/2016 09:15 PM, Jan Kratochvil wrote:
> > Sending packet: $qXfer:exec-file:read:67:0,fff#f7...Packet received: l/root/redhat/threadit
> > Reading /root/redhat/threadit from remote target...
> > Sending packet: $vFile:open:2f726f6f742f7265646861742f7468726561646974,0,0#7e...Packet received: F5
> > Sending packet: $vFile:pread:5,3fff,0#98...Packet received: F27f8;\177ELF\002\001\001\000
> > 
> > Just stating that, nothing interesting.
> 
> That'd assume that there's a structured elf on the target, while on bare
> metal, you don't have that; no sections, no segments, etc.  Nothing other
> than unstructured raw memory, much like what the "dump memory" would
> give you.

Yes, reading raw memory without structure is not useful as an exec-file (I see
now gdbserver protocol "qXfer:exec-file:read:" maps to the GDB command "file"
and not to the GDB command "exec-file") which serves mostly as a symbol file.
But for example vDSO is a memory readable ELF file.  I remember some other
ROMs which also had structured format, parseable by BFD but not really
containing a filesystem. Amiga ROM contained a list of libraries, each one
with some PLTs etc.


Jan
  

Patch

diff --git a/gdb/exec.c b/gdb/exec.c
index 90811c0..a10ab9b 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -151,7 +151,13 @@  exec_file_locate_attach (int pid, int from_tty)
   /* Try to determine a filename from the process itself.  */
   exec_file = target_pid_to_exec_file (pid);
   if (exec_file == NULL)
-    return;
+    {
+      warning (_("No executable has been specified and target does not "
+		 "support\n"
+		 "determining executable automatically.  "
+		 "Try using the \"file\" command."));
+      return;
+    }
 
   /* If gdb_sysroot is not empty and the discovered filename
      is absolute then prefix the filename with gdb_sysroot.  */
diff --git a/gdb/remote.c b/gdb/remote.c
index af0a08a..4e44ffd 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1311,7 +1311,10 @@  packet_ok (const char *buf, struct packet_config *config)
     internal_error (__FILE__, __LINE__,
 		    _("packet_ok: attempt to use a disabled packet"));
 
-  result = packet_check_result (buf);
+  if (strcmp (buf, "OK") == 0 && startswith (config->name, "vFile:"))
+    result = PACKET_UNKNOWN;
+  else
+    result = packet_check_result (buf);
   switch (result)
     {
     case PACKET_OK:
@@ -12977,7 +12980,12 @@  remote_pid_to_exec_file (struct target_ops *self, int pid)
   char *annex = NULL;
 
   if (packet_support (PACKET_qXfer_exec_file) != PACKET_ENABLE)
-    return NULL;
+    {
+      warning (_("Remote gdbserver does not support determining executable "
+		 "automatically.\n"
+		 "FSF gdbserver version 7.10 or later would support that."));
+      return NULL;
+    }
 
   if (filename != NULL)
     xfree (filename);
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index 8eb5176..79739a6 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -214,8 +214,7 @@  add_vsyscall_page (struct target_ops *target, int from_tty)
 	  format should fix this.  */
 	{
 	  warning (_("Could not load vsyscall page "
-		     "because no executable was specified\n"
-		     "try using the \"file\" command first."));
+		     "because no executable was specified"));
 	  return;
 	}
       args.bfd = bfd;