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