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