This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfc][4/4] Implement remote "info proc" for Linux
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 1 Dec 2011 20:41:11 +0100 (CET)
- Subject: [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 ", <mp) > 0)
- printf_filtered (_("Flags: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Minor faults (no memory page): %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Minor faults, children: %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Major faults (memory page faults): %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Major faults, children: %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("utime: %ld\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("stime: %ld\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("utime, children: %ld\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("stime, children: %ld\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("jiffies remaining in current "
- "time slice: %ld\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("'nice' value: %ld\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("jiffies until next timeout: %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("jiffies until next SIGALRM: %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("start time (jiffies since "
- "system boot): %ld\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Virtual memory size: %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Resident set size: %lu\n"),
- (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("rlim: %lu\n"), (unsigned long) ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("Start of text: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0)
- printf_filtered (_("End of text: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 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 ", <mp) > 0) /* FIXME arch? */
- printf_filtered (_("Kernel stack pointer: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 0) /* FIXME arch? */
- printf_filtered (_("Kernel instr pointer: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("Pending signals bitmap: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("Blocked signals bitmap: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("Ignored signals bitmap: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%ld ", <mp) > 0)
- printf_filtered (_("Catched signals bitmap: 0x%lx\n"), ltmp);
- if (fscanf (procfile, "%lu ", <mp) > 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 (¤t_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 (¤t_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 (¤t_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 (¤t_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 (¤t_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 (¤t_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