1 /* Linux-specific methods for using the /proc file system.
2 Copyright 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
23 #include <sys/param.h> /* for MAXPATHLEN */
24 #include <sys/procfs.h>
25 #include "gregset.h" /* for gregset */
26 #include "gdbcore.h" /* for get_exec_file */
27 #include "gdbthread.h" /* for struct thread_info etc. */
30 /* Function: child_pid_to_exec_file
32 * Accepts an integer pid
33 * Returns a string representing a file that can be opened
34 * to get the symbols for the child process.
38 child_pid_to_exec_file (int pid
)
42 name1
= xmalloc (MAXPATHLEN
);
43 name2
= xmalloc (MAXPATHLEN
);
44 make_cleanup (xfree
, name1
);
45 make_cleanup (xfree
, name2
);
46 memset (name2
, 0, MAXPATHLEN
);
48 sprintf (name1
, "/proc/%d/exe", pid
);
49 if (readlink (name1
, name2
, MAXPATHLEN
) > 0)
55 /* Function: linux_find_memory_regions
57 * Fills the "to_find_memory_regions" target vector.
58 * Lists the memory regions in the inferior for a corefile.
62 linux_find_memory_regions (int (*func
) (CORE_ADDR
,
68 long long pid
= PIDGET (inferior_ptid
);
69 char procfilename
[MAXPATHLEN
];
71 long long addr
, endaddr
, size
, offset
, inode
;
72 char perms
[8], dev
[8], filename
[MAXPATHLEN
];
73 int read
, write
, exec
;
76 /* Compose the filename for the /proc memory map, and open it. */
77 sprintf (procfilename
, "/proc/%lld/maps", pid
);
78 if ((procfile
= fopen (procfilename
, "r")) == NULL
)
79 error ("Could not open %s\n", procfilename
);
82 fprintf_filtered (gdb_stdout
,
83 "Reading memory regions from %s\n", procfilename
);
85 /* Read the first memory segment descriptor from the maps file. */
86 ret
= fscanf (procfile
, "%llx-%llx %s %llx %s %llx",
87 &addr
, &endaddr
, perms
, &offset
, dev
, &inode
);
89 fscanf (procfile
, " %s\n", filename
);
93 fscanf (procfile
, "\n");
96 /* Now iterate until end-of-file. */
97 while (ret
> 0 && ret
!= EOF
)
99 size
= endaddr
- addr
;
101 /* Get the segment's permissions. */
102 read
= (strchr (perms
, 'r') != 0);
103 write
= (strchr (perms
, 'w') != 0);
104 exec
= (strchr (perms
, 'x') != 0);
108 fprintf_filtered (gdb_stdout
,
109 "Save segment, %lld bytes at 0x%s (%c%c%c)",
110 size
, paddr_nz (addr
),
114 if (filename
&& filename
[0])
115 fprintf_filtered (gdb_stdout
,
116 " for %s", filename
);
117 fprintf_filtered (gdb_stdout
, "\n");
120 /* Invoke the callback function to create the corefile segment. */
121 func (addr
, size
, read
, write
, exec
, obfd
);
123 /* Read the next memory region. */
125 ret
= fscanf (procfile
, "%llx-%llx %s %llx %s %llx",
126 &addr
, &endaddr
, perms
, &offset
, dev
, &inode
);
128 fscanf (procfile
, " %s\n", filename
);
132 fscanf (procfile
, "\n");
140 /* Function: linux_do_thread_registers
142 * Records the thread's register state for the corefile note section.
146 linux_do_thread_registers (bfd
*obfd
, ptid_t ptid
,
147 char *note_data
, int *note_size
)
150 gdb_fpregset_t fpregs
;
151 unsigned long merged_pid
= ptid_get_tid (ptid
) << 16 | ptid_get_pid (ptid
);
153 fill_gregset (&gregs
, -1);
154 note_data
= (char *) elfcore_write_prstatus (obfd
,
161 fill_fpregset (&fpregs
, -1);
162 note_data
= (char *) elfcore_write_prfpreg (obfd
,
170 struct linux_corefile_thread_data
{
176 /* Function: linux_corefile_thread_callback
178 * Called by gdbthread.c once per thread.
179 * Records the thread's register state for the corefile note section.
183 linux_corefile_thread_callback (struct thread_info
*ti
, void *data
)
185 struct linux_corefile_thread_data
*args
= data
;
186 ptid_t saved_ptid
= inferior_ptid
;
188 inferior_ptid
= ti
->ptid
;
189 registers_changed ();
190 target_fetch_registers (-1); /* FIXME should not be necessary;
191 fill_gregset should do it automatically. */
192 args
->note_data
= linux_do_thread_registers (args
->obfd
,
196 inferior_ptid
= saved_ptid
;
197 registers_changed ();
198 target_fetch_registers (-1); /* FIXME should not be necessary;
199 fill_gregset should do it automatically. */
203 /* Function: linux_make_note_section
205 * Fills the "to_make_corefile_note" target vector.
206 * Builds the note section for a corefile, and returns it
207 * in a malloc buffer.
211 linux_make_note_section (bfd
*obfd
, int *note_size
)
213 struct linux_corefile_thread_data thread_args
;
214 struct cleanup
*old_chain
;
215 char fname
[16] = {'\0'};
216 char psargs
[80] = {'\0'};
217 char *note_data
= NULL
;
218 ptid_t current_ptid
= inferior_ptid
;
220 if (get_exec_file (0))
222 strncpy (fname
, strrchr (get_exec_file (0), '/') + 1, sizeof (fname
));
223 strncpy (psargs
, get_exec_file (0),
225 if (get_inferior_args ())
227 strncat (psargs
, " ",
228 sizeof (psargs
) - strlen (psargs
));
229 strncat (psargs
, get_inferior_args (),
230 sizeof (psargs
) - strlen (psargs
));
232 note_data
= (char *) elfcore_write_prpsinfo (obfd
,
239 /* Dump information for threads. */
240 thread_args
.obfd
= obfd
;
241 thread_args
.note_data
= note_data
;
242 thread_args
.note_size
= note_size
;
243 iterate_over_threads (linux_corefile_thread_callback
, &thread_args
);
244 if (thread_args
.note_data
== note_data
)
246 /* iterate_over_threads didn't come up with any threads;
247 just use inferior_ptid. */
248 note_data
= linux_do_thread_registers (obfd
, inferior_ptid
,
249 note_data
, note_size
);
253 note_data
= thread_args
.note_data
;
256 make_cleanup (xfree
, note_data
);
261 _initialize_linux_proc (void)
263 extern void inftarg_set_find_memory_regions ();
264 extern void inftarg_set_make_corefile_notes ();
266 inftarg_set_find_memory_regions (linux_find_memory_regions
);
267 inftarg_set_make_corefile_notes (linux_make_note_section
);