2009-05-27 Tom Tromey <tromey@redhat.com>
[platform/upstream/binutils.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 }