* regcache.c (register_buffer): Consitify first argument.
[deliverable/binutils-gdb.git] / gdb / linux-proc.c
CommitLineData
ca557f44
AC
1/* GNU/Linux specific methods for using the /proc file system.
2
be4d1333 3 Copyright 2001, 2002 Free Software Foundation, Inc.
4b09dc8c
MS
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include "defs.h"
be4d1333 23#include "inferior.h"
6949171e
JJ
24#include <sys/param.h> /* for MAXPATHLEN */
25#include <sys/procfs.h> /* for elf_gregset etc. */
26#include "gdb_stat.h" /* for struct stat */
27#include <ctype.h> /* for isdigit */
28#include <unistd.h> /* for open, pread64 */
29#include <fcntl.h> /* for O_RDONLY */
30#include "regcache.h" /* for registers_changed */
31#include "gregset.h" /* for gregset */
32#include "gdbcore.h" /* for get_exec_file */
33#include "gdbthread.h" /* for struct thread_info etc. */
34#include "elf-bfd.h" /* for elfcore_write_* */
2bf543a6 35#include "cli/cli-decode.h" /* for add_info */
ff5922b5 36#include "gdb_string.h"
be4d1333 37
0274a8ce
MS
38#include "linux-nat.h"
39
eb784848
DJ
40#ifndef O_LARGEFILE
41#define O_LARGEFILE 0
42#endif
43
be4d1333
MS
44/* Function: child_pid_to_exec_file
45 *
46 * Accepts an integer pid
47 * Returns a string representing a file that can be opened
48 * to get the symbols for the child process.
49 */
4b09dc8c
MS
50
51char *
52child_pid_to_exec_file (int pid)
53{
145fdc6e 54 char *name1, *name2;
4b09dc8c 55
145fdc6e
MS
56 name1 = xmalloc (MAXPATHLEN);
57 name2 = xmalloc (MAXPATHLEN);
58 make_cleanup (xfree, name1);
59 make_cleanup (xfree, name2);
60 memset (name2, 0, MAXPATHLEN);
61
62 sprintf (name1, "/proc/%d/exe", pid);
63 if (readlink (name1, name2, MAXPATHLEN) > 0)
64 return name2;
65 else
66 return name1;
4b09dc8c 67}
be4d1333 68
2bf543a6
MS
69/* Function: read_mappings
70 *
71 * Service function for corefiles and info proc.
72 */
73
6949171e
JJ
74static int
75read_mapping (FILE *mapfile,
76 long long *addr,
77 long long *endaddr,
78 char *permissions,
79 long long *offset,
80 char *device, long long *inode, char *filename)
2bf543a6 81{
6949171e 82 int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx",
2bf543a6
MS
83 addr, endaddr, permissions, offset, device, inode);
84
85 if (ret > 0 && ret != EOF && *inode != 0)
86 {
ee677e8d 87 /* Eat everything up to EOL for the filename. This will prevent
6949171e
JJ
88 weird filenames (such as one with embedded whitespace) from
89 confusing this code. It also makes this code more robust
90 in respect to annotations the kernel may add after the
91 filename.
ee677e8d 92
6949171e 93 Note the filename is used for informational purposes only. */
ee677e8d 94 ret += fscanf (mapfile, "%[^\n]\n", filename);
2bf543a6
MS
95 }
96 else
97 {
98 filename[0] = '\0'; /* no filename */
99 fscanf (mapfile, "\n");
100 }
101 return (ret != 0 && ret != EOF);
102}
103
be4d1333
MS
104/* Function: linux_find_memory_regions
105 *
106 * Fills the "to_find_memory_regions" target vector.
107 * Lists the memory regions in the inferior for a corefile.
108 */
109
110static int
6949171e 111linux_find_memory_regions (int (*func) (CORE_ADDR,
be4d1333 112 unsigned long,
6949171e 113 int, int, int, void *), void *obfd)
be4d1333
MS
114{
115 long long pid = PIDGET (inferior_ptid);
2bf543a6
MS
116 char mapsfilename[MAXPATHLEN];
117 FILE *mapsfile;
be4d1333 118 long long addr, endaddr, size, offset, inode;
2bf543a6 119 char permissions[8], device[8], filename[MAXPATHLEN];
be4d1333
MS
120 int read, write, exec;
121 int ret;
122
123 /* Compose the filename for the /proc memory map, and open it. */
2bf543a6
MS
124 sprintf (mapsfilename, "/proc/%lld/maps", pid);
125 if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
126 error ("Could not open %s\n", mapsfilename);
be4d1333
MS
127
128 if (info_verbose)
6949171e 129 fprintf_filtered (gdb_stdout,
2bf543a6 130 "Reading memory regions from %s\n", mapsfilename);
be4d1333
MS
131
132 /* Now iterate until end-of-file. */
6949171e 133 while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
2bf543a6 134 &offset, &device[0], &inode, &filename[0]))
be4d1333
MS
135 {
136 size = endaddr - addr;
137
138 /* Get the segment's permissions. */
6949171e 139 read = (strchr (permissions, 'r') != 0);
2bf543a6 140 write = (strchr (permissions, 'w') != 0);
6949171e 141 exec = (strchr (permissions, 'x') != 0);
be4d1333
MS
142
143 if (info_verbose)
144 {
6949171e
JJ
145 fprintf_filtered (gdb_stdout,
146 "Save segment, %lld bytes at 0x%s (%c%c%c)",
147 size, paddr_nz (addr),
148 read ? 'r' : ' ',
149 write ? 'w' : ' ', exec ? 'x' : ' ');
be4d1333 150 if (filename && filename[0])
6949171e 151 fprintf_filtered (gdb_stdout, " for %s", filename);
be4d1333
MS
152 fprintf_filtered (gdb_stdout, "\n");
153 }
154
155 /* Invoke the callback function to create the corefile segment. */
156 func (addr, size, read, write, exec, obfd);
be4d1333 157 }
2bf543a6 158 fclose (mapsfile);
be4d1333
MS
159 return 0;
160}
161
162/* Function: linux_do_thread_registers
163 *
164 * Records the thread's register state for the corefile note section.
165 */
166
167static char *
6949171e 168linux_do_thread_registers (bfd *obfd, ptid_t ptid,
be4d1333
MS
169 char *note_data, int *note_size)
170{
171 gdb_gregset_t gregs;
172 gdb_fpregset_t fpregs;
32872fa7
DJ
173#ifdef FILL_FPXREGSET
174 gdb_fpxregset_t fpxregs;
175#endif
0274a8ce 176 unsigned long lwp = ptid_get_lwp (ptid);
be4d1333
MS
177
178 fill_gregset (&gregs, -1);
6949171e
JJ
179 note_data = (char *) elfcore_write_prstatus (obfd,
180 note_data,
181 note_size,
0274a8ce 182 lwp,
6949171e 183 stop_signal, &gregs);
be4d1333
MS
184
185 fill_fpregset (&fpregs, -1);
6949171e
JJ
186 note_data = (char *) elfcore_write_prfpreg (obfd,
187 note_data,
188 note_size,
189 &fpregs, sizeof (fpregs));
32872fa7
DJ
190#ifdef FILL_FPXREGSET
191 fill_fpxregset (&fpxregs, -1);
6949171e
JJ
192 note_data = (char *) elfcore_write_prxfpreg (obfd,
193 note_data,
194 note_size,
195 &fpxregs, sizeof (fpxregs));
32872fa7 196#endif
be4d1333
MS
197 return note_data;
198}
199
8acc2935
MK
200struct linux_corefile_thread_data
201{
202 bfd *obfd;
be4d1333 203 char *note_data;
8acc2935
MK
204 int *note_size;
205 int num_notes;
be4d1333
MS
206};
207
208/* Function: linux_corefile_thread_callback
209 *
210 * Called by gdbthread.c once per thread.
211 * Records the thread's register state for the corefile note section.
212 */
213
214static int
0274a8ce 215linux_corefile_thread_callback (struct lwp_info *ti, void *data)
be4d1333
MS
216{
217 struct linux_corefile_thread_data *args = data;
218 ptid_t saved_ptid = inferior_ptid;
219
220 inferior_ptid = ti->ptid;
221 registers_changed ();
222 target_fetch_registers (-1); /* FIXME should not be necessary;
223 fill_gregset should do it automatically. */
6949171e
JJ
224 args->note_data = linux_do_thread_registers (args->obfd,
225 ti->ptid,
226 args->note_data,
be4d1333 227 args->note_size);
8acc2935 228 args->num_notes++;
be4d1333
MS
229 inferior_ptid = saved_ptid;
230 registers_changed ();
231 target_fetch_registers (-1); /* FIXME should not be necessary;
232 fill_gregset should do it automatically. */
233 return 0;
234}
235
236/* Function: linux_make_note_section
237 *
238 * Fills the "to_make_corefile_note" target vector.
239 * Builds the note section for a corefile, and returns it
240 * in a malloc buffer.
241 */
242
243static char *
244linux_make_note_section (bfd *obfd, int *note_size)
245{
246 struct linux_corefile_thread_data thread_args;
247 struct cleanup *old_chain;
6949171e
JJ
248 char fname[16] = { '\0' };
249 char psargs[80] = { '\0' };
be4d1333
MS
250 char *note_data = NULL;
251 ptid_t current_ptid = inferior_ptid;
252
253 if (get_exec_file (0))
254 {
255 strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
6949171e 256 strncpy (psargs, get_exec_file (0), sizeof (psargs));
be4d1333
MS
257 if (get_inferior_args ())
258 {
6949171e
JJ
259 strncat (psargs, " ", sizeof (psargs) - strlen (psargs));
260 strncat (psargs, get_inferior_args (),
be4d1333
MS
261 sizeof (psargs) - strlen (psargs));
262 }
6949171e
JJ
263 note_data = (char *) elfcore_write_prpsinfo (obfd,
264 note_data,
265 note_size, fname, psargs);
be4d1333
MS
266 }
267
268 /* Dump information for threads. */
269 thread_args.obfd = obfd;
270 thread_args.note_data = note_data;
271 thread_args.note_size = note_size;
8acc2935 272 thread_args.num_notes = 0;
0274a8ce 273 iterate_over_lwps (linux_corefile_thread_callback, &thread_args);
8acc2935 274 if (thread_args.num_notes == 0)
be4d1333
MS
275 {
276 /* iterate_over_threads didn't come up with any threads;
6949171e
JJ
277 just use inferior_ptid. */
278 note_data = linux_do_thread_registers (obfd, inferior_ptid,
be4d1333
MS
279 note_data, note_size);
280 }
281 else
282 {
283 note_data = thread_args.note_data;
284 }
285
286 make_cleanup (xfree, note_data);
287 return note_data;
288}
289
2bf543a6
MS
290/*
291 * Function: linux_info_proc_cmd
292 *
293 * Implement the "info proc" command.
294 */
295
296static void
297linux_info_proc_cmd (char *args, int from_tty)
298{
299 long long pid = PIDGET (inferior_ptid);
300 FILE *procfile;
301 char **argv = NULL;
302 char buffer[MAXPATHLEN];
303 char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
304 int cmdline_f = 1;
305 int cwd_f = 1;
306 int exe_f = 1;
307 int mappings_f = 0;
308 int environ_f = 0;
309 int status_f = 0;
310 int stat_f = 0;
311 int all = 0;
312 struct stat dummy;
313
314 if (args)
315 {
316 /* Break up 'args' into an argv array. */
317 if ((argv = buildargv (args)) == NULL)
318 nomem (0);
319 else
320 make_cleanup_freeargv (argv);
321 }
322 while (argv != NULL && *argv != NULL)
323 {
324 if (isdigit (argv[0][0]))
325 {
326 pid = strtoul (argv[0], NULL, 10);
327 }
328 else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
329 {
330 mappings_f = 1;
331 }
332 else if (strcmp (argv[0], "status") == 0)
333 {
334 status_f = 1;
335 }
336 else if (strcmp (argv[0], "stat") == 0)
337 {
338 stat_f = 1;
339 }
340 else if (strcmp (argv[0], "cmd") == 0)
341 {
342 cmdline_f = 1;
343 }
344 else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0)
345 {
346 exe_f = 1;
347 }
348 else if (strcmp (argv[0], "cwd") == 0)
349 {
350 cwd_f = 1;
351 }
352 else if (strncmp (argv[0], "all", strlen (argv[0])) == 0)
353 {
354 all = 1;
355 }
356 else
357 {
358 /* [...] (future options here) */
359 }
360 argv++;
361 }
362 if (pid == 0)
363 error ("No current process: you must name one.");
364
365 sprintf (fname1, "/proc/%lld", pid);
366 if (stat (fname1, &dummy) != 0)
367 error ("No /proc directory: '%s'", fname1);
368
369 printf_filtered ("process %lld\n", pid);
370 if (cmdline_f || all)
371 {
372 sprintf (fname1, "/proc/%lld/cmdline", pid);
373 if ((procfile = fopen (fname1, "r")) > 0)
374 {
375 fgets (buffer, sizeof (buffer), procfile);
376 printf_filtered ("cmdline = '%s'\n", buffer);
377 fclose (procfile);
378 }
379 else
380 warning ("unable to open /proc file '%s'", fname1);
381 }
382 if (cwd_f || all)
383 {
384 sprintf (fname1, "/proc/%lld/cwd", pid);
385 memset (fname2, 0, sizeof (fname2));
386 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
387 printf_filtered ("cwd = '%s'\n", fname2);
388 else
389 warning ("unable to read link '%s'", fname1);
390 }
391 if (exe_f || all)
392 {
393 sprintf (fname1, "/proc/%lld/exe", pid);
394 memset (fname2, 0, sizeof (fname2));
395 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
396 printf_filtered ("exe = '%s'\n", fname2);
397 else
398 warning ("unable to read link '%s'", fname1);
399 }
400 if (mappings_f || all)
401 {
402 sprintf (fname1, "/proc/%lld/maps", pid);
403 if ((procfile = fopen (fname1, "r")) > 0)
404 {
405 long long addr, endaddr, size, offset, inode;
406 char permissions[8], device[8], filename[MAXPATHLEN];
2bf543a6 407
ba058b66 408 printf_filtered ("Mapped address spaces:\n\n");
2bf543a6
MS
409 if (TARGET_ADDR_BIT == 32)
410 {
ba058b66
DC
411 printf_filtered ("\t%10s %10s %10s %10s %7s\n",
412 "Start Addr",
413 " End Addr",
414 " Size", " Offset", "objfile");
415 }
2bf543a6 416 else
ba058b66
DC
417 {
418 printf_filtered (" %18s %18s %10s %10s %7s\n",
2bf543a6
MS
419 "Start Addr",
420 " End Addr",
6949171e 421 " Size", " Offset", "objfile");
ba058b66 422 }
6949171e
JJ
423
424 while (read_mapping (procfile, &addr, &endaddr, &permissions[0],
2bf543a6
MS
425 &offset, &device[0], &inode, &filename[0]))
426 {
427 size = endaddr - addr;
ba058b66
DC
428
429 /* FIXME: carlton/2003-08-27: Maybe the printf_filtered
430 calls here (and possibly above) should be abstracted
431 out into their own functions? Andrew suggests using
432 a generic local_address_string instead to print out
433 the addresses; that makes sense to me, too. */
434
435 if (TARGET_ADDR_BIT == 32)
436 {
437 printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
438 (unsigned long) addr, /* FIXME: pr_addr */
6949171e
JJ
439 (unsigned long) endaddr,
440 (int) size,
441 (unsigned int) offset,
2bf543a6 442 filename[0] ? filename : "");
ba058b66
DC
443 }
444 else
445 {
446 printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n",
447 (unsigned long) addr, /* FIXME: pr_addr */
448 (unsigned long) endaddr,
449 (int) size,
450 (unsigned int) offset,
451 filename[0] ? filename : "");
452 }
2bf543a6
MS
453 }
454
455 fclose (procfile);
456 }
457 else
458 warning ("unable to open /proc file '%s'", fname1);
459 }
460 if (status_f || all)
461 {
462 sprintf (fname1, "/proc/%lld/status", pid);
463 if ((procfile = fopen (fname1, "r")) > 0)
464 {
465 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
306d9ac5 466 puts_filtered (buffer);
2bf543a6
MS
467 fclose (procfile);
468 }
6949171e 469 else
2bf543a6
MS
470 warning ("unable to open /proc file '%s'", fname1);
471 }
472 if (stat_f || all)
473 {
474 sprintf (fname1, "/proc/%lld/stat", pid);
475 if ((procfile = fopen (fname1, "r")) > 0)
476 {
477 int itmp;
478 char ctmp;
479
480 if (fscanf (procfile, "%d ", &itmp) > 0)
481 printf_filtered ("Process: %d\n", itmp);
482 if (fscanf (procfile, "%s ", &buffer[0]) > 0)
483 printf_filtered ("Exec file: %s\n", buffer);
484 if (fscanf (procfile, "%c ", &ctmp) > 0)
485 printf_filtered ("State: %c\n", ctmp);
486 if (fscanf (procfile, "%d ", &itmp) > 0)
487 printf_filtered ("Parent process: %d\n", itmp);
488 if (fscanf (procfile, "%d ", &itmp) > 0)
489 printf_filtered ("Process group: %d\n", itmp);
490 if (fscanf (procfile, "%d ", &itmp) > 0)
491 printf_filtered ("Session id: %d\n", itmp);
492 if (fscanf (procfile, "%d ", &itmp) > 0)
493 printf_filtered ("TTY: %d\n", itmp);
494 if (fscanf (procfile, "%d ", &itmp) > 0)
495 printf_filtered ("TTY owner process group: %d\n", itmp);
496 if (fscanf (procfile, "%u ", &itmp) > 0)
497 printf_filtered ("Flags: 0x%x\n", itmp);
498 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 499 printf_filtered ("Minor faults (no memory page): %u\n",
2bf543a6
MS
500 (unsigned int) itmp);
501 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 502 printf_filtered ("Minor faults, children: %u\n",
2bf543a6
MS
503 (unsigned int) itmp);
504 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 505 printf_filtered ("Major faults (memory page faults): %u\n",
2bf543a6
MS
506 (unsigned int) itmp);
507 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 508 printf_filtered ("Major faults, children: %u\n",
2bf543a6
MS
509 (unsigned int) itmp);
510 if (fscanf (procfile, "%d ", &itmp) > 0)
511 printf_filtered ("utime: %d\n", itmp);
512 if (fscanf (procfile, "%d ", &itmp) > 0)
513 printf_filtered ("stime: %d\n", itmp);
514 if (fscanf (procfile, "%d ", &itmp) > 0)
515 printf_filtered ("utime, children: %d\n", itmp);
516 if (fscanf (procfile, "%d ", &itmp) > 0)
517 printf_filtered ("stime, children: %d\n", itmp);
518 if (fscanf (procfile, "%d ", &itmp) > 0)
6949171e 519 printf_filtered ("jiffies remaining in current time slice: %d\n",
2bf543a6
MS
520 itmp);
521 if (fscanf (procfile, "%d ", &itmp) > 0)
522 printf_filtered ("'nice' value: %d\n", itmp);
523 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 524 printf_filtered ("jiffies until next timeout: %u\n",
2bf543a6
MS
525 (unsigned int) itmp);
526 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 527 printf_filtered ("jiffies until next SIGALRM: %u\n",
2bf543a6
MS
528 (unsigned int) itmp);
529 if (fscanf (procfile, "%d ", &itmp) > 0)
6949171e 530 printf_filtered ("start time (jiffies since system boot): %d\n",
2bf543a6
MS
531 itmp);
532 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 533 printf_filtered ("Virtual memory size: %u\n",
2bf543a6
MS
534 (unsigned int) itmp);
535 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 536 printf_filtered ("Resident set size: %u\n", (unsigned int) itmp);
2bf543a6 537 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 538 printf_filtered ("rlim: %u\n", (unsigned int) itmp);
2bf543a6
MS
539 if (fscanf (procfile, "%u ", &itmp) > 0)
540 printf_filtered ("Start of text: 0x%x\n", itmp);
541 if (fscanf (procfile, "%u ", &itmp) > 0)
542 printf_filtered ("End of text: 0x%x\n", itmp);
543 if (fscanf (procfile, "%u ", &itmp) > 0)
544 printf_filtered ("Start of stack: 0x%x\n", itmp);
6949171e
JJ
545#if 0 /* Don't know how architecture-dependent the rest is...
546 Anyway the signal bitmap info is available from "status". */
2bf543a6
MS
547 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
548 printf_filtered ("Kernel stack pointer: 0x%x\n", itmp);
549 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
550 printf_filtered ("Kernel instr pointer: 0x%x\n", itmp);
551 if (fscanf (procfile, "%d ", &itmp) > 0)
552 printf_filtered ("Pending signals bitmap: 0x%x\n", itmp);
553 if (fscanf (procfile, "%d ", &itmp) > 0)
554 printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp);
555 if (fscanf (procfile, "%d ", &itmp) > 0)
556 printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp);
557 if (fscanf (procfile, "%d ", &itmp) > 0)
558 printf_filtered ("Catched signals bitmap: 0x%x\n", itmp);
559 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
560 printf_filtered ("wchan (system call): 0x%x\n", itmp);
561#endif
562 fclose (procfile);
563 }
564 else
565 warning ("unable to open /proc file '%s'", fname1);
566 }
567}
568
be4d1333
MS
569void
570_initialize_linux_proc (void)
571{
572 extern void inftarg_set_find_memory_regions ();
573 extern void inftarg_set_make_corefile_notes ();
574
575 inftarg_set_find_memory_regions (linux_find_memory_regions);
576 inftarg_set_make_corefile_notes (linux_make_note_section);
2bf543a6 577
6949171e 578 add_info ("proc", linux_info_proc_cmd,
2bf543a6
MS
579 "Show /proc process information about any running process.\n\
580Specify any process id, or use the program being debugged by default.\n\
581Specify any of the following keywords for detailed info:\n\
582 mappings -- list of mapped memory regions.\n\
583 stat -- list a bunch of random process info.\n\
584 status -- list a different bunch of random process info.\n\
585 all -- list all available /proc info.");
be4d1333 586}
eb784848 587
6949171e
JJ
588int
589linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len, int write,
590 struct mem_attrib *attrib, struct target_ops *target)
eb784848
DJ
591{
592 int fd, ret;
593 char filename[64];
594
595 if (write)
596 return 0;
597
598 /* Don't bother for one word. */
599 if (len < 3 * sizeof (long))
600 return 0;
601
602 /* We could keep this file open and cache it - possibly one
603 per thread. That requires some juggling, but is even faster. */
604 sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
605 fd = open (filename, O_RDONLY | O_LARGEFILE);
606 if (fd == -1)
607 return 0;
608
609 /* If pread64 is available, use it. It's faster if the kernel
610 supports it (only one syscall), and it's 64-bit safe even
611 on 32-bit platforms (for instance, SPARC debugging a SPARC64
6564f77d 612 application). */
eb784848
DJ
613#ifdef HAVE_PREAD64
614 if (pread64 (fd, myaddr, len, addr) != len)
615#else
6949171e 616 if (lseek (fd, addr, SEEK_SET) == -1 || read (fd, myaddr, len) != len)
eb784848
DJ
617#endif
618 ret = 0;
619 else
620 ret = len;
621
622 close (fd);
623 return ret;
624}
This page took 0.209718 seconds and 4 git commands to generate.