From 2bf543a6e7194f487a2a939905ae14e8dff932e9 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Tue, 15 Jan 2002 20:10:55 +0000 Subject: 2002-01-10 Michael Snyder * linux-proc.c: Add "info proc" command, a la procfs.c. (read_mapping): New function, abstract and re-use code. (linux_find_memory_regions): Use new func read_mapping. (linux_info_proc_cmd): New function, implement "info proc". (_initialize_linux_proc): Add new command "info proc". --- gdb/ChangeLog | 10 ++ gdb/linux-proc.c | 362 +++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 334 insertions(+), 38 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a36e315..bbe9edf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ +2002-01-10 Michael Snyder + + * linux-proc.c: Add "info proc" command, a la procfs.c. + (read_mapping): New function, abstract and re-use code. + (linux_find_memory_regions): Use new func read_mapping. + (linux_info_proc_cmd): New function, implement "info proc". + (_initialize_linux_proc): Add new command "info proc". + 2002-01-15 Michael Snyder + * NEWS: Add item for new 'gcore' command. + * symfile.c (generic_load): Use bfd_map_over_sections method instead of manipulating bfd structure members directly. (add_section_size_callback): New function, bfd sections callback diff --git a/gdb/linux-proc.c b/gdb/linux-proc.c index 666240f..8877d06 100644 --- a/gdb/linux-proc.c +++ b/gdb/linux-proc.c @@ -21,11 +21,14 @@ #include "defs.h" #include "inferior.h" #include /* for MAXPATHLEN */ -#include +#include /* for elf_gregset etc. */ +#include /* for struct stat */ +#include /* for isdigit */ #include "gregset.h" /* for gregset */ #include "gdbcore.h" /* for get_exec_file */ #include "gdbthread.h" /* for struct thread_info etc. */ -#include "elf-bfd.h" +#include "elf-bfd.h" /* for elfcore_write_* */ +#include "cli/cli-decode.h" /* for add_info */ /* Function: child_pid_to_exec_file * @@ -52,6 +55,36 @@ child_pid_to_exec_file (int pid) return name1; } +/* Function: read_mappings + * + * Service function for corefiles and info proc. + */ + +static int +read_mapping (FILE *mapfile, + long long *addr, + long long *endaddr, + char *permissions, + long long *offset, + char *device, + long long *inode, + char *filename) +{ + int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx", + addr, endaddr, permissions, offset, device, inode); + + if (ret > 0 && ret != EOF && *inode != 0) + { + ret += fscanf (mapfile, "%s\n", filename); + } + else + { + filename[0] = '\0'; /* no filename */ + fscanf (mapfile, "\n"); + } + return (ret != 0 && ret != EOF); +} + /* Function: linux_find_memory_regions * * Fills the "to_find_memory_regions" target vector. @@ -66,42 +99,32 @@ linux_find_memory_regions (int (*func) (CORE_ADDR, void *obfd) { long long pid = PIDGET (inferior_ptid); - char procfilename[MAXPATHLEN]; - FILE *procfile; + char mapsfilename[MAXPATHLEN]; + FILE *mapsfile; long long addr, endaddr, size, offset, inode; - char perms[8], dev[8], filename[MAXPATHLEN]; + char permissions[8], device[8], filename[MAXPATHLEN]; int read, write, exec; int ret; /* Compose the filename for the /proc memory map, and open it. */ - sprintf (procfilename, "/proc/%lld/maps", pid); - if ((procfile = fopen (procfilename, "r")) == NULL) - error ("Could not open %s\n", procfilename); + sprintf (mapsfilename, "/proc/%lld/maps", pid); + if ((mapsfile = fopen (mapsfilename, "r")) == NULL) + error ("Could not open %s\n", mapsfilename); if (info_verbose) fprintf_filtered (gdb_stdout, - "Reading memory regions from %s\n", procfilename); - - /* Read the first memory segment descriptor from the maps file. */ - ret = fscanf (procfile, "%llx-%llx %s %llx %s %llx", - &addr, &endaddr, perms, &offset, dev, &inode); - if (inode) - fscanf (procfile, " %s\n", filename); - else - { - filename[0] = '\0'; - fscanf (procfile, "\n"); - } + "Reading memory regions from %s\n", mapsfilename); /* Now iterate until end-of-file. */ - while (ret > 0 && ret != EOF) + while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0], + &offset, &device[0], &inode, &filename[0])) { size = endaddr - addr; /* Get the segment's permissions. */ - read = (strchr (perms, 'r') != 0); - write = (strchr (perms, 'w') != 0); - exec = (strchr (perms, 'x') != 0); + read = (strchr (permissions, 'r') != 0); + write = (strchr (permissions, 'w') != 0); + exec = (strchr (permissions, 'x') != 0); if (info_verbose) { @@ -119,21 +142,8 @@ linux_find_memory_regions (int (*func) (CORE_ADDR, /* Invoke the callback function to create the corefile segment. */ func (addr, size, read, write, exec, obfd); - - /* Read the next memory region. */ - filename[0] = '\0'; - ret = fscanf (procfile, "%llx-%llx %s %llx %s %llx", - &addr, &endaddr, perms, &offset, dev, &inode); - if (inode) - fscanf (procfile, " %s\n", filename); - else - { - filename[0] = '\0'; - fscanf (procfile, "\n"); - } } - - fclose (procfile); + fclose (mapsfile); return 0; } @@ -257,6 +267,273 @@ linux_make_note_section (bfd *obfd, int *note_size) return note_data; } +/* + * Function: linux_info_proc_cmd + * + * Implement the "info proc" command. + */ + +static void +linux_info_proc_cmd (char *args, int from_tty) +{ + long long pid = PIDGET (inferior_ptid); + FILE *procfile; + char **argv = NULL; + char buffer[MAXPATHLEN]; + char fname1[MAXPATHLEN], fname2[MAXPATHLEN]; + int cmdline_f = 1; + int cwd_f = 1; + int exe_f = 1; + int mappings_f = 0; + int environ_f = 0; + int status_f = 0; + int stat_f = 0; + int all = 0; + struct stat dummy; + + if (args) + { + /* Break up 'args' into an argv array. */ + if ((argv = buildargv (args)) == NULL) + nomem (0); + else + make_cleanup_freeargv (argv); + } + while (argv != NULL && *argv != NULL) + { + if (isdigit (argv[0][0])) + { + pid = strtoul (argv[0], NULL, 10); + } + else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0) + { + mappings_f = 1; + } + else if (strcmp (argv[0], "status") == 0) + { + status_f = 1; + } + else if (strcmp (argv[0], "stat") == 0) + { + stat_f = 1; + } + else if (strcmp (argv[0], "cmd") == 0) + { + cmdline_f = 1; + } + else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0) + { + exe_f = 1; + } + else if (strcmp (argv[0], "cwd") == 0) + { + cwd_f = 1; + } + else if (strncmp (argv[0], "all", strlen (argv[0])) == 0) + { + all = 1; + } + else + { + /* [...] (future options here) */ + } + argv++; + } + if (pid == 0) + error ("No current process: you must name one."); + + sprintf (fname1, "/proc/%lld", pid); + if (stat (fname1, &dummy) != 0) + error ("No /proc directory: '%s'", fname1); + + printf_filtered ("process %lld\n", pid); + if (cmdline_f || all) + { + sprintf (fname1, "/proc/%lld/cmdline", pid); + if ((procfile = fopen (fname1, "r")) > 0) + { + fgets (buffer, sizeof (buffer), procfile); + printf_filtered ("cmdline = '%s'\n", buffer); + fclose (procfile); + } + else + warning ("unable to open /proc file '%s'", fname1); + } + if (cwd_f || all) + { + sprintf (fname1, "/proc/%lld/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 || all) + { + sprintf (fname1, "/proc/%lld/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 || all) + { + sprintf (fname1, "/proc/%lld/maps", pid); + if ((procfile = fopen (fname1, "r")) > 0) + { + long long addr, endaddr, size, offset, inode; + char permissions[8], device[8], filename[MAXPATHLEN]; + char *header_fmt_string, *data_fmt_string; + + if (TARGET_ADDR_BIT == 32) + { + header_fmt_string = "\t%10s %10s %10s %10s %7s\n"; + data_fmt_string = "\t%#10lx %#10lx %#10x %#10x %7s\n"; + } + else + { + header_fmt_string = " %18s %18s %10s %10s %7s\n"; + data_fmt_string = " %#18lx %#18lx %#10x %#10x %7s\n"; + } + + printf_filtered ("Mapped address spaces:\n\n"); + printf_filtered (header_fmt_string, + "Start Addr", + " End Addr", + " Size", + " Offset", + "objfile"); + + while (read_mapping (procfile, &addr, &endaddr, &permissions[0], + &offset, &device[0], &inode, &filename[0])) + { + size = endaddr - addr; + printf_filtered (data_fmt_string, + (unsigned long) addr, /* FIXME: pr_addr */ + (unsigned long) endaddr, + (int) size, + (unsigned int) offset, + filename[0] ? filename : ""); + + } + + fclose (procfile); + } + else + warning ("unable to open /proc file '%s'", fname1); + } + if (status_f || all) + { + sprintf (fname1, "/proc/%lld/status", pid); + if ((procfile = fopen (fname1, "r")) > 0) + { + while (fgets (buffer, sizeof (buffer), procfile) != NULL) + printf_filtered (buffer); + fclose (procfile); + } + else + warning ("unable to open /proc file '%s'", fname1); + } + if (stat_f || all) + { + sprintf (fname1, "/proc/%lld/stat", pid); + if ((procfile = fopen (fname1, "r")) > 0) + { + int itmp; + char ctmp; + + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("Process: %d\n", itmp); + if (fscanf (procfile, "%s ", &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, "%u ", &itmp) > 0) + printf_filtered ("Flags: 0x%x\n", itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Minor faults (no memory page): %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Minor faults, children: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Major faults (memory page faults): %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Major faults, children: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("utime: %d\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("stime: %d\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("utime, children: %d\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("stime, children: %d\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("jiffies remaining in current time slice: %d\n", + itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("'nice' value: %d\n", itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("jiffies until next timeout: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("jiffies until next SIGALRM: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("start time (jiffies since system boot): %d\n", + itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Virtual memory size: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Resident set size: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("rlim: %u\n", + (unsigned int) itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Start of text: 0x%x\n", itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("End of text: 0x%x\n", itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) + printf_filtered ("Start of stack: 0x%x\n", itmp); +#if 0 /* Don't know how architecture-dependent the rest is... + Anyway the signal bitmap info is available from "status". */ + if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */ + printf_filtered ("Kernel stack pointer: 0x%x\n", itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */ + printf_filtered ("Kernel instr pointer: 0x%x\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("Pending signals bitmap: 0x%x\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp); + if (fscanf (procfile, "%d ", &itmp) > 0) + printf_filtered ("Catched signals bitmap: 0x%x\n", itmp); + if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */ + printf_filtered ("wchan (system call): 0x%x\n", itmp); +#endif + fclose (procfile); + } + else + warning ("unable to open /proc file '%s'", fname1); + } +} + void _initialize_linux_proc (void) { @@ -265,4 +542,13 @@ _initialize_linux_proc (void) inftarg_set_find_memory_regions (linux_find_memory_regions); inftarg_set_make_corefile_notes (linux_make_note_section); + + add_info ("proc", linux_info_proc_cmd, + "Show /proc process information about any running process.\n\ +Specify any process id, or use the program being debugged by default.\n\ +Specify any of the following keywords for detailed info:\n\ + mappings -- list of mapped memory regions.\n\ + stat -- list a bunch of random process info.\n\ + status -- list a different bunch of random process info.\n\ + all -- list all available /proc info."); } -- cgit v1.1