* darwin-nat-info.c (darwin_debug_regions_recurse): Use
[deliverable/binutils-gdb.git] / gdb / darwin-nat-info.c
1 /* Darwin support for GDB, the GNU debugger.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2008
3 Free Software Foundation, Inc.
4
5 Contributed by Apple Computer, Inc.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 /* The name of the ppc_thread_state structure, and the names of its
25 members, have been changed for Unix conformance reasons. The easiest
26 way to have gdb build on systems with the older names and systems
27 with the newer names is to build this compilation unit with the
28 non-conformant define below. This doesn't seem to cause the resulting
29 binary any problems but it seems like it could cause us problems in
30 the future. It'd be good to remove this at some point when compiling on
31 Tiger is no longer important. */
32
33 #include "defs.h"
34 #include "symtab.h"
35 #include "gdbtypes.h"
36 #include "gdbcore.h"
37 #include "value.h"
38 #include "gdbcmd.h"
39 #include "inferior.h"
40
41 #include <sys/param.h>
42 #include <sys/sysctl.h>
43
44 #include "darwin-nat.h"
45
46 #include <mach/thread_info.h>
47 #include <mach/thread_act.h>
48 #include <mach/task.h>
49 #include <mach/vm_map.h>
50 #include <mach/mach_port.h>
51 #include <mach/mach_init.h>
52 #include <mach/mach_vm.h>
53
54 #define CHECK_ARGS(what, args) do { \
55 if ((NULL == args) || ((args[0] != '0') && (args[1] != 'x'))) \
56 error("%s must be specified with 0x...", what); \
57 } while (0)
58
59 #define PRINT_FIELD(structure, field) \
60 printf_unfiltered(_(#field":\t%#lx\n"), (unsigned long) (structure)->field)
61
62 #define PRINT_TV_FIELD(structure, field) \
63 printf_unfiltered(_(#field":\t%u.%06u sec\n"), \
64 (unsigned) (structure)->field.seconds, \
65 (unsigned) (structure)->field.microseconds)
66
67 #define task_self mach_task_self
68 #define task_by_unix_pid task_for_pid
69 #define port_name_array_t mach_port_array_t
70 #define port_type_array_t mach_port_array_t
71
72 static void
73 info_mach_tasks_command (char *args, int from_tty)
74 {
75 int sysControl[4];
76 int count, index;
77 size_t length;
78 struct kinfo_proc *procInfo;
79
80 sysControl[0] = CTL_KERN;
81 sysControl[1] = KERN_PROC;
82 sysControl[2] = KERN_PROC_ALL;
83
84 sysctl (sysControl, 3, NULL, &length, NULL, 0);
85 procInfo = (struct kinfo_proc *) xmalloc (length);
86 sysctl (sysControl, 3, procInfo, &length, NULL, 0);
87
88 count = (length / sizeof (struct kinfo_proc));
89 printf_unfiltered (_("%d processes:\n"), count);
90 for (index = 0; index < count; ++index)
91 {
92 kern_return_t result;
93 mach_port_t taskPort;
94
95 result =
96 task_by_unix_pid (mach_task_self (), procInfo[index].kp_proc.p_pid,
97 &taskPort);
98 if (KERN_SUCCESS == result)
99 {
100 printf_unfiltered (_(" %s is %d has task %#x\n"),
101 procInfo[index].kp_proc.p_comm,
102 procInfo[index].kp_proc.p_pid, taskPort);
103 }
104 else
105 {
106 printf_unfiltered (_(" %s is %d unknown task port\n"),
107 procInfo[index].kp_proc.p_comm,
108 procInfo[index].kp_proc.p_pid);
109 }
110 }
111
112 xfree (procInfo);
113 }
114
115 static task_t
116 get_task_from_args (char *args)
117 {
118 task_t task;
119 char *eptr;
120
121 if (args == NULL || *args == 0)
122 {
123 if (ptid_equal (inferior_ptid, null_ptid))
124 printf_unfiltered (_("No inferior running\n"));
125 return current_inferior ()->private->task;
126 }
127 if (strcmp (args, "gdb") == 0)
128 return mach_task_self ();
129 task = strtoul (args, &eptr, 0);
130 if (*eptr)
131 {
132 printf_unfiltered (_("cannot parse task id '%s'\n"), args);
133 return TASK_NULL;
134 }
135 return task;
136 }
137
138 static void
139 info_mach_task_command (char *args, int from_tty)
140 {
141 union
142 {
143 struct task_basic_info basic;
144 struct task_events_info events;
145 struct task_thread_times_info thread_times;
146 } task_info_data;
147
148 kern_return_t result;
149 unsigned int info_count;
150 task_t task;
151
152 task = get_task_from_args (args);
153 if (task == TASK_NULL)
154 return;
155
156 printf_unfiltered (_("TASK_BASIC_INFO for 0x%x:\n"), task);
157 info_count = TASK_BASIC_INFO_COUNT;
158 result = task_info (task,
159 TASK_BASIC_INFO,
160 (task_info_t) & task_info_data.basic, &info_count);
161 MACH_CHECK_ERROR (result);
162
163 PRINT_FIELD (&task_info_data.basic, suspend_count);
164 PRINT_FIELD (&task_info_data.basic, virtual_size);
165 PRINT_FIELD (&task_info_data.basic, resident_size);
166 PRINT_TV_FIELD (&task_info_data.basic, user_time);
167 PRINT_TV_FIELD (&task_info_data.basic, system_time);
168 printf_unfiltered (_("\nTASK_EVENTS_INFO:\n"));
169 info_count = TASK_EVENTS_INFO_COUNT;
170 result = task_info (task,
171 TASK_EVENTS_INFO,
172 (task_info_t) & task_info_data.events, &info_count);
173 MACH_CHECK_ERROR (result);
174
175 PRINT_FIELD (&task_info_data.events, faults);
176 #if 0
177 PRINT_FIELD (&task_info_data.events, zero_fills);
178 PRINT_FIELD (&task_info_data.events, reactivations);
179 #endif
180 PRINT_FIELD (&task_info_data.events, pageins);
181 PRINT_FIELD (&task_info_data.events, cow_faults);
182 PRINT_FIELD (&task_info_data.events, messages_sent);
183 PRINT_FIELD (&task_info_data.events, messages_received);
184 printf_unfiltered (_("\nTASK_THREAD_TIMES_INFO:\n"));
185 info_count = TASK_THREAD_TIMES_INFO_COUNT;
186 result = task_info (task,
187 TASK_THREAD_TIMES_INFO,
188 (task_info_t) & task_info_data.thread_times,
189 &info_count);
190 MACH_CHECK_ERROR (result);
191 PRINT_TV_FIELD (&task_info_data.thread_times, user_time);
192 PRINT_TV_FIELD (&task_info_data.thread_times, system_time);
193 }
194
195 static void
196 info_mach_ports_command (char *args, int from_tty)
197 {
198 port_name_array_t names;
199 port_type_array_t types;
200 unsigned int name_count, type_count;
201 kern_return_t result;
202 int index;
203 task_t task;
204
205 task = get_task_from_args (args);
206 if (task == TASK_NULL)
207 return;
208
209 result = mach_port_names (task, &names, &name_count, &types, &type_count);
210 MACH_CHECK_ERROR (result);
211
212 gdb_assert (name_count == type_count);
213
214 printf_unfiltered (_("Ports for task 0x%x:\n"), task);
215 printf_unfiltered (_("port type\n"));
216 for (index = 0; index < name_count; ++index)
217 {
218 mach_port_t port = names[index];
219 unsigned int j;
220 struct type_descr
221 {
222 mach_port_type_t type;
223 const char *name;
224 mach_port_right_t right;
225 };
226 static struct type_descr descrs[] =
227 {
228 {MACH_PORT_TYPE_SEND, "send", MACH_PORT_RIGHT_SEND},
229 {MACH_PORT_TYPE_SEND_ONCE, "send-once", MACH_PORT_RIGHT_SEND_ONCE},
230 {MACH_PORT_TYPE_RECEIVE, "receive", MACH_PORT_RIGHT_RECEIVE},
231 {MACH_PORT_TYPE_PORT_SET, "port-set", MACH_PORT_RIGHT_PORT_SET},
232 {MACH_PORT_TYPE_DEAD_NAME, "dead", MACH_PORT_RIGHT_DEAD_NAME}
233 };
234
235 printf_unfiltered (_("%04x: %08x "), port, types[index]);
236 for (j = 0; j < sizeof(descrs) / sizeof(*descrs); j++)
237 if (types[index] & descrs[j].type)
238 {
239 mach_port_urefs_t ref;
240 kern_return_t ret;
241
242 printf_unfiltered (_(" %s("), descrs[j].name);
243 ret = mach_port_get_refs (task, port, descrs[j].right, &ref);
244 if (ret != KERN_SUCCESS)
245 printf_unfiltered (_("??"));
246 else
247 printf_unfiltered (_("%u"), ref);
248 printf_unfiltered (_(" refs)"));
249 }
250
251 if (task == task_self ())
252 {
253 if (port == task_self())
254 printf_unfiltered (_(" gdb-task"));
255 else if (port == darwin_host_self)
256 printf_unfiltered (_(" host-self"));
257 else if (port == darwin_ex_port)
258 printf_unfiltered (_(" gdb-exception"));
259 else if (port == darwin_port_set)
260 printf_unfiltered (_(" gdb-port_set"));
261 else if (!ptid_equal (inferior_ptid, null_ptid))
262 {
263 struct inferior *inf = current_inferior ();
264
265 if (port == inf->private->task)
266 printf_unfiltered (_(" inferior-task"));
267 else if (port == inf->private->notify_port)
268 printf_unfiltered (_(" inferior-notify"));
269 else
270 {
271 int k;
272 darwin_thread_t *t;
273
274 for (k = 0; k < inf->private->exception_info.count; k++)
275 if (port == inf->private->exception_info.ports[k])
276 {
277 printf_unfiltered (_(" inferior-excp-port"));
278 break;
279 }
280
281 if (inf->private->threads)
282 {
283 for (k = 0;
284 VEC_iterate(darwin_thread_t,
285 inf->private->threads, k, t);
286 k++)
287 if (port == t->gdb_port)
288 {
289 printf_unfiltered (_(" inferior-thread for 0x%x"),
290 inf->private->task);
291 break;
292 }
293 }
294 }
295 }
296 }
297 printf_unfiltered (_("\n"));
298 }
299
300 vm_deallocate (task_self (), (vm_address_t) names,
301 (name_count * sizeof (mach_port_t)));
302 vm_deallocate (task_self (), (vm_address_t) types,
303 (type_count * sizeof (mach_port_type_t)));
304 }
305
306
307 void
308 darwin_debug_port_info (task_t task, mach_port_t port)
309 {
310 kern_return_t kret;
311 mach_port_status_t status;
312 mach_msg_type_number_t len = sizeof (status);
313
314 kret = mach_port_get_attributes
315 (task, port, MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &len);
316 MACH_CHECK_ERROR (kret);
317
318 printf_unfiltered (_("Port 0x%lx in task 0x%lx:\n"), (unsigned long) port,
319 (unsigned long) task);
320 printf_unfiltered (_(" port set: 0x%x\n"), status.mps_pset);
321 printf_unfiltered (_(" seqno: 0x%x\n"), status.mps_seqno);
322 printf_unfiltered (_(" mscount: 0x%x\n"), status.mps_mscount);
323 printf_unfiltered (_(" qlimit: 0x%x\n"), status.mps_qlimit);
324 printf_unfiltered (_(" msgcount: 0x%x\n"), status.mps_msgcount);
325 printf_unfiltered (_(" sorights: 0x%x\n"), status.mps_sorights);
326 printf_unfiltered (_(" srights: 0x%x\n"), status.mps_srights);
327 printf_unfiltered (_(" pdrequest: 0x%x\n"), status.mps_pdrequest);
328 printf_unfiltered (_(" nsrequest: 0x%x\n"), status.mps_nsrequest);
329 printf_unfiltered (_(" flags: 0x%x\n"), status.mps_flags);
330 }
331
332 static void
333 info_mach_port_command (char *args, int from_tty)
334 {
335 task_t task;
336 mach_port_t port;
337
338 CHECK_ARGS (_("Task and port"), args);
339 sscanf (args, "0x%x 0x%x", &task, &port);
340
341 darwin_debug_port_info (task, port);
342 }
343
344 static void
345 info_mach_threads_command (char *args, int from_tty)
346 {
347 thread_array_t threads;
348 unsigned int thread_count;
349 kern_return_t result;
350 task_t task;
351 int i;
352
353 task = get_task_from_args (args);
354 if (task == TASK_NULL)
355 return;
356
357 result = task_threads (task, &threads, &thread_count);
358 MACH_CHECK_ERROR (result);
359
360 printf_unfiltered (_("Threads in task %#x:\n"), task);
361 for (i = 0; i < thread_count; ++i)
362 {
363 printf_unfiltered (_(" %#x\n"), threads[i]);
364 mach_port_deallocate (task_self (), threads[i]);
365 }
366
367 vm_deallocate (task_self (), (vm_address_t) threads,
368 (thread_count * sizeof (thread_t)));
369 }
370
371 static void
372 info_mach_thread_command (char *args, int from_tty)
373 {
374 union
375 {
376 struct thread_basic_info basic;
377 } thread_info_data;
378
379 thread_t thread;
380 kern_return_t result;
381 unsigned int info_count;
382
383 CHECK_ARGS (_("Thread"), args);
384 sscanf (args, "0x%x", &thread);
385
386 printf_unfiltered (_("THREAD_BASIC_INFO\n"));
387 info_count = THREAD_BASIC_INFO_COUNT;
388 result = thread_info (thread,
389 THREAD_BASIC_INFO,
390 (thread_info_t) & thread_info_data.basic,
391 &info_count);
392 MACH_CHECK_ERROR (result);
393
394 #if 0
395 PRINT_FIELD (&thread_info_data.basic, user_time);
396 PRINT_FIELD (&thread_info_data.basic, system_time);
397 #endif
398 PRINT_FIELD (&thread_info_data.basic, cpu_usage);
399 PRINT_FIELD (&thread_info_data.basic, run_state);
400 PRINT_FIELD (&thread_info_data.basic, flags);
401 PRINT_FIELD (&thread_info_data.basic, suspend_count);
402 PRINT_FIELD (&thread_info_data.basic, sleep_time);
403 }
404
405 static const char *
406 unparse_protection (vm_prot_t p)
407 {
408 switch (p)
409 {
410 case VM_PROT_NONE:
411 return "---";
412 case VM_PROT_READ:
413 return "r--";
414 case VM_PROT_WRITE:
415 return "-w-";
416 case VM_PROT_READ | VM_PROT_WRITE:
417 return "rw-";
418 case VM_PROT_EXECUTE:
419 return "--x";
420 case VM_PROT_EXECUTE | VM_PROT_READ:
421 return "r-x";
422 case VM_PROT_EXECUTE | VM_PROT_WRITE:
423 return "-wx";
424 case VM_PROT_EXECUTE | VM_PROT_WRITE | VM_PROT_READ:
425 return "rwx";
426 default:
427 return "???";
428 }
429 }
430
431 static const char *
432 unparse_inheritance (vm_inherit_t i)
433 {
434 switch (i)
435 {
436 case VM_INHERIT_SHARE:
437 return _("share");
438 case VM_INHERIT_COPY:
439 return _("copy ");
440 case VM_INHERIT_NONE:
441 return _("none ");
442 default:
443 return _("??? ");
444 }
445 }
446
447 static const char *
448 unparse_share_mode (unsigned char p)
449 {
450 switch (p)
451 {
452 case SM_COW:
453 return _("cow");
454 case SM_PRIVATE:
455 return _("private");
456 case SM_EMPTY:
457 return _("empty");
458 case SM_SHARED:
459 return _("shared");
460 case SM_TRUESHARED:
461 return _("true-shrd");
462 case SM_PRIVATE_ALIASED:
463 return _("prv-alias");
464 case SM_SHARED_ALIASED:
465 return _("shr-alias");
466 default:
467 return _("???");
468 }
469 }
470
471 static const char *
472 unparse_user_tag (unsigned int tag)
473 {
474 switch (tag)
475 {
476 case 0:
477 return _("default");
478 case VM_MEMORY_MALLOC:
479 return _("malloc");
480 case VM_MEMORY_MALLOC_SMALL:
481 return _("malloc_small");
482 case VM_MEMORY_MALLOC_LARGE:
483 return _("malloc_large");
484 case VM_MEMORY_MALLOC_HUGE:
485 return _("malloc_huge");
486 case VM_MEMORY_SBRK:
487 return _("sbrk");
488 case VM_MEMORY_REALLOC:
489 return _("realloc");
490 case VM_MEMORY_MALLOC_TINY:
491 return _("malloc_tiny");
492 case VM_MEMORY_ANALYSIS_TOOL:
493 return _("analysis_tool");
494 case VM_MEMORY_MACH_MSG:
495 return _("mach_msg");
496 case VM_MEMORY_IOKIT:
497 return _("iokit");
498 case VM_MEMORY_STACK:
499 return _("stack");
500 case VM_MEMORY_GUARD:
501 return _("guard");
502 case VM_MEMORY_SHARED_PMAP:
503 return _("shared_pmap");
504 case VM_MEMORY_DYLIB:
505 return _("dylib");
506 case VM_MEMORY_APPKIT:
507 return _("appkit");
508 case VM_MEMORY_FOUNDATION:
509 return _("foundation");
510 default:
511 return NULL;
512 }
513 }
514
515 static void
516 darwin_debug_regions (task_t task, mach_vm_address_t address, int max)
517 {
518 kern_return_t kret;
519 vm_region_basic_info_data_64_t info, prev_info;
520 mach_vm_address_t prev_address;
521 mach_vm_size_t size, prev_size;
522
523 mach_port_t object_name;
524 mach_msg_type_number_t count;
525
526 int nsubregions = 0;
527 int num_printed = 0;
528
529 count = VM_REGION_BASIC_INFO_COUNT_64;
530 kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO_64,
531 (vm_region_info_t) &info, &count, &object_name);
532 if (kret != KERN_SUCCESS)
533 {
534 printf_filtered (_("No memory regions."));
535 return;
536 }
537 memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
538 prev_address = address;
539 prev_size = size;
540 nsubregions = 1;
541
542 for (;;)
543 {
544 int print = 0;
545 int done = 0;
546
547 address = prev_address + prev_size;
548
549 /* Check to see if address space has wrapped around. */
550 if (address == 0)
551 print = done = 1;
552
553 if (!done)
554 {
555 count = VM_REGION_BASIC_INFO_COUNT_64;
556 kret =
557 mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO_64,
558 (vm_region_info_t) &info, &count, &object_name);
559 if (kret != KERN_SUCCESS)
560 {
561 size = 0;
562 print = done = 1;
563 }
564 }
565
566 if (address != prev_address + prev_size)
567 print = 1;
568
569 if ((info.protection != prev_info.protection)
570 || (info.max_protection != prev_info.max_protection)
571 || (info.inheritance != prev_info.inheritance)
572 || (info.shared != prev_info.reserved)
573 || (info.reserved != prev_info.reserved))
574 print = 1;
575
576 if (print)
577 {
578 printf_filtered (_("%s-%s %s/%s %s %s %s"),
579 paddr(prev_address),
580 paddr(prev_address + prev_size),
581 unparse_protection (prev_info.protection),
582 unparse_protection (prev_info.max_protection),
583 unparse_inheritance (prev_info.inheritance),
584 prev_info.shared ? _("shrd") : _("priv"),
585 prev_info.reserved ? _("reserved") : _("not-rsvd"));
586
587 if (nsubregions > 1)
588 printf_filtered (_(" (%d sub-rgn)"), nsubregions);
589
590 printf_filtered (_("\n"));
591
592 prev_address = address;
593 prev_size = size;
594 memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
595 nsubregions = 1;
596
597 num_printed++;
598 }
599 else
600 {
601 prev_size += size;
602 nsubregions++;
603 }
604
605 if ((max > 0) && (num_printed >= max))
606 done = 1;
607
608 if (done)
609 break;
610 }
611 }
612
613 static void
614 darwin_debug_regions_recurse (task_t task)
615 {
616 mach_vm_address_t r_addr;
617 mach_vm_address_t r_start;
618 mach_vm_size_t r_size;
619 natural_t r_depth;
620 mach_msg_type_number_t r_info_size;
621 vm_region_submap_short_info_data_64_t r_info;
622 kern_return_t kret;
623 int ret;
624 struct cleanup *table_chain;
625
626 table_chain = make_cleanup_ui_out_table_begin_end (uiout, 9, -1, "regions");
627
628 if (gdbarch_addr_bit (target_gdbarch) <= 32)
629 {
630 ui_out_table_header (uiout, 10, ui_left, "start", "Start");
631 ui_out_table_header (uiout, 10, ui_left, "end", "End");
632 }
633 else
634 {
635 ui_out_table_header (uiout, 18, ui_left, "start", "Start");
636 ui_out_table_header (uiout, 18, ui_left, "end", "End");
637 }
638 ui_out_table_header (uiout, 3, ui_left, "min-prot", "Min");
639 ui_out_table_header (uiout, 3, ui_left, "max-prot", "Max");
640 ui_out_table_header (uiout, 5, ui_left, "inheritence", "Inh");
641 ui_out_table_header (uiout, 9, ui_left, "share-mode", "Shr");
642 ui_out_table_header (uiout, 1, ui_left, "depth", "D");
643 ui_out_table_header (uiout, 3, ui_left, "submap", "Sm");
644 ui_out_table_header (uiout, 0, ui_noalign, "tag", "Tag");
645
646 ui_out_table_body (uiout);
647
648 r_start = 0;
649 r_depth = 0;
650 while (1)
651 {
652 const char *tag;
653 struct cleanup *row_chain;
654
655 r_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
656 r_size = -1;
657 kret = mach_vm_region_recurse (task, &r_start, &r_size, &r_depth,
658 (vm_region_recurse_info_t) &r_info,
659 &r_info_size);
660 if (kret != KERN_SUCCESS)
661 break;
662 row_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "regions-row");
663
664 ui_out_field_core_addr (uiout, "start", r_start);
665 ui_out_field_core_addr (uiout, "end", r_start + r_size);
666 ui_out_field_string (uiout, "min-prot",
667 unparse_protection (r_info.protection));
668 ui_out_field_string (uiout, "max-prot",
669 unparse_protection (r_info.max_protection));
670 ui_out_field_string (uiout, "inheritence",
671 unparse_inheritance (r_info.inheritance));
672 ui_out_field_string (uiout, "share-mode",
673 unparse_share_mode (r_info.share_mode));
674 ui_out_field_int (uiout, "depth", r_depth);
675 ui_out_field_string (uiout, "submap",
676 r_info.is_submap ? _("sm ") : _("obj"));
677 tag = unparse_user_tag (r_info.user_tag);
678 if (tag)
679 ui_out_field_string (uiout, "tag", tag);
680 else
681 ui_out_field_int (uiout, "tag", r_info.user_tag);
682
683 do_cleanups (row_chain);
684
685 if (!ui_out_is_mi_like_p (uiout))
686 ui_out_text (uiout, "\n");
687
688 if (r_info.is_submap)
689 r_depth++;
690 else
691 r_start += r_size;
692 }
693 do_cleanups (table_chain);
694
695 }
696
697
698 static void
699 darwin_debug_region (task_t task, mach_vm_address_t address)
700 {
701 darwin_debug_regions (task, address, 1);
702 }
703
704 static void
705 info_mach_regions_command (char *args, int from_tty)
706 {
707 task_t task;
708
709 task = get_task_from_args (args);
710 if (task == TASK_NULL)
711 return;
712
713 darwin_debug_regions (task, 0, -1);
714 }
715
716 static void
717 info_mach_regions_recurse_command (char *args, int from_tty)
718 {
719 task_t task;
720
721 task = get_task_from_args (args);
722 if (task == TASK_NULL)
723 return;
724
725 darwin_debug_regions_recurse (task);
726 }
727
728 static void
729 info_mach_region_command (char *exp, int from_tty)
730 {
731 struct expression *expr;
732 struct value *val;
733 mach_vm_address_t address;
734 struct inferior *inf;
735
736 expr = parse_expression (exp);
737 val = evaluate_expression (expr);
738 if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF)
739 {
740 val = value_ind (val);
741 }
742 address = value_as_address (val);
743
744 if (ptid_equal (inferior_ptid, null_ptid))
745 error (_("Inferior not available"));
746
747 inf = current_inferior ();
748 darwin_debug_region (inf->private->task, address);
749 }
750
751 static void
752 disp_exception (const darwin_exception_info *info)
753 {
754 int i;
755
756 printf_filtered (_("%d exceptions:\n"), info->count);
757 for (i = 0; i < info->count; i++)
758 {
759 exception_mask_t mask = info->masks[i];
760
761 printf_filtered (_("port 0x%04x, behavior: "), info->ports[i]);
762 switch (info->behaviors[i])
763 {
764 case EXCEPTION_DEFAULT:
765 printf_unfiltered (_("default"));
766 break;
767 case EXCEPTION_STATE:
768 printf_unfiltered (_("state"));
769 break;
770 case EXCEPTION_STATE_IDENTITY:
771 printf_unfiltered (_("state-identity"));
772 break;
773 default:
774 printf_unfiltered (_("0x%x"), info->behaviors[i]);
775 }
776 printf_unfiltered (_(", masks:"));
777 if (mask & EXC_MASK_BAD_ACCESS)
778 printf_unfiltered (_(" BAD_ACCESS"));
779 if (mask & EXC_MASK_BAD_INSTRUCTION)
780 printf_unfiltered (_(" BAD_INSTRUCTION"));
781 if (mask & EXC_MASK_ARITHMETIC)
782 printf_unfiltered (_(" ARITHMETIC"));
783 if (mask & EXC_MASK_EMULATION)
784 printf_unfiltered (_(" EMULATION"));
785 if (mask & EXC_MASK_SOFTWARE)
786 printf_unfiltered (_(" SOFTWARE"));
787 if (mask & EXC_MASK_BREAKPOINT)
788 printf_unfiltered (_(" BREAKPOINT"));
789 if (mask & EXC_MASK_SYSCALL)
790 printf_unfiltered (_(" SYSCALL"));
791 if (mask & EXC_MASK_MACH_SYSCALL)
792 printf_unfiltered (_(" MACH_SYSCALL"));
793 if (mask & EXC_MASK_RPC_ALERT)
794 printf_unfiltered (_(" RPC_ALERT"));
795 if (mask & EXC_MASK_CRASH)
796 printf_unfiltered (_(" CRASH"));
797 printf_unfiltered (_("\n"));
798 }
799 }
800
801 static void
802 info_mach_exceptions_command (char *args, int from_tty)
803 {
804 int i;
805 task_t task;
806 kern_return_t kret;
807 darwin_exception_info info;
808
809 info.count = sizeof (info.ports) / sizeof (info.ports[0]);
810
811 if (args != NULL)
812 {
813 if (strcmp (args, "saved") == 0)
814 {
815 if (ptid_equal (inferior_ptid, null_ptid))
816 printf_unfiltered (_("No inferior running\n"));
817 disp_exception (&current_inferior ()->private->exception_info);
818 return;
819 }
820 else if (strcmp (args, "host") == 0)
821 {
822 /* FIXME: This need a the privilegied host port! */
823 kret = host_get_exception_ports
824 (darwin_host_self, EXC_MASK_ALL, info.masks,
825 &info.count, info.ports, info.behaviors, info.flavors);
826 MACH_CHECK_ERROR (kret);
827 disp_exception (&info);
828 }
829 else
830 error (_("Parameter is saved, host or none"));
831 }
832 else
833 {
834 struct inferior *inf;
835
836 if (ptid_equal (inferior_ptid, null_ptid))
837 printf_unfiltered (_("No inferior running\n"));
838 inf = current_inferior ();
839
840 kret = task_get_exception_ports
841 (inf->private->task, EXC_MASK_ALL, info.masks,
842 &info.count, info.ports, info.behaviors, info.flavors);
843 MACH_CHECK_ERROR (kret);
844 disp_exception (&info);
845 }
846 }
847
848 static void
849 darwin_list_gdb_ports (const char *msg)
850 {
851 mach_port_name_array_t names;
852 mach_port_type_array_t types;
853 unsigned int name_count, type_count;
854 kern_return_t result;
855 int i;
856
857 result = mach_port_names (mach_task_self (),
858 &names, &name_count, &types, &type_count);
859 MACH_CHECK_ERROR (result);
860
861 gdb_assert (name_count == type_count);
862
863 printf_unfiltered (_("Ports for %s:"), msg);
864 for (i = 0; i < name_count; ++i)
865 printf_unfiltered (_(" 0x%04x"), names[i]);
866 printf_unfiltered (_("\n"));
867
868 vm_deallocate (mach_task_self (), (vm_address_t) names,
869 (name_count * sizeof (mach_port_t)));
870 vm_deallocate (mach_task_self (), (vm_address_t) types,
871 (type_count * sizeof (mach_port_type_t)));
872 }
873
874 void
875 _initialize_darwin_info_commands (void)
876 {
877 add_info ("mach-tasks", info_mach_tasks_command,
878 _("Get list of tasks in system."));
879 add_info ("mach-ports", info_mach_ports_command,
880 _("Get list of ports in a task."));
881 add_info ("mach-port", info_mach_port_command,
882 _("Get info on a specific port."));
883 add_info ("mach-task", info_mach_task_command,
884 _("Get info on a specific task."));
885 add_info ("mach-threads", info_mach_threads_command,
886 _("Get list of threads in a task."));
887 add_info ("mach-thread", info_mach_thread_command,
888 _("Get info on a specific thread."));
889
890 add_info ("mach-regions", info_mach_regions_command,
891 _("Get information on all mach region for the task."));
892 add_info ("mach-regions-rec", info_mach_regions_recurse_command,
893 _("Get information on all mach sub region for the task."));
894 add_info ("mach-region", info_mach_region_command,
895 _("Get information on mach region at given address."));
896
897 add_info ("mach-exceptions", info_mach_exceptions_command,
898 _("Disp mach exceptions."));
899 }
This page took 0.047364 seconds and 5 git commands to generate.