fa49ac26c9bfa4ede635163c053041b902b8b4c0
[deliverable/binutils-gdb.git] / gdb / nbsd-nat.c
1 /* Native-dependent code for NetBSD.
2
3 Copyright (C) 2006-2020 Free Software Foundation, Inc.
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
9 the Free Software Foundation; either version 3 of the License, or
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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21
22 #include "nbsd-nat.h"
23 #include "gdbthread.h"
24 #include "nbsd-tdep.h"
25 #include "inferior.h"
26 #include "gdbarch.h"
27
28 #include <sys/types.h>
29 #include <sys/ptrace.h>
30 #include <sys/sysctl.h>
31
32 /* Return the name of a file that can be opened to get the symbols for
33 the child process identified by PID. */
34
35 char *
36 nbsd_nat_target::pid_to_exec_file (int pid)
37 {
38 static char buf[PATH_MAX];
39 size_t buflen;
40 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
41 buflen = sizeof (buf);
42 if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0))
43 return NULL;
44 return buf;
45 }
46
47 /* Return the current directory for the process identified by PID. */
48
49 static std::string
50 nbsd_pid_to_cwd (int pid)
51 {
52 char buf[PATH_MAX];
53 size_t buflen;
54 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD};
55 buflen = sizeof (buf);
56 if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0))
57 return "";
58 return buf;
59 }
60
61 /* Return the command line for the process identified by PID. */
62
63 static gdb::unique_xmalloc_ptr<char[]>
64 nbsd_pid_to_cmdline (int pid)
65 {
66 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
67
68 size_t size = 0;
69 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
70 return nullptr;
71
72 gdb::unique_xmalloc_ptr<char[]> args (XNEWVAR (char, size));
73
74 if (sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1
75 || size == 0)
76 return nullptr;
77
78 /* Arguments are returned as a flattened string with NUL separators.
79 Join the arguments with spaces to form a single string. */
80 for (size_t i = 0; i < size - 1; i++)
81 if (args[i] == '\0')
82 args[i] = ' ';
83 args[size - 1] = '\0';
84
85 return args;
86 }
87
88 /* Generic thread (LWP) lister within a specified process. The callback
89 parameters is a C++ function that is called for each detected thread. */
90
91 static bool
92 nbsd_thread_lister (const pid_t pid,
93 gdb::function_view<bool (const struct kinfo_lwp *)>
94 callback)
95 {
96 int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0};
97 size_t size;
98
99 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
100 perror_with_name (("sysctl"));
101
102 mib[4] = size / sizeof (size_t);
103
104 gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl
105 ((struct kinfo_lwp *) xcalloc (size, 1));
106
107 if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1
108 || size == 0)
109 perror_with_name (("sysctl"));
110
111 for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++)
112 {
113 struct kinfo_lwp *l = &kl[i];
114
115 /* Return true if the specified thread is alive. */
116 auto lwp_alive
117 = [] (struct kinfo_lwp *lwp)
118 {
119 switch (lwp->l_stat)
120 {
121 case LSSLEEP:
122 case LSRUN:
123 case LSONPROC:
124 case LSSTOP:
125 case LSSUSPENDED:
126 return true;
127 default:
128 return false;
129 }
130 };
131
132 /* Ignore embryonic or demised threads. */
133 if (!lwp_alive (l))
134 continue;
135
136 if (callback (l))
137 return true;
138 }
139
140 return false;
141 }
142
143 /* Return true if PTID is still active in the inferior. */
144
145 bool
146 nbsd_nat_target::thread_alive (ptid_t ptid)
147 {
148 pid_t pid = ptid.pid ();
149 int lwp = ptid.lwp ();
150
151 auto fn
152 = [&lwp] (const struct kinfo_lwp *kl)
153 {
154 return kl->l_lid == lwp;
155 };
156
157 return nbsd_thread_lister (pid, fn);
158 }
159
160 /* Return the name assigned to a thread by an application. Returns
161 the string in a static buffer. */
162
163 const char *
164 nbsd_nat_target::thread_name (struct thread_info *thr)
165 {
166 ptid_t ptid = thr->ptid;
167 pid_t pid = ptid.pid ();
168 int lwp = ptid.lwp ();
169
170 static char buf[KI_LNAMELEN] = {};
171
172 auto fn
173 = [&lwp] (const struct kinfo_lwp *kl)
174 {
175 if (kl->l_lid == lwp)
176 {
177 xsnprintf (buf, sizeof buf, "%s", kl->l_name);
178 return true;
179 }
180 return false;
181 };
182
183 if (nbsd_thread_lister (pid, fn))
184 return buf;
185 else
186 return NULL;
187 }
188
189 /* Implement the "post_attach" target_ops method. */
190
191 static void
192 nbsd_add_threads (nbsd_nat_target *target, pid_t pid)
193 {
194 auto fn
195 = [&target, &pid] (const struct kinfo_lwp *kl)
196 {
197 ptid_t ptid = ptid_t (pid, kl->l_lid, 0);
198 if (!in_thread_list (target, ptid))
199 {
200 if (inferior_ptid.lwp () == 0)
201 thread_change_ptid (target, inferior_ptid, ptid);
202 else
203 add_thread (target, ptid);
204 }
205 return false;
206 };
207
208 nbsd_thread_lister (pid, fn);
209 }
210
211 /* Implement the "post_attach" target_ops method. */
212
213 void
214 nbsd_nat_target::post_attach (int pid)
215 {
216 nbsd_add_threads (this, pid);
217 }
218
219 /* Implement the "update_thread_list" target_ops method. */
220
221 void
222 nbsd_nat_target::update_thread_list ()
223 {
224 prune_threads ();
225
226 nbsd_add_threads (this, inferior_ptid.pid ());
227 }
228
229 /* Convert PTID to a string. */
230
231 std::string
232 nbsd_nat_target::pid_to_str (ptid_t ptid)
233 {
234 int lwp = ptid.lwp ();
235
236 if (lwp != 0)
237 {
238 pid_t pid = ptid.pid ();
239
240 return string_printf ("LWP %d of process %d", lwp, pid);
241 }
242
243 return normal_pid_to_str (ptid);
244 }
245
246 /* Retrieve all the memory regions in the specified process. */
247
248 static gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]>
249 nbsd_kinfo_get_vmmap (pid_t pid, size_t *size)
250 {
251 int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid,
252 sizeof (struct kinfo_vmentry)};
253
254 size_t length = 0;
255 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0))
256 {
257 *size = 0;
258 return NULL;
259 }
260
261 /* Prereserve more space. The length argument is volatile and can change
262 between the sysctl(3) calls as this function can be called against a
263 running process. */
264 length = length * 5 / 3;
265
266 gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> kiv
267 (XNEWVAR (kinfo_vmentry, length));
268
269 if (sysctl (mib, ARRAY_SIZE (mib), kiv.get (), &length, NULL, 0))
270 {
271 *size = 0;
272 return NULL;
273 }
274
275 *size = length / sizeof (struct kinfo_vmentry);
276 return kiv;
277 }
278
279 /* Iterate over all the memory regions in the current inferior,
280 calling FUNC for each memory region. OBFD is passed as the last
281 argument to FUNC. */
282
283 int
284 nbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
285 void *data)
286 {
287 pid_t pid = inferior_ptid.pid ();
288
289 size_t nitems;
290 gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl
291 = nbsd_kinfo_get_vmmap (pid, &nitems);
292 if (vmentl == NULL)
293 perror_with_name (_("Couldn't fetch VM map entries."));
294
295 for (size_t i = 0; i < nitems; i++)
296 {
297 struct kinfo_vmentry *kve = &vmentl[i];
298
299 /* Skip unreadable segments and those where MAP_NOCORE has been set. */
300 if (!(kve->kve_protection & KVME_PROT_READ)
301 || kve->kve_flags & KVME_FLAG_NOCOREDUMP)
302 continue;
303
304 /* Skip segments with an invalid type. */
305 switch (kve->kve_type)
306 {
307 case KVME_TYPE_VNODE:
308 case KVME_TYPE_ANON:
309 case KVME_TYPE_SUBMAP:
310 case KVME_TYPE_OBJECT:
311 break;
312 default:
313 continue;
314 }
315
316 size_t size = kve->kve_end - kve->kve_start;
317 if (info_verbose)
318 {
319 fprintf_filtered (gdb_stdout,
320 "Save segment, %ld bytes at %s (%c%c%c)\n",
321 (long) size,
322 paddress (target_gdbarch (), kve->kve_start),
323 kve->kve_protection & KVME_PROT_READ ? 'r' : '-',
324 kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-',
325 kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-');
326 }
327
328 /* Invoke the callback function to create the corefile segment.
329 Pass MODIFIED as true, we do not know the real modification state. */
330 func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ,
331 kve->kve_protection & KVME_PROT_WRITE,
332 kve->kve_protection & KVME_PROT_EXEC, 1, data);
333 }
334 return 0;
335 }
336
337 /* Implement the "info_proc" target_ops method. */
338
339 bool
340 nbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
341 {
342 pid_t pid;
343 bool do_cmdline = false;
344 bool do_cwd = false;
345 bool do_exe = false;
346 bool do_mappings = false;
347
348 switch (what)
349 {
350 case IP_MAPPINGS:
351 do_mappings = true;
352 break;
353 case IP_CMDLINE:
354 do_cmdline = true;
355 break;
356 case IP_EXE:
357 do_exe = true;
358 break;
359 case IP_CWD:
360 do_cwd = true;
361 break;
362 default:
363 error (_("Not supported on this target."));
364 }
365
366 gdb_argv built_argv (args);
367 if (built_argv.count () == 0)
368 {
369 pid = inferior_ptid.pid ();
370 if (pid == 0)
371 error (_("No current process: you must name one."));
372 }
373 else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
374 pid = strtol (built_argv[0], NULL, 10);
375 else
376 error (_("Invalid arguments."));
377
378 printf_filtered (_("process %d\n"), pid);
379
380 if (do_cmdline)
381 {
382 gdb::unique_xmalloc_ptr<char[]> cmdline = nbsd_pid_to_cmdline (pid);
383 if (cmdline != nullptr)
384 printf_filtered ("cmdline = '%s'\n", cmdline.get ());
385 else
386 warning (_("unable to fetch command line"));
387 }
388 if (do_cwd)
389 {
390 std::string cwd = nbsd_pid_to_cwd (pid);
391 if (cwd != "")
392 printf_filtered ("cwd = '%s'\n", cwd.c_str ());
393 else
394 warning (_("unable to fetch current working directory"));
395 }
396 if (do_exe)
397 {
398 const char *exe = pid_to_exec_file (pid);
399 if (exe != nullptr)
400 printf_filtered ("exe = '%s'\n", exe);
401 else
402 warning (_("unable to fetch executable path name"));
403 }
404 if (do_mappings)
405 {
406 size_t nvment;
407 gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl
408 = nbsd_kinfo_get_vmmap (pid, &nvment);
409
410 if (vmentl != nullptr)
411 {
412 int addr_bit = TARGET_CHAR_BIT * sizeof (void *);
413 nbsd_info_proc_mappings_header (addr_bit);
414
415 struct kinfo_vmentry *kve = vmentl.get ();
416 for (int i = 0; i < nvment; i++, kve++)
417 nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start,
418 kve->kve_end, kve->kve_offset,
419 kve->kve_flags, kve->kve_protection,
420 kve->kve_path);
421 }
422 else
423 warning (_("unable to fetch virtual memory map"));
424 }
425
426 return true;
427 }
This page took 0.038465 seconds and 3 git commands to generate.