This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc][2/4][rfa/doc] Support for TARGET_OBJECT_PROC


Hello,

this patch actually adds the TARGET_OBJECT_PROC object type and all code
required to access such objects on native and remote targets.

The "annex" specifies the name of the /proc file (in the /proc directory
associated with the current inferior process) that is to be accessed.

Both read and write access to /proc files is supported (even though
currently, there is no actual user of the write capability).  The contents
of the target object are (usually, except for symbolic links) simply the
contents of the /proc file in question.

Note that /proc files that are symbolic links are handled specially:
a read request returns the link path name, not the contents of the
linked-to file, and write requests are refused.

The actual implementation is in common/linux-procfs.c, shared between
the linux-nat.c and gdbserver/linux-low.c users.

Bye,
Ulrich



ChangeLog:

	* common/linux-procfs.c: Include <sys/param.h>.
	(linux_common_xfer_proc): New function.
	* common/linux-procfs.h (linux_common_xfer_proc): Add prototype.

	* target.h (enum target_object): Add TARGET_OBJECT_PROC.
	* linux-nat.c (linux_proc_xfer_proc): New function.
	(linux_xfer_partial): Use it to handle TARGET_OBJECT_PROC.

	* remote.c (PACKET_qXfer_proc_read): New enum value.
	(PACKET_qXfer_proc_write): Likewise.
	(remote_protocol_features): Add qXfer:proc:read and qXfer:proc:write
	packet types.
	(_initialize_remote): Likewise.
	(remote_xfer_partial): Handle TARGET_OBJECT_PROC.

doc/ChangeLog:

	* gdb.texinfo (General Query Packets): Document qXfer:proc:read
	and qXfer:proc:write packets and mention them under qSupported.

gdbserver/ChangeLog:

	* server.c (handle_qxfer_proc): New function.
	(qxfer_packets): Install it.
	(handle_query): Handle qXfer:proc:read and qXfer:proc:write.
	* target.h (struct target_ops): Add qxfer_proc.
	* linux-low.c (linux_qxfer_proc): New function.
	(linux_target_ops): Install it.


Index: gdb-head/gdb/target.h
===================================================================
--- gdb-head.orig/gdb/target.h
+++ gdb-head/gdb/target.h
@@ -243,6 +243,8 @@ enum target_object
   TARGET_OBJECT_AUXV,
   /* StackGhost cookie.  See "sparc-tdep.c".  */
   TARGET_OBJECT_WCOOKIE,
+  /* /proc file contents.  */
+  TARGET_OBJECT_PROC,
   /* Target memory map in XML format.  */
   TARGET_OBJECT_MEMORY_MAP,
   /* Flash memory.  This object can be used to write contents to
Index: gdb-head/gdb/common/linux-procfs.c
===================================================================
--- gdb-head.orig/gdb/common/linux-procfs.c
+++ gdb-head/gdb/common/linux-procfs.c
@@ -23,6 +23,7 @@
 #include "gdb_string.h"
 #endif
 
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -66,6 +67,64 @@ linux_proc_get_tgid (int lwpid)
   return tgid;
 }
 
+/* Implements the to_xfer_partial interface for the TARGET_OBJECT_PROC
+   object type, using the /proc file system.  */
+LONGEST
+linux_common_xfer_proc (long pid, const char *annex, gdb_byte *readbuf,
+			const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  char buf[128];
+  int fd = 0;
+  LONGEST ret = 0;
+  struct stat st;
+
+  if (!writebuf && !readbuf)
+    return -1;
+
+  snprintf (buf, sizeof buf, "/proc/%ld/%s", pid, annex);
+
+  /* If the /proc file is a symbolic link, we access its link path.  */
+  if (lstat (buf, &st) == 0 && S_ISLNK (st.st_mode))
+    {
+      char *name;
+
+      if (writebuf)
+	return -1;
+
+      name = xmalloc (MAXPATHLEN);
+      ret = readlink (buf, name, MAXPATHLEN);
+      if (ret >= offset)
+	{
+	  ret -= offset;
+	  if (ret > len)
+	    ret = len;
+
+	  memcpy (readbuf, name + offset, ret);
+	}
+
+      xfree (name);
+      return ret;
+    }
+
+  fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
+  if (fd <= 0)
+    return -1;
+
+  if (offset != 0
+      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
+    {
+      close (fd);
+      return 0;
+    }
+
+  if (writebuf)
+    ret = write (fd, writebuf, (size_t) len);
+  else
+    ret = read (fd, readbuf, (size_t) len);
+
+  close (fd);
+  return ret;
+}
 
 /* Enumerate spufs IDs for process PID.  */
 static LONGEST
Index: gdb-head/gdb/common/linux-procfs.h
===================================================================
--- gdb-head.orig/gdb/common/linux-procfs.h
+++ gdb-head/gdb/common/linux-procfs.h
@@ -26,6 +26,11 @@
 
 extern int linux_proc_get_tgid (int lwpid);
 
+extern LONGEST linux_common_xfer_proc (long pid, const char *annex,
+				       gdb_byte *readbuf,
+				       const gdb_byte *writebuf,
+				       ULONGEST offset, LONGEST len);
+
 extern LONGEST linux_common_xfer_spu (long pid, const char *annex,
 				      gdb_byte *readbuf,
 				      const gdb_byte *writebuf,
Index: gdb-head/gdb/gdbserver/linux-low.c
===================================================================
--- gdb-head.orig/gdb/gdbserver/linux-low.c
+++ gdb-head/gdb/gdbserver/linux-low.c
@@ -4675,6 +4675,17 @@ linux_supports_disable_randomization (vo
 #endif
 }
 
+/* Implements the to_xfer_partial interface for the TARGET_OBJECT_PROC
+   object type, using the /proc file system.  */
+static int
+linux_qxfer_proc (const char *annex, unsigned char *readbuf,
+		  unsigned const char *writebuf,
+		  CORE_ADDR offset, int len)
+{
+  long pid = lwpid_of (get_thread_lwp (current_inferior));
+  return linux_common_xfer_proc (pid, annex, readbuf, writebuf, offset, len);
+}
+
 /* Implements the to_xfer_partial interface for the TARGET_OBJECT_SPU
    object type, using the /proc file system.  */
 static int
@@ -4938,6 +4949,7 @@ static struct target_ops linux_target_op
   linux_emit_ops,
   linux_supports_disable_randomization,
   linux_get_min_fast_tracepoint_insn_len,
+  linux_qxfer_proc,
 };
 
 static void
Index: gdb-head/gdb/gdbserver/server.c
===================================================================
--- gdb-head.orig/gdb/gdbserver/server.c
+++ gdb-head/gdb/gdbserver/server.c
@@ -1021,6 +1021,22 @@ handle_qxfer_siginfo (const char *annex,
   return (*the_target->qxfer_siginfo) (annex, readbuf, writebuf, offset, len);
 }
 
+/* Handle qXfer:proc:read and qXfer:proc:write.  */
+
+static int
+handle_qxfer_proc (const char *annex,
+		   gdb_byte *readbuf, const gdb_byte *writebuf,
+		   ULONGEST offset, LONGEST len)
+{
+  if (the_target->qxfer_proc == NULL)
+    return -2;
+
+  if (!target_running ())
+    return -1;
+
+  return (*the_target->qxfer_proc) (annex, readbuf, writebuf, offset, len);
+}
+
 /* Handle qXfer:spu:read and qXfer:spu:write.  */
 
 static int
@@ -1217,6 +1233,7 @@ static const struct qxfer qxfer_packets[
     { "features", handle_qxfer_features },
     { "libraries", handle_qxfer_libraries },
     { "osdata", handle_qxfer_osdata },
+    { "proc", handle_qxfer_proc },
     { "siginfo", handle_qxfer_siginfo },
     { "spu", handle_qxfer_spu },
     { "statictrace", handle_qxfer_statictrace },
@@ -1543,6 +1560,9 @@ handle_query (char *own_buf, int packet_
       if (the_target->read_auxv != NULL)
 	strcat (own_buf, ";qXfer:auxv:read+");
 
+      if (the_target->qxfer_proc != NULL)
+	strcat (own_buf, ";qXfer:proc:read+;qXfer:proc:write+");
+
       if (the_target->qxfer_spu != NULL)
 	strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+");
 
Index: gdb-head/gdb/gdbserver/target.h
===================================================================
--- gdb-head.orig/gdb/gdbserver/target.h
+++ gdb-head/gdb/gdbserver/target.h
@@ -390,6 +390,10 @@ struct target_ops
   /* Return the minimum length of an instruction that can be safely overwritten
      for use as a fast tracepoint.  */
   int (*get_min_fast_tracepoint_insn_len) (void);
+
+   /* Read/Write from/to /proc using qXfer packets.  */
+  int (*qxfer_proc) (const char *annex, unsigned char *readbuf,
+		     unsigned const char *writebuf, CORE_ADDR offset, int len);
 };
 
 extern struct target_ops *the_target;
Index: gdb-head/gdb/linux-nat.c
===================================================================
--- gdb-head.orig/gdb/linux-nat.c
+++ gdb-head/gdb/linux-nat.c
@@ -5128,6 +5128,20 @@ linux_proc_xfer_partial (struct target_o
   return ret;
 }
 
+/* Implement the to_xfer_partial interface for the TARGET_OBJECT_PROC
+   object type, using the /proc file system.  */
+static LONGEST
+linux_proc_xfer_proc (struct target_ops *ops, enum target_object object,
+		      const char *annex, gdb_byte *readbuf,
+		      const gdb_byte *writebuf,
+		      ULONGEST offset, LONGEST len)
+{
+  gdb_assert (object == TARGET_OBJECT_PROC);
+
+  return linux_common_xfer_proc (PIDGET (inferior_ptid), annex,
+				 readbuf, writebuf, offset, len);
+}
+
 /* Implement the to_xfer_partial interface for the TARGET_OBJECT_SPU
    object type, using the /proc file system.  */
 static LONGEST
@@ -5251,6 +5265,10 @@ linux_xfer_partial (struct target_ops *o
     return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
                                offset, len);
 
+  if (object == TARGET_OBJECT_PROC)
+    return linux_proc_xfer_proc (ops, object, annex, readbuf, writebuf,
+				 offset, len);
+
   if (object == TARGET_OBJECT_SPU)
     return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf,
 				offset, len);
Index: gdb-head/gdb/remote.c
===================================================================
--- gdb-head.orig/gdb/remote.c
+++ gdb-head/gdb/remote.c
@@ -1244,6 +1244,8 @@ enum {
   PACKET_qXfer_features,
   PACKET_qXfer_libraries,
   PACKET_qXfer_memory_map,
+  PACKET_qXfer_proc_read,
+  PACKET_qXfer_proc_write,
   PACKET_qXfer_spu_read,
   PACKET_qXfer_spu_write,
   PACKET_qXfer_osdata,
@@ -3750,6 +3752,10 @@ static struct protocol_feature remote_pr
     PACKET_qXfer_libraries },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_memory_map },
+  { "qXfer:proc:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_proc_read },
+  { "qXfer:proc:write", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_proc_write },
   { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_spu_read },
   { "qXfer:spu:write", PACKET_DISABLE, remote_supported_packet,
@@ -8273,6 +8279,21 @@ remote_xfer_partial (struct target_ops *
 	return -1;
     }
 
+  /* Handle /proc file contents using qxfer packets.  */
+  if (object == TARGET_OBJECT_PROC)
+    {
+      if (readbuf)
+	return remote_read_qxfer (ops, "proc", annex,
+				  readbuf, offset, len,
+				  &remote_protocol_packets
+				    [PACKET_qXfer_proc_read]);
+      else
+	return remote_write_qxfer (ops, "proc", annex,
+				   writebuf, offset, len,
+				   &remote_protocol_packets
+				     [PACKET_qXfer_proc_write]);
+    }
+
   /* Handle SPU memory using qxfer packets.  */
   if (object == TARGET_OBJECT_SPU)
     {
@@ -11081,6 +11102,12 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
 			 "qXfer:memory-map:read", "memory-map", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_proc_read],
+                         "qXfer:proc:read", "read-proc-object", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_proc_write],
+                         "qXfer:proc:write", "write-proc-object", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_read],
                          "qXfer:spu:read", "read-spu-object", 0);
 
Index: gdb-head/gdb/doc/gdb.texinfo
===================================================================
--- gdb-head.orig/gdb/doc/gdb.texinfo
+++ gdb-head/gdb/doc/gdb.texinfo
@@ -17334,6 +17334,14 @@ are:
 @tab @code{qXfer:sdata:read}
 @tab @code{print $_sdata}
 
+@item @code{read-proc-object}
+@tab @code{qXfer:proc:read}
+@tab @code{info proc}
+
+@item @code{write-proc-object}
+@tab @code{qXfer:proc:write}
+@tab @code{info proc}
+
 @item @code{read-spu-object}
 @tab @code{qXfer:spu:read}
 @tab @code{info spu}
@@ -34863,6 +34871,16 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:proc:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
+@item @samp{qXfer:proc:write}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{qXfer:spu:read}
 @tab No
 @tab @samp{-}
@@ -34994,6 +35012,14 @@ The remote stub understands the @samp{qX
 The remote stub understands the @samp{qXfer:sdata:read} packet
 (@pxref{qXfer sdata read}).
 
+@item qXfer:proc:read
+The remote stub understands the @samp{qXfer:proc:read} packet
+(@pxref{qXfer proc read}).
+
+@item qXfer:proc:write
+The remote stub understands the @samp{qXfer:proc:write} packet
+(@pxref{qXfer proc write}).
+
 @item qXfer:spu:read
 The remote stub understands the @samp{qXfer:spu:read} packet
 (@pxref{qXfer spu read}).
@@ -35262,6 +35288,16 @@ This packet is not probed by default; th
 by supplying an appropriate @samp{qSupported} response
 (@pxref{qSupported}).
 
+@item qXfer:proc:read:@var{annex}:@var{offset},@var{length}
+@anchor{qXfer proc read}
+Read contents of a @code{/proc} file on the target system.  The
+annex specifies which file in the @code{/proc} directory of the
+current process to read.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:spu:read:@var{annex}:@var{offset},@var{length}
 @anchor{qXfer spu read}
 Read contents of an @code{spufs} file on the target system.  The
@@ -35365,6 +35401,15 @@ This packet is not probed by default; th
 by supplying an appropriate @samp{qSupported} response
 (@pxref{qSupported}).
 
+@item qXfer:proc:write:@var{annex}:@var{offset}:@var{data}@dots{}
+@anchor{qXfer proc write}
+Write @var{data} to a @code{/proc} file on the target system.  The
+annex specifies which file in the @code{/proc} directory of the
+current process to write.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
 @item qXfer:spu:write:@var{annex}:@var{offset}:@var{data}@dots{}
 @anchor{qXfer spu write}
 Write @var{data} to an @code{spufs} file on the target system.  The
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]