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][4/4] Implement remote "info proc" for Linux


Hello,

this patch now connects the pieces to implement remote "info proc",
at least on Linux.

It adds a new *gdbarch* info_proc callback in addition to the target
method.  This is used by the common infcmd.c implementation in
preference to the target method.

This is then used to move the Linux info_proc handler from a target
method in linux-nat.c to a gdbarch method in linux-tdep.c.  Note that
this requires somewhat of a rewrite, since the old code made a number
of Linux-specific assumptions (e.g. availability of "long long",
certain printf/scanf format string behaviour etc.).

To get at its data, the new handler uses target_read_stralloc on the
TARGET_OBJECT_PROC object with the appropriate annex.  Note that there
is a minor enhancement to target_read_stralloc as well: it now accepts
*trailing* NUL bytes even while continuing to warn if there are NUL
bytes actually *embedded* (i.e. followed by some non-NUL byte) in the
target object contents.

(Note that in principle, there is no reason why we couldn't move
the info_proc handler from native to target-dependent code for
procfs target as well; we could eliminate the target info_proc
method completely then.  But since we don't support gdbserver
on those targets, there is not much point in doing so.)

Bye,
Ulrich


ChangeLog:

	* gdbarch.sh (info_proc): New callback.
	* gdbarch.c, gdbarch.h: Regenerate.

	* infcmd.c (info_proc_cmd_1): Try gdbarch info_proc callback
	before falling back to the target info_proc callback.

	* linux-nat.c (linux_nat_info_proc): Remove.
	(linux_target_install_ops): No longer install it.

	* linux-tdep.c: Include <ctype.h>.
	(read_mapping): New function.
	(linux_info_proc): Likewise.
	(linux_init_abi): Install it.

	* target.c (target_read_stralloc): Accept trailing, but not
	embedded NUL bytes.


Index: gdb-head/gdb/gdbarch.c
===================================================================
--- gdb-head.orig/gdb/gdbarch.c
+++ gdb-head/gdb/gdbarch.c
@@ -272,6 +272,7 @@ struct gdbarch
   const char * solib_symbols_extension;
   int has_dos_based_file_system;
   gdbarch_gen_return_address_ftype *gen_return_address;
+  gdbarch_info_proc_ftype *info_proc;
 };
 
 
@@ -427,6 +428,7 @@ struct gdbarch startup_gdbarch =
   0,  /* solib_symbols_extension */
   0,  /* has_dos_based_file_system */
   default_gen_return_address,  /* gen_return_address */
+  0,  /* info_proc */
   /* startup_gdbarch() */
 };
 
@@ -715,6 +717,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of auto_wide_charset, invalid_p == 0 */
   /* Skip verify of has_dos_based_file_system, invalid_p == 0 */
   /* Skip verify of gen_return_address, invalid_p == 0 */
+  /* Skip verify of info_proc, has predicate.  */
   buf = ui_file_xstrdup (log, &length);
   make_cleanup (xfree, buf);
   if (length > 0)
@@ -1003,6 +1006,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: in_solib_return_trampoline = <%s>\n",
                       host_address_to_string (gdbarch->in_solib_return_trampoline));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_info_proc_p() = %d\n",
+                      gdbarch_info_proc_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: info_proc = <%s>\n",
+                      host_address_to_string (gdbarch->info_proc));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: inner_than = <%s>\n",
                       host_address_to_string (gdbarch->inner_than));
   fprintf_unfiltered (file,
@@ -3911,6 +3920,30 @@ set_gdbarch_gen_return_address (struct g
   gdbarch->gen_return_address = gen_return_address;
 }
 
+int
+gdbarch_info_proc_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->info_proc != NULL;
+}
+
+void
+gdbarch_info_proc (struct gdbarch *gdbarch, enum info_proc_what what)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->info_proc != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_info_proc called\n");
+  gdbarch->info_proc (gdbarch, what);
+}
+
+void
+set_gdbarch_info_proc (struct gdbarch *gdbarch,
+                       gdbarch_info_proc_ftype info_proc)
+{
+  gdbarch->info_proc = info_proc;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules.  */
Index: gdb-head/gdb/gdbarch.h
===================================================================
--- gdb-head.orig/gdb/gdbarch.h
+++ gdb-head/gdb/gdbarch.h
@@ -1031,6 +1031,14 @@ typedef void (gdbarch_gen_return_address
 extern void gdbarch_gen_return_address (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope);
 extern void set_gdbarch_gen_return_address (struct gdbarch *gdbarch, gdbarch_gen_return_address_ftype *gen_return_address);
 
+/* Print information about current process */
+
+extern int gdbarch_info_proc_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_info_proc_ftype) (struct gdbarch *gdbarch, enum info_proc_what what);
+extern void gdbarch_info_proc (struct gdbarch *gdbarch, enum info_proc_what what);
+extern void set_gdbarch_info_proc (struct gdbarch *gdbarch, gdbarch_info_proc_ftype *info_proc);
+
 /* Definition for an unknown syscall, used basically in error-cases.  */
 #define UNKNOWN_SYSCALL (-1)
 
Index: gdb-head/gdb/gdbarch.sh
===================================================================
--- gdb-head.orig/gdb/gdbarch.sh
+++ gdb-head/gdb/gdbarch.sh
@@ -831,6 +831,9 @@ v:int:has_dos_based_file_system:::0:0::0
 # places that the return address may be found.
 m:void:gen_return_address:struct agent_expr *ax, struct axs_value *value, CORE_ADDR scope:ax, value, scope::default_gen_return_address::0
 
+# Print information about current process
+M:void:info_proc:enum info_proc_what what:what
+
 EOF
 }
 
Index: gdb-head/gdb/infcmd.c
===================================================================
--- gdb-head.orig/gdb/infcmd.c
+++ gdb-head/gdb/infcmd.c
@@ -2787,6 +2787,7 @@ unset_command (char *args, int from_tty)
 static void
 info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty)
 {
+  struct gdbarch *gdbarch = get_current_arch ();
   long pid = PIDGET (inferior_ptid);
   long tid = 0;
 
@@ -2802,6 +2803,16 @@ info_proc_cmd_1 (char *args, enum info_p
   if (pid == 0)
     error (_("No current process: you must name one."));
 
+  if (gdbarch_info_proc_p (gdbarch))
+    {
+      if (pid != PIDGET (inferior_ptid) || tid != 0)
+	error (_("\"info proc\" does not support a PID argument "
+		 "on this platform."));
+
+      gdbarch_info_proc (gdbarch, what);
+      return;
+    }
+
   target_info_proc (ptid_build (pid, 0, tid), what);
 }
 
Index: gdb-head/gdb/linux-nat.c
===================================================================
--- gdb-head.orig/gdb/linux-nat.c
+++ gdb-head/gdb/linux-nat.c
@@ -4746,239 +4746,6 @@ linux_nat_make_corefile_notes (bfd *obfd
   return note_data;
 }
 
-/* Implement the "info proc" command.  */
-
-static void
-linux_nat_info_proc (struct target_ops *ops, ptid_t ptid,
-		     enum info_proc_what what)
-{
-  long pid = ptid_get_pid (ptid);
-  FILE *procfile;
-  char buffer[MAXPATHLEN];
-  char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
-  int cmdline_f = (what == IP_MINIMAL || what == IP_CMDLINE || what == IP_ALL);
-  int cwd_f = (what == IP_MINIMAL || what == IP_CWD || what == IP_ALL);
-  int exe_f = (what == IP_MINIMAL || what == IP_EXE || what == IP_ALL);
-  int mappings_f = (what == IP_MAPPINGS || what == IP_ALL);
-  int status_f = (what == IP_STATUS || what == IP_ALL);
-  int stat_f = (what == IP_STAT || what == IP_ALL);
-  struct stat dummy;
-
-  sprintf (fname1, "/proc/%ld", pid);
-  if (stat (fname1, &dummy) != 0)
-    error (_("No /proc directory: '%s'"), fname1);
-
-  printf_filtered (_("process %ld\n"), pid);
-  if (cmdline_f)
-    {
-      sprintf (fname1, "/proc/%ld/cmdline", pid);
-      if ((procfile = fopen (fname1, "r")) != NULL)
-	{
-	  struct cleanup *cleanup = make_cleanup_fclose (procfile);
-
-          if (fgets (buffer, sizeof (buffer), procfile))
-            printf_filtered ("cmdline = '%s'\n", buffer);
-          else
-            warning (_("unable to read '%s'"), fname1);
-	  do_cleanups (cleanup);
-	}
-      else
-	warning (_("unable to open /proc file '%s'"), fname1);
-    }
-  if (cwd_f)
-    {
-      sprintf (fname1, "/proc/%ld/cwd", pid);
-      memset (fname2, 0, sizeof (fname2));
-      if (readlink (fname1, fname2, sizeof (fname2)) > 0)
-	printf_filtered ("cwd = '%s'\n", fname2);
-      else
-	warning (_("unable to read link '%s'"), fname1);
-    }
-  if (exe_f)
-    {
-      sprintf (fname1, "/proc/%ld/exe", pid);
-      memset (fname2, 0, sizeof (fname2));
-      if (readlink (fname1, fname2, sizeof (fname2)) > 0)
-	printf_filtered ("exe = '%s'\n", fname2);
-      else
-	warning (_("unable to read link '%s'"), fname1);
-    }
-  if (mappings_f)
-    {
-      sprintf (fname1, "/proc/%ld/maps", pid);
-      if ((procfile = fopen (fname1, "r")) != NULL)
-	{
-	  long long addr, endaddr, size, offset, inode;
-	  char permissions[8], device[8], filename[MAXPATHLEN];
-	  struct cleanup *cleanup;
-
-	  cleanup = make_cleanup_fclose (procfile);
-	  printf_filtered (_("Mapped address spaces:\n\n"));
-	  if (gdbarch_addr_bit (target_gdbarch) == 32)
-	    {
-	      printf_filtered ("\t%10s %10s %10s %10s %7s\n",
-			   "Start Addr",
-			   "  End Addr",
-			   "      Size", "    Offset", "objfile");
-            }
-	  else
-            {
-	      printf_filtered ("  %18s %18s %10s %10s %7s\n",
-			   "Start Addr",
-			   "  End Addr",
-			   "      Size", "    Offset", "objfile");
-	    }
-
-	  while (read_mapping (procfile, &addr, &endaddr, &permissions[0],
-			       &offset, &device[0], &inode, &filename[0]))
-	    {
-	      size = endaddr - addr;
-
-	      /* FIXME: carlton/2003-08-27: Maybe the printf_filtered
-		 calls here (and possibly above) should be abstracted
-		 out into their own functions?  Andrew suggests using
-		 a generic local_address_string instead to print out
-		 the addresses; that makes sense to me, too.  */
-
-	      if (gdbarch_addr_bit (target_gdbarch) == 32)
-	        {
-	          printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
-			       (unsigned long) addr,	/* FIXME: pr_addr */
-			       (unsigned long) endaddr,
-			       (int) size,
-			       (unsigned int) offset,
-			       filename[0] ? filename : "");
-		}
-	      else
-	        {
-	          printf_filtered ("  %#18lx %#18lx %#10x %#10x %7s\n",
-			       (unsigned long) addr,	/* FIXME: pr_addr */
-			       (unsigned long) endaddr,
-			       (int) size,
-			       (unsigned int) offset,
-			       filename[0] ? filename : "");
-	        }
-	    }
-
-	  do_cleanups (cleanup);
-	}
-      else
-	warning (_("unable to open /proc file '%s'"), fname1);
-    }
-  if (status_f)
-    {
-      sprintf (fname1, "/proc/%ld/status", pid);
-      if ((procfile = fopen (fname1, "r")) != NULL)
-	{
-	  struct cleanup *cleanup = make_cleanup_fclose (procfile);
-
-	  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
-	    puts_filtered (buffer);
-	  do_cleanups (cleanup);
-	}
-      else
-	warning (_("unable to open /proc file '%s'"), fname1);
-    }
-  if (stat_f)
-    {
-      sprintf (fname1, "/proc/%ld/stat", pid);
-      if ((procfile = fopen (fname1, "r")) != NULL)
-	{
-	  int itmp;
-	  char ctmp;
-	  long ltmp;
-	  struct cleanup *cleanup = make_cleanup_fclose (procfile);
-
-	  if (fscanf (procfile, "%d ", &itmp) > 0)
-	    printf_filtered (_("Process: %d\n"), itmp);
-	  if (fscanf (procfile, "(%[^)]) ", &buffer[0]) > 0)
-	    printf_filtered (_("Exec file: %s\n"), buffer);
-	  if (fscanf (procfile, "%c ", &ctmp) > 0)
-	    printf_filtered (_("State: %c\n"), ctmp);
-	  if (fscanf (procfile, "%d ", &itmp) > 0)
-	    printf_filtered (_("Parent process: %d\n"), itmp);
-	  if (fscanf (procfile, "%d ", &itmp) > 0)
-	    printf_filtered (_("Process group: %d\n"), itmp);
-	  if (fscanf (procfile, "%d ", &itmp) > 0)
-	    printf_filtered (_("Session id: %d\n"), itmp);
-	  if (fscanf (procfile, "%d ", &itmp) > 0)
-	    printf_filtered (_("TTY: %d\n"), itmp);
-	  if (fscanf (procfile, "%d ", &itmp) > 0)
-	    printf_filtered (_("TTY owner process group: %d\n"), itmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Flags: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Minor faults (no memory page): %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Minor faults, children: %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Major faults (memory page faults): %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Major faults, children: %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("utime: %ld\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("stime: %ld\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("utime, children: %ld\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("stime, children: %ld\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("jiffies remaining in current "
-			       "time slice: %ld\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("'nice' value: %ld\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("jiffies until next timeout: %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("jiffies until next SIGALRM: %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("start time (jiffies since "
-			       "system boot): %ld\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Virtual memory size: %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Resident set size: %lu\n"),
-			     (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("rlim: %lu\n"), (unsigned long) ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Start of text: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("End of text: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)
-	    printf_filtered (_("Start of stack: 0x%lx\n"), ltmp);
-#if 0	/* Don't know how architecture-dependent the rest is...
-	   Anyway the signal bitmap info is available from "status".  */
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)	/* FIXME arch?  */
-	    printf_filtered (_("Kernel stack pointer: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)	/* FIXME arch?  */
-	    printf_filtered (_("Kernel instr pointer: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("Pending signals bitmap: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("Blocked signals bitmap: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("Ignored signals bitmap: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%ld ", &ltmp) > 0)
-	    printf_filtered (_("Catched signals bitmap: 0x%lx\n"), ltmp);
-	  if (fscanf (procfile, "%lu ", &ltmp) > 0)	/* FIXME arch?  */
-	    printf_filtered (_("wchan (system call): 0x%lx\n"), ltmp);
-#endif
-	  do_cleanups (cleanup);
-	}
-      else
-	warning (_("unable to open /proc file '%s'"), fname1);
-    }
-}
-
 /* Implement the to_xfer_partial interface for memory reads using the /proc
    filesystem.  Because we can use a single read() call for /proc, this
    can be much more efficient than banging away at PTRACE_PEEKTEXT,
@@ -5212,7 +4979,6 @@ linux_target_install_ops (struct target_
   t->to_follow_fork = linux_child_follow_fork;
   t->to_find_memory_regions = linux_nat_find_memory_regions;
   t->to_make_corefile_notes = linux_nat_make_corefile_notes;
-  t->to_info_proc = linux_nat_info_proc;
 
   super_xfer_partial = t->to_xfer_partial;
   t->to_xfer_partial = linux_xfer_partial;
Index: gdb-head/gdb/linux-tdep.c
===================================================================
--- gdb-head.orig/gdb/linux-tdep.c
+++ gdb-head/gdb/linux-tdep.c
@@ -25,6 +25,8 @@
 #include "elf/common.h"
 #include "inferior.h"
 
+#include <ctype.h>
+
 static struct gdbarch_data *linux_gdbarch_data_handle;
 
 struct linux_gdbarch_data
@@ -196,6 +198,311 @@ linux_core_pid_to_str (struct gdbarch *g
   return normal_pid_to_str (ptid);
 }
 
+/* Service function for corefiles and info proc.  */
+
+static void
+read_mapping (const char *line,
+	      ULONGEST *addr, ULONGEST *endaddr,
+	      const char **permissions, size_t *permissions_len,
+	      ULONGEST *offset,
+              const char **device, size_t *device_len,
+	      ULONGEST *inode,
+	      const char **filename)
+{
+  const char *p = line;
+
+  *addr = strtoulst (p, &p, 16);
+  if (*p == '-')
+    p++;
+  *endaddr = strtoulst (p, &p, 16);
+
+  while (*p && isspace (*p))
+    p++;
+  *permissions = p;
+  while (*p && !isspace (*p))
+    p++;
+  *permissions_len = *permissions - p;
+
+  *offset = strtoulst (p, &p, 16);
+
+  while (*p && isspace (*p))
+    p++;
+  *device = p;
+  while (*p && !isspace (*p))
+    p++;
+  *device_len = *device - p;
+
+  *inode = strtoulst (p, &p, 10);
+
+  while (*p && isspace (*p))
+    p++;
+  *filename = p;
+}
+
+/* Implement the "info proc" command.  */
+
+static void
+linux_info_proc (struct gdbarch *gdbarch, enum info_proc_what what)
+{
+  int cmdline_f = (what == IP_MINIMAL || what == IP_CMDLINE || what == IP_ALL);
+  int cwd_f = (what == IP_MINIMAL || what == IP_CWD || what == IP_ALL);
+  int exe_f = (what == IP_MINIMAL || what == IP_EXE || what == IP_ALL);
+  int mappings_f = (what == IP_MAPPINGS || what == IP_ALL);
+  int status_f = (what == IP_STATUS || what == IP_ALL);
+  int stat_f = (what == IP_STAT || what == IP_ALL);
+  LONGEST len;
+  gdb_byte *data;
+
+  printf_filtered (_("process %d\n"), PIDGET (inferior_ptid));
+  if (cmdline_f)
+    {
+      data = target_read_stralloc (&current_target, TARGET_OBJECT_PROC,
+				   "cmdline");
+      if (data)
+	{
+	  struct cleanup *cleanup = make_cleanup (xfree, data);
+          printf_filtered ("cmdline = '%s'\n", data);
+	  do_cleanups (cleanup);
+	}
+      else
+	warning (_("unable to read /proc file \"cmdline\""));
+    }
+  if (cwd_f)
+    {
+      data = target_read_stralloc (&current_target, TARGET_OBJECT_PROC,
+				   "cwd");
+      if (data)
+	{
+	  struct cleanup *cleanup = make_cleanup (xfree, data);
+          printf_filtered ("cwd = '%s'\n", data);
+	  do_cleanups (cleanup);
+	}
+      else
+	warning (_("unable to read /proc file \"cwd\""));
+    }
+  if (exe_f)
+    {
+      data = target_read_stralloc (&current_target, TARGET_OBJECT_PROC,
+				   "exe");
+      if (data)
+	{
+	  struct cleanup *cleanup = make_cleanup (xfree, data);
+          printf_filtered ("exe = '%s'\n", data);
+	  do_cleanups (cleanup);
+	}
+      else
+	warning (_("unable to read /proc file \"exe\""));
+    }
+  if (mappings_f)
+    {
+      data = target_read_stralloc (&current_target, TARGET_OBJECT_PROC,
+				   "maps");
+      if (data)
+	{
+	  struct cleanup *cleanup = make_cleanup (xfree, data);
+	  char *line;
+
+	  printf_filtered (_("Mapped address spaces:\n\n"));
+	  if (gdbarch_addr_bit (gdbarch) == 32)
+	    {
+	      printf_filtered ("\t%10s %10s %10s %10s %s\n",
+			   "Start Addr",
+			   "  End Addr",
+			   "      Size", "    Offset", "objfile");
+            }
+	  else
+            {
+	      printf_filtered ("  %18s %18s %10s %10s %s\n",
+			   "Start Addr",
+			   "  End Addr",
+			   "      Size", "    Offset", "objfile");
+	    }
+
+	  for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n"))
+	    {
+	      ULONGEST addr, endaddr, offset, inode;
+	      const char *permissions, *device, *filename;
+	      size_t permissions_len, device_len;
+
+	      read_mapping (line, &addr, &endaddr,
+			    &permissions, &permissions_len,
+			    &offset, &device, &device_len,
+			    &inode, &filename);
+
+	      if (gdbarch_addr_bit (gdbarch) == 32)
+	        {
+	          printf_filtered ("\t%10s %10s %10s %10s %s\n",
+				   paddress (gdbarch, addr),
+				   paddress (gdbarch, endaddr),
+				   hex_string (endaddr - addr),
+				   hex_string (offset),
+				   *filename? filename : "");
+		}
+	      else
+	        {
+	          printf_filtered ("  %18s %18s %10s %10s %s\n",
+				   paddress (gdbarch, addr),
+				   paddress (gdbarch, endaddr),
+				   hex_string (endaddr - addr),
+				   hex_string (offset),
+				   *filename? filename : "");
+	        }
+	    }
+
+	  do_cleanups (cleanup);
+	}
+      else
+	warning (_("unable to read /proc file \"maps\""));
+    }
+  if (status_f)
+    {
+      data = target_read_stralloc (&current_target, TARGET_OBJECT_PROC,
+				   "status");
+      if (data)
+	{
+	  struct cleanup *cleanup = make_cleanup (xfree, data);
+          puts_filtered (data);
+	  do_cleanups (cleanup);
+	}
+      else
+	warning (_("unable to read /proc file \"status\""));
+    }
+  if (stat_f)
+    {
+      data = target_read_stralloc (&current_target, TARGET_OBJECT_PROC,
+				   "stat");
+      if (data)
+	{
+	  struct cleanup *cleanup = make_cleanup (xfree, data);
+	  const char *p = data;
+	  const char *ep;
+	  ULONGEST val;
+
+	  printf_filtered (_("Process: %s\n"),
+			   pulongest (strtoulst (p, &p, 10)));
+
+	  while (*p && isspace (*p))
+	    p++;
+	  if (*p == '(' && (ep = strchr (p, ')')) != NULL)
+	    {
+	      printf_filtered ("Exec file: %.*s\n", (int) (ep - p - 1), p + 1);
+	      p = ep + 1;
+	    }
+
+	  while (*p && isspace (*p))
+	    p++;
+	  if (*p)
+	    printf_filtered (_("State: %c\n"), *p++);
+
+	  if (*p)
+	    printf_filtered (_("Parent process: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Process group: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Session id: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("TTY: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("TTY owner process group: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+
+	  if (*p)
+	    printf_filtered (_("Flags: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Minor faults (no memory page): %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Minor faults, children: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Major faults (memory page faults): %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Major faults, children: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("utime: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("stime: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("utime, children: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("stime, children: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("jiffies remaining in current "
+			       "time slice: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("'nice' value: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("jiffies until next timeout: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("jiffies until next SIGALRM: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("start time (jiffies since "
+			       "system boot): %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Virtual memory size: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Resident set size: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("rlim: %s\n"),
+			     pulongest (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Start of text: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("End of text: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Start of stack: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+#if 0	/* Don't know how architecture-dependent the rest is...
+	   Anyway the signal bitmap info is available from "status".  */
+	  if (*p)
+	    printf_filtered (_("Kernel stack pointer: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Kernel instr pointer: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Pending signals bitmap: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Blocked signals bitmap: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Ignored signals bitmap: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("Catched signals bitmap: %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+	  if (*p)
+	    printf_filtered (_("wchan (system call): %s\n"),
+			     hex_string (strtoulst (p, &p, 10)));
+#endif
+	  do_cleanups (cleanup);
+	}
+      else
+	warning (_("unable to read /proc file \"stat\""));
+    }
+}
+
 /* To be called from the various GDB_OSABI_LINUX handlers for the
    various GNU/Linux architectures and machine types.  */
 
@@ -203,6 +510,7 @@ void
 linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   set_gdbarch_core_pid_to_str (gdbarch, linux_core_pid_to_str);
+  set_gdbarch_info_proc (gdbarch, linux_info_proc);
 }
 
 void
Index: gdb-head/gdb/target.c
===================================================================
--- gdb-head.orig/gdb/target.c
+++ gdb-head/gdb/target.c
@@ -2297,7 +2297,7 @@ target_read_stralloc (struct target_ops 
 		      const char *annex)
 {
   gdb_byte *buffer;
-  LONGEST transferred;
+  LONGEST i, transferred;
 
   transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
 
@@ -2308,10 +2308,16 @@ target_read_stralloc (struct target_ops 
     return xstrdup ("");
 
   buffer[transferred] = 0;
-  if (strlen (buffer) < transferred)
-    warning (_("target object %d, annex %s, "
-	       "contained unexpected null characters"),
-	     (int) object, annex ? annex : "(none)");
+
+  /* Check for embedded NUL bytes; but allow trailing NULs.  */
+  for (i = strlen (buffer); i < transferred; i++)
+    if (buffer[i] != 0)
+      {
+	warning (_("target object %d, annex %s, "
+		   "contained unexpected null characters"),
+		 (int) object, annex ? annex : "(none)");
+	break;
+      }
 
   return (char *) buffer;
 }
-- 
  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]