replace hexify with bin2hex
[platform/upstream/binutils.git] / gdb / common / linux-osdata.c
index 1086d10..805850c 100644 (file)
@@ -1,6 +1,6 @@
 /* Linux-specific functions to retrieve OS data.
    
-   Copyright (C) 2009-2012 Free Software Foundation, Inc.
+   Copyright (C) 2009-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,8 +26,7 @@
 #include "linux-osdata.h"
 
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
+#include <sys/sysinfo.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include "xml-utils.h"
 #include "buffer.h"
 #include "gdb_assert.h"
-#include "gdb_dirent.h"
+#include <dirent.h>
+#include <sys/stat.h>
+#include "filestuff.h"
+
+#define NAMELEN(dirent) strlen ((dirent)->d_name)
 
 /* Define PID_T to be a fixed size that is at least as large as pid_t,
    so that reading pid values embedded in /proc works
@@ -76,7 +79,7 @@ linux_common_core_of_thread (ptid_t ptid)
 
   sprintf (filename, "/proc/%lld/task/%lld/stat",
           (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
-  f = fopen (filename, "r");
+  f = gdb_fopen_cloexec (filename, "r");
   if (!f)
     return -1;
 
@@ -125,7 +128,7 @@ static void
 command_from_pid (char *command, int maxlen, PID_T pid)
 {
   char *stat_path = xstrprintf ("/proc/%lld/stat", pid); 
-  FILE *fp = fopen (stat_path, "r");
+  FILE *fp = gdb_fopen_cloexec (stat_path, "r");
   
   command[0] = '\0';
  
@@ -134,9 +137,9 @@ command_from_pid (char *command, int maxlen, PID_T pid)
       /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
         include/linux/sched.h in the Linux kernel sources) plus two
         (for the brackets).  */
-      char cmd[32]; 
+      char cmd[18];
       PID_T stat_pid;
-      int items_read = fscanf (fp, "%lld %32s", &stat_pid, cmd);
+      int items_read = fscanf (fp, "%lld %17s", &stat_pid, cmd);
          
       if (items_read == 2 && pid == stat_pid)
        {
@@ -165,7 +168,7 @@ commandline_from_pid (PID_T pid)
 {
   char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
   char *commandline = NULL;
-  FILE *f = fopen (pathname, "r");
+  FILE *f = gdb_fopen_cloexec (pathname, "r");
 
   if (f)
     {
@@ -254,30 +257,8 @@ get_process_owner (uid_t *owner, PID_T pid)
     return -1;
 }
 
-/* Returns the number of CPU cores found on the system.  */
-
-static int
-get_number_of_cpu_cores (void)
-{
-  int cores = 0;
-  FILE *f = fopen ("/proc/cpuinfo", "r");
-
-  while (!feof (f))
-    {
-      char buf[512];
-      char *p = fgets (buf, sizeof (buf), f);
-
-      if (p && strncmp (buf, "processor", 9) == 0)
-       ++cores;
-    }
-
-  fclose (f);
-
-  return cores;
-}
-
 /* Find the CPU cores used by process PID and return them in CORES.
-   CORES points to an array of at least get_number_of_cpu_cores ()
+   CORES points to an array of at least sysconf(_SC_NPROCESSOR_ONLN)
    elements.  */
 
 static int
@@ -320,7 +301,7 @@ get_cores_used_by_process (PID_T pid, int *cores)
 
 static LONGEST
 linux_xfer_osdata_processes (gdb_byte *readbuf,
-                            ULONGEST offset, LONGEST len)
+                            ULONGEST offset, ULONGEST len)
 {
   /* We make the process list snapshot when the object starts to be read.  */
   static const char *buf;
@@ -341,7 +322,7 @@ linux_xfer_osdata_processes (gdb_byte *readbuf,
       dirp = opendir ("/proc");
       if (dirp)
        {
-         const int num_cores = get_number_of_cpu_cores ();
+         const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
          struct dirent *dp;
 
          while ((dp = readdir (dirp)) != NULL)
@@ -468,7 +449,7 @@ compare_processes (const void *process1, const void *process2)
 
 static LONGEST
 linux_xfer_osdata_processgroups (gdb_byte *readbuf,
-                                ULONGEST offset, LONGEST len)
+                                ULONGEST offset, ULONGEST len)
 {
   /* We make the process list snapshot when the object starts to be read.  */
   static const char *buf;
@@ -584,7 +565,7 @@ linux_xfer_osdata_processgroups (gdb_byte *readbuf,
 
 static LONGEST
 linux_xfer_osdata_threads (gdb_byte *readbuf,
-                          ULONGEST offset, LONGEST len)
+                          ULONGEST offset, ULONGEST len)
 {
   /* We make the process list snapshot when the object starts to be read.  */
   static const char *buf;
@@ -698,7 +679,7 @@ linux_xfer_osdata_threads (gdb_byte *readbuf,
 
 static LONGEST
 linux_xfer_osdata_fds (gdb_byte *readbuf,
-                      ULONGEST offset, LONGEST len)
+                      ULONGEST offset, ULONGEST len)
 {
   /* We make the process list snapshot when the object starts to be read.  */
   static const char *buf;
@@ -759,7 +740,7 @@ linux_xfer_osdata_fds (gdb_byte *readbuf,
                            continue;
 
                          fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
-                         rslt = readlink (fdname, buf, 1000);
+                         rslt = readlink (fdname, buf, sizeof (buf) - 1);
                          if (rslt >= 0)
                            buf[rslt] = '\0';
 
@@ -882,7 +863,7 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer)
   else
     return;
 
-  fp = fopen (proc_file, "r");
+  fp = gdb_fopen_cloexec (proc_file, "r");
   if (fp)
     {
       char buf[8192];
@@ -892,29 +873,22 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer)
          if (fgets (buf, sizeof (buf), fp))
            {
              uid_t uid;
-             unsigned long tlen, inode;
-             int sl, timeout;
              unsigned int local_port, remote_port, state;
-             unsigned int txq, rxq, trun, retn;
              char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
-             char extra[512];
              int result;
 
+#if NI_MAXHOST <= 32
+#error "local_address and remote_address buffers too small"
+#endif
+
              result = sscanf (buf,
-                              "%d: %33[0-9A-F]:%X %33[0-9A-F]:%X %X %X:%X %X:%lX %X %d %d %lu %512s\n",
-                              &sl,
+                              "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
                               local_address, &local_port,
                               remote_address, &remote_port,
                               &state,
-                              &txq, &rxq,
-                              &trun, &tlen,
-                              &retn,
-                              &uid,
-                              &timeout,
-                              &inode,
-                              extra);
+                              &uid);
              
-             if (result == 15)
+             if (result == 6)
                {
                  union socket_addr locaddr, remaddr;
                  size_t addr_size;
@@ -1012,7 +986,7 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer)
 
 static LONGEST
 linux_xfer_osdata_isockets (gdb_byte *readbuf,
-                           ULONGEST offset, LONGEST len)
+                           ULONGEST offset, ULONGEST len)
 {
   static const char *buf;
   static LONGEST len_avail = -1;
@@ -1093,7 +1067,7 @@ group_from_gid (char *group, int maxlen, gid_t gid)
 
 static LONGEST
 linux_xfer_osdata_shm (gdb_byte *readbuf,
-                      ULONGEST offset, LONGEST len)
+                      ULONGEST offset, ULONGEST len)
 {
   static const char *buf;
   static LONGEST len_avail = -1;
@@ -1110,7 +1084,7 @@ linux_xfer_osdata_shm (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
 
-      fp = fopen ("/proc/sysvipc/shm", "r");
+      fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
       if (fp)
        {
          char buf[8192];
@@ -1221,7 +1195,7 @@ linux_xfer_osdata_shm (gdb_byte *readbuf,
 
 static LONGEST
 linux_xfer_osdata_sem (gdb_byte *readbuf,
-                      ULONGEST offset, LONGEST len)
+                      ULONGEST offset, ULONGEST len)
 {
   static const char *buf;
   static LONGEST len_avail = -1;
@@ -1238,7 +1212,7 @@ linux_xfer_osdata_sem (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
 
-      fp = fopen ("/proc/sysvipc/sem", "r");
+      fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
       if (fp)
        {
          char buf[8192];
@@ -1333,7 +1307,7 @@ linux_xfer_osdata_sem (gdb_byte *readbuf,
 
 static LONGEST
 linux_xfer_osdata_msg (gdb_byte *readbuf,
-                      ULONGEST offset, LONGEST len)
+                      ULONGEST offset, ULONGEST len)
 {
   static const char *buf;
   static LONGEST len_avail = -1;
@@ -1350,7 +1324,7 @@ linux_xfer_osdata_msg (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
       
-      fp = fopen ("/proc/sysvipc/msg", "r");
+      fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
       if (fp)
        {
          char buf[8192];
@@ -1459,7 +1433,7 @@ linux_xfer_osdata_msg (gdb_byte *readbuf,
 
 static LONGEST
 linux_xfer_osdata_modules (gdb_byte *readbuf,
-                          ULONGEST offset, LONGEST len)
+                          ULONGEST offset, ULONGEST len)
 {
   static const char *buf;
   static LONGEST len_avail = -1;
@@ -1476,7 +1450,7 @@ linux_xfer_osdata_modules (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
 
-      fp = fopen ("/proc/modules", "r");
+      fp = gdb_fopen_cloexec ("/proc/modules", "r");
       if (fp)
        {
          char buf[8192];
@@ -1485,19 +1459,42 @@ linux_xfer_osdata_modules (gdb_byte *readbuf,
            {
              if (fgets (buf, sizeof (buf), fp))
                {
-                 char name[64], dependencies[256], status[16];
+                 char *name, *dependencies, *status, *tmp;
                  unsigned int size;
                  unsigned long long address;
                  int uses;
-                 int items_read;
-                 
-                 items_read = sscanf (buf,
-                                      "%64s %d %d %256s %16s 0x%llx",
-                                      name, &size, &uses,
-                                      dependencies, status, &address);
 
-                 if (items_read == 6)
-                   buffer_xml_printf (
+                 name = strtok (buf, " ");
+                 if (name == NULL)
+                   continue;
+
+                 tmp = strtok (NULL, " ");
+                 if (tmp == NULL)
+                   continue;
+                 if (sscanf (tmp, "%u", &size) != 1)
+                   continue;
+
+                 tmp = strtok (NULL, " ");
+                 if (tmp == NULL)
+                   continue;
+                 if (sscanf (tmp, "%d", &uses) != 1)
+                   continue;
+
+                 dependencies = strtok (NULL, " ");
+                 if (dependencies == NULL)
+                   continue;
+
+                 status = strtok (NULL, " ");
+                 if (status == NULL)
+                   continue;
+
+                 tmp = strtok (NULL, "\n");
+                 if (tmp == NULL)
+                   continue;
+                 if (sscanf (tmp, "%llx", &address) != 1)
+                   continue;
+
+                 buffer_xml_printf (
                        &buffer,
                        "<item>"
                        "<column name=\"name\">%s</column>"
@@ -1543,33 +1540,34 @@ linux_xfer_osdata_modules (gdb_byte *readbuf,
 
 struct osdata_type {
   char *type;
+  char *title;
   char *description;
-  LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, LONGEST len);
+  LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
 } osdata_table[] = {
-  { "processes", "Listing of all processes",
+  { "processes", "Processes", "Listing of all processes",
     linux_xfer_osdata_processes },
-  { "procgroups", "Listing of all process groups",
+  { "procgroups", "Process groups", "Listing of all process groups",
     linux_xfer_osdata_processgroups },
-  { "threads", "Listing of all threads",
+  { "threads", "Threads", "Listing of all threads",
     linux_xfer_osdata_threads },
-  { "files", "Listing of all file descriptors",
+  { "files", "File descriptors", "Listing of all file descriptors",
     linux_xfer_osdata_fds },
-  { "sockets", "Listing of all internet-domain sockets",
+  { "sockets", "Sockets", "Listing of all internet-domain sockets",
     linux_xfer_osdata_isockets },
-  { "shm", "Listing of all shared-memory regions",
+  { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
     linux_xfer_osdata_shm },
-  { "semaphores", "Listing of all semaphores",
+  { "semaphores", "Semaphores", "Listing of all semaphores",
     linux_xfer_osdata_sem },
-  { "msg", "Listing of all message queues",
+  { "msg", "Message queues", "Listing of all message queues",
     linux_xfer_osdata_msg },
-  { "modules", "Listing of all loaded kernel modules",
+  { "modules", "Kernel modules", "Listing of all loaded kernel modules",
     linux_xfer_osdata_modules },
   { NULL, NULL, NULL }
 };
 
 LONGEST
 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
-                         ULONGEST offset, LONGEST len)
+                         ULONGEST offset, ULONGEST len)
 {
   if (!annex || *annex == '\0')
     {
@@ -1594,9 +1592,11 @@ linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
                               "<item>"
                               "<column name=\"Type\">%s</column>"
                               "<column name=\"Description\">%s</column>"
+                              "<column name=\"Title\">%s</column>"
                               "</item>",
                               osdata_table[i].type,
-                              osdata_table[i].description);
+                              osdata_table[i].description,
+                              osdata_table[i].title);
 
          buffer_grow_str0 (&buffer, "</osdata>\n");
          buf = buffer_finish (&buffer);