gdb
[deliverable/binutils-gdb.git] / gdb / fbsd-nat.c
CommitLineData
578c1c03
MK
1/* Native-dependent code for FreeBSD.
2
0fb0cc75
JB
3 Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009
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
95fbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long,
96 int, int, int, void *),
97 void *obfd)
98{
99 pid_t pid = ptid_get_pid (inferior_ptid);
100 char *mapfilename;
101 FILE *mapfile;
102 unsigned long start, end, size;
103 char protection[4];
104 int read, write, exec;
7c8a8b04 105 struct cleanup *cleanup;
578c1c03
MK
106
107 mapfilename = xstrprintf ("/proc/%ld/map", (long) pid);
7c8a8b04 108 cleanup = make_cleanup (xfree, mapfilename);
578c1c03
MK
109 mapfile = fopen (mapfilename, "r");
110 if (mapfile == NULL)
8a3fe4f8 111 error (_("Couldn't open %s."), mapfilename);
7c8a8b04 112 make_cleanup_fclose (mapfile);
578c1c03
MK
113
114 if (info_verbose)
115 fprintf_filtered (gdb_stdout,
116 "Reading memory regions from %s\n", mapfilename);
117
118 /* Now iterate until end-of-file. */
119 while (fbsd_read_mapping (mapfile, &start, &end, &protection[0]))
120 {
121 size = end - start;
122
123 read = (strchr (protection, 'r') != 0);
124 write = (strchr (protection, 'w') != 0);
125 exec = (strchr (protection, 'x') != 0);
126
127 if (info_verbose)
128 {
129 fprintf_filtered (gdb_stdout,
130 "Save segment, %ld bytes at 0x%s (%c%c%c)\n",
131 size, paddr_nz (start),
132 read ? 'r' : '-',
133 write ? 'w' : '-',
134 exec ? 'x' : '-');
135 }
136
137 /* Invoke the callback function to create the corefile segment. */
138 func (start, size, read, write, exec, obfd);
139 }
140
7c8a8b04 141 do_cleanups (cleanup);
578c1c03
MK
142 return 0;
143}
144
2020b7ab
PA
145static int
146find_signalled_thread (struct thread_info *info, void *data)
147{
148 if (info->stop_signal != TARGET_SIGNAL_0
149 && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
150 return 1;
151
152 return 0;
153}
154
155static enum target_signal
156find_stop_signal (void)
157{
158 struct thread_info *info =
159 iterate_over_threads (find_signalled_thread, NULL);
160
161 if (info)
162 return info->stop_signal;
163 else
164 return TARGET_SIGNAL_0;
165}
166
578c1c03
MK
167/* Create appropriate note sections for a corefile, returning them in
168 allocated memory. */
169
170char *
171fbsd_make_corefile_notes (bfd *obfd, int *note_size)
172{
594f7785 173 const struct regcache *regcache = get_current_regcache ();
9970f04b 174 struct gdbarch *gdbarch = get_regcache_arch (regcache);
578c1c03
MK
175 gregset_t gregs;
176 fpregset_t fpregs;
177 char *note_data = NULL;
178 Elf_Internal_Ehdr *i_ehdrp;
179 const struct regset *regset;
180 size_t size;
181
182 /* Put a "FreeBSD" label in the ELF header. */
183 i_ehdrp = elf_elfheader (obfd);
184 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
185
186 gdb_assert (gdbarch_regset_from_core_section_p (gdbarch));
187
188 size = sizeof gregs;
189 regset = gdbarch_regset_from_core_section (gdbarch, ".reg", size);
190 gdb_assert (regset && regset->collect_regset);
191 regset->collect_regset (regset, regcache, -1, &gregs, size);
192
193 note_data = elfcore_write_prstatus (obfd, note_data, note_size,
194 ptid_get_pid (inferior_ptid),
2020b7ab 195 find_stop_signal (), &gregs);
578c1c03
MK
196
197 size = sizeof fpregs;
198 regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", size);
199 gdb_assert (regset && regset->collect_regset);
200 regset->collect_regset (regset, regcache, -1, &fpregs, size);
201
202 note_data = elfcore_write_prfpreg (obfd, note_data, note_size,
203 &fpregs, sizeof (fpregs));
204
205 if (get_exec_file (0))
206 {
207 char *fname = strrchr (get_exec_file (0), '/') + 1;
208 char *psargs = xstrdup (fname);
209
210 if (get_inferior_args ())
211 psargs = reconcat (psargs, psargs, " ", get_inferior_args (), NULL);
212
213 note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
214 fname, psargs);
215 }
216
217 make_cleanup (xfree, note_data);
218 return note_data;
219}
This page took 0.297036 seconds and 4 git commands to generate.