gdb/
[deliverable/binutils-gdb.git] / gdb / fbsd-nat.c
CommitLineData
578c1c03
MK
1/* Native-dependent code for FreeBSD.
2
4c38e0a4 3 Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010
0fb0cc75 4 Free Software Foundation, Inc.
578c1c03
MK
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
578c1c03
MK
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
578c1c03
MK
20
21#include "defs.h"
22#include "gdbcore.h"
23#include "inferior.h"
24#include "regcache.h"
25#include "regset.h"
2020b7ab 26#include "gdbthread.h"
578c1c03
MK
27
28#include "gdb_assert.h"
29#include "gdb_string.h"
578c1c03 30#include <sys/types.h>
68b9939a
MK
31#include <sys/procfs.h>
32#include <sys/sysctl.h>
578c1c03
MK
33
34#include "elf-bfd.h"
35#include "fbsd-nat.h"
36
37/* Return a the name of file that can be opened to get the symbols for
38 the child process identified by PID. */
39
40char *
41fbsd_pid_to_exec_file (int pid)
42{
68b9939a
MK
43 size_t len = MAXPATHLEN;
44 char *buf = xcalloc (len, sizeof (char));
578c1c03 45 char *path;
578c1c03 46
68b9939a
MK
47#ifdef KERN_PROC_PATHNAME
48 int mib[4];
578c1c03 49
68b9939a
MK
50 mib[0] = CTL_KERN;
51 mib[1] = KERN_PROC;
52 mib[2] = KERN_PROC_PATHNAME;
53 mib[3] = pid;
54 if (sysctl (mib, 4, buf, &len, NULL, 0) == 0)
578c1c03 55 return buf;
68b9939a 56#endif
578c1c03 57
68b9939a
MK
58 path = xstrprintf ("/proc/%d/file", pid);
59 if (readlink (path, buf, MAXPATHLEN) == -1)
60 {
61 xfree (buf);
62 buf = NULL;
63 }
64
65 xfree (path);
66 return buf;
578c1c03
MK
67}
68
69static int
70fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end,
71 char *protection)
72{
73 /* FreeBSD 5.1-RELEASE uses a 256-byte buffer. */
74 char buf[256];
75 int resident, privateresident;
76 unsigned long obj;
77 int ret = EOF;
78
79 /* As of FreeBSD 5.0-RELEASE, the layout is described in
80 /usr/src/sys/fs/procfs/procfs_map.c. Somewhere in 5.1-CURRENT a
81 new column was added to the procfs map. Therefore we can't use
82 fscanf since we need to support older releases too. */
83 if (fgets (buf, sizeof buf, mapfile) != NULL)
84 ret = sscanf (buf, "%lx %lx %d %d %lx %s", start, end,
85 &resident, &privateresident, &obj, protection);
86
87 return (ret != 0 && ret != EOF);
88}
89
90/* Iterate over all the memory regions in the current inferior,
91 calling FUNC for each memory region. OBFD is passed as the last
92 argument to FUNC. */
93
94int
b8edc417 95fbsd_find_memory_regions (find_memory_region_ftype func, void *obfd)
578c1c03
MK
96{
97 pid_t pid = ptid_get_pid (inferior_ptid);
98 char *mapfilename;
99 FILE *mapfile;
100 unsigned long start, end, size;
101 char protection[4];
102 int read, write, exec;
7c8a8b04 103 struct cleanup *cleanup;
578c1c03
MK
104
105 mapfilename = xstrprintf ("/proc/%ld/map", (long) pid);
7c8a8b04 106 cleanup = make_cleanup (xfree, mapfilename);
578c1c03
MK
107 mapfile = fopen (mapfilename, "r");
108 if (mapfile == NULL)
8a3fe4f8 109 error (_("Couldn't open %s."), mapfilename);
7c8a8b04 110 make_cleanup_fclose (mapfile);
578c1c03
MK
111
112 if (info_verbose)
113 fprintf_filtered (gdb_stdout,
114 "Reading memory regions from %s\n", mapfilename);
115
116 /* Now iterate until end-of-file. */
117 while (fbsd_read_mapping (mapfile, &start, &end, &protection[0]))
118 {
119 size = end - start;
120
121 read = (strchr (protection, 'r') != 0);
122 write = (strchr (protection, 'w') != 0);
123 exec = (strchr (protection, 'x') != 0);
124
125 if (info_verbose)
126 {
127 fprintf_filtered (gdb_stdout,
5af949e3
UW
128 "Save segment, %ld bytes at %s (%c%c%c)\n",
129 size, paddress (target_gdbarch, start),
578c1c03
MK
130 read ? 'r' : '-',
131 write ? 'w' : '-',
132 exec ? 'x' : '-');
133 }
134
135 /* Invoke the callback function to create the corefile segment. */
136 func (start, size, read, write, exec, obfd);
137 }
138
7c8a8b04 139 do_cleanups (cleanup);
578c1c03
MK
140 return 0;
141}
142
2020b7ab
PA
143static int
144find_signalled_thread (struct thread_info *info, void *data)
145{
146 if (info->stop_signal != TARGET_SIGNAL_0
147 && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
148 return 1;
149
150 return 0;
151}
152
153static enum target_signal
154find_stop_signal (void)
155{
156 struct thread_info *info =
157 iterate_over_threads (find_signalled_thread, NULL);
158
159 if (info)
160 return info->stop_signal;
161 else
162 return TARGET_SIGNAL_0;
163}
164
578c1c03
MK
165/* Create appropriate note sections for a corefile, returning them in
166 allocated memory. */
167
168char *
169fbsd_make_corefile_notes (bfd *obfd, int *note_size)
170{
594f7785 171 const struct regcache *regcache = get_current_regcache ();
9970f04b 172 struct gdbarch *gdbarch = get_regcache_arch (regcache);
578c1c03
MK
173 gregset_t gregs;
174 fpregset_t fpregs;
175 char *note_data = NULL;
176 Elf_Internal_Ehdr *i_ehdrp;
177 const struct regset *regset;
178 size_t size;
179
180 /* Put a "FreeBSD" label in the ELF header. */
181 i_ehdrp = elf_elfheader (obfd);
182 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
183
184 gdb_assert (gdbarch_regset_from_core_section_p (gdbarch));
185
186 size = sizeof gregs;
187 regset = gdbarch_regset_from_core_section (gdbarch, ".reg", size);
188 gdb_assert (regset && regset->collect_regset);
189 regset->collect_regset (regset, regcache, -1, &gregs, size);
190
191 note_data = elfcore_write_prstatus (obfd, note_data, note_size,
192 ptid_get_pid (inferior_ptid),
2020b7ab 193 find_stop_signal (), &gregs);
578c1c03
MK
194
195 size = sizeof fpregs;
196 regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", size);
197 gdb_assert (regset && regset->collect_regset);
198 regset->collect_regset (regset, regcache, -1, &fpregs, size);
199
200 note_data = elfcore_write_prfpreg (obfd, note_data, note_size,
201 &fpregs, sizeof (fpregs));
202
203 if (get_exec_file (0))
204 {
205 char *fname = strrchr (get_exec_file (0), '/') + 1;
206 char *psargs = xstrdup (fname);
207
208 if (get_inferior_args ())
3f1f6884
JK
209 psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
210 (char *) NULL);
578c1c03
MK
211
212 note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
213 fname, psargs);
214 }
215
216 make_cleanup (xfree, note_data);
217 return note_data;
218}
This page took 0.407424 seconds and 4 git commands to generate.