*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / linux-proc.c
index c66df986689da7d60013c489829724a441f2cac2..2f43ae61f97004f3bfd968271037e8af05935052 100644 (file)
@@ -25,6 +25,8 @@
 #include <sys/procfs.h>        /* for elf_gregset etc. */
 #include <sys/stat.h>  /* for struct stat */
 #include <ctype.h>     /* for isdigit */
+#include <unistd.h>    /* for open, pread64 */
+#include <fcntl.h>     /* for O_RDONLY */
 #include "regcache.h"  /* for registers_changed */
 #include "gregset.h"   /* for gregset */
 #include "gdbcore.h"   /* for get_exec_file */
 #include "cli/cli-decode.h"    /* for add_info */
 #include "gdb_string.h"
 
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
 /* Function: child_pid_to_exec_file
  *
  * Accepts an integer pid
@@ -198,10 +204,12 @@ linux_do_thread_registers (bfd *obfd, ptid_t ptid,
   return note_data;
 }
 
-struct linux_corefile_thread_data {
-  bfd  *obfd;
+struct linux_corefile_thread_data
+{
+  bfd *obfd;
   char *note_data;
-  int  *note_size;
+  int *note_size;
+  int num_notes;
 };
 
 /* Function: linux_corefile_thread_callback
@@ -224,6 +232,7 @@ linux_corefile_thread_callback (struct thread_info *ti, void *data)
                                               ti->ptid, 
                                               args->note_data, 
                                               args->note_size);
+  args->num_notes++;
   inferior_ptid = saved_ptid;
   registers_changed ();
   target_fetch_registers (-1); /* FIXME should not be necessary; 
@@ -271,11 +280,12 @@ linux_make_note_section (bfd *obfd, int *note_size)
   thread_args.obfd = obfd;
   thread_args.note_data = note_data;
   thread_args.note_size = note_size;
+  thread_args.num_notes = 0;
   iterate_over_threads (linux_corefile_thread_callback, &thread_args);
-  if (thread_args.note_data == note_data)
+  if (thread_args.num_notes == 0)
     {
       /* iterate_over_threads didn't come up with any threads;
-        just use inferior_ptid. */
+        just use inferior_ptid.  */
       note_data = linux_do_thread_registers (obfd, inferior_ptid, 
                                             note_data, note_size);
     }
@@ -573,3 +583,46 @@ Specify any of the following keywords for detailed info:\n\
   status   -- list a different bunch of random process info.\n\
   all      -- list all available /proc info.");
 }
+
+int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len, int write,
+                           struct mem_attrib *attrib,
+                           struct target_ops *target)
+{
+  int fd, ret;
+  char filename[64];
+
+  if (write)
+    return 0;
+
+  /* Don't bother for one word.  */
+  if (len < 3 * sizeof (long))
+    return 0;
+
+  /* We could keep this file open and cache it - possibly one
+     per thread.  That requires some juggling, but is even faster.  */
+  sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
+  fd = open (filename, O_RDONLY | O_LARGEFILE);
+  if (fd == -1)
+    return 0;
+
+  /* If pread64 is available, use it.  It's faster if the kernel
+     supports it (only one syscall), and it's 64-bit safe even
+     on 32-bit platforms (for instance, SPARC debugging a SPARC64
+     application).
+
+     We play some autoconf and CFLAGS games to get this declaration
+     exposed: -D_XOPEN_SOURCE=500 -D_LARGEFILE64_SOURCE.  And then
+     a -D_BSD_SOURCE to counteract the defaults for _XOPEN_SOURCE.  */
+#ifdef HAVE_PREAD64
+  if (pread64 (fd, myaddr, len, addr) != len)
+#else
+  if (lseek (fd, addr, SEEK_SET) == -1
+      || read (fd, myaddr, len) != len)
+#endif
+    ret = 0;
+  else
+    ret = len;
+
+  close (fd);
+  return ret;
+}
This page took 0.025729 seconds and 4 git commands to generate.