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