Updated copyright notices for most files.
[external/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 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 (darwin_inf->task == TASK_NULL)
124         printf_unfiltered (_("No inferior running\n"));
125       return darwin_inf->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_not_port)
258             printf_unfiltered (_(" gdb-notifier"));
259           else if (port == darwin_ex_port)
260             printf_unfiltered (_(" gdb-exception"));
261           else if (port == darwin_port_set)
262             printf_unfiltered (_(" gdb-port_set"));
263           else if (darwin_inf && port == darwin_inf->task)
264             printf_unfiltered (_(" inferior-task"));
265           else if (darwin_inf && darwin_inf->threads)
266             {
267               int k;
268               thread_t t;
269               for (k = 0; VEC_iterate(thread_t, darwin_inf->threads, k, t); k++)
270                 if (port == t)
271                   {
272                     printf_unfiltered (_(" inferior-thread for 0x%x"),
273                                        darwin_inf->task);
274                     break;
275                   }
276             }
277         }
278       printf_unfiltered (_("\n"));
279     }
280
281   vm_deallocate (task_self (), (vm_address_t) names,
282                  (name_count * sizeof (mach_port_t)));
283   vm_deallocate (task_self (), (vm_address_t) types,
284                  (type_count * sizeof (mach_port_type_t)));
285 }
286
287
288 void
289 darwin_debug_port_info (task_t task, mach_port_t port)
290 {
291   kern_return_t kret;
292   mach_port_status_t status;
293   mach_msg_type_number_t len = sizeof (status);
294
295   kret = mach_port_get_attributes
296     (task, port, MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &len);
297   MACH_CHECK_ERROR (kret);
298
299   printf_unfiltered (_("Port 0x%lx in task 0x%lx:\n"), (unsigned long) port,
300                      (unsigned long) task);
301   printf_unfiltered (_("  port set: 0x%x\n"), status.mps_pset);
302   printf_unfiltered (_("     seqno: 0x%x\n"), status.mps_seqno);
303   printf_unfiltered (_("   mscount: 0x%x\n"), status.mps_mscount);
304   printf_unfiltered (_("    qlimit: 0x%x\n"), status.mps_qlimit);
305   printf_unfiltered (_("  msgcount: 0x%x\n"), status.mps_msgcount);
306   printf_unfiltered (_("  sorights: 0x%x\n"), status.mps_sorights);
307   printf_unfiltered (_("   srights: 0x%x\n"), status.mps_srights);
308   printf_unfiltered (_(" pdrequest: 0x%x\n"), status.mps_pdrequest);
309   printf_unfiltered (_(" nsrequest: 0x%x\n"), status.mps_nsrequest);
310   printf_unfiltered (_("     flags: 0x%x\n"), status.mps_flags);
311 }
312
313 static void
314 info_mach_port_command (char *args, int from_tty)
315 {
316   task_t task;
317   mach_port_t port;
318
319   CHECK_ARGS (_("Task and port"), args);
320   sscanf (args, "0x%x 0x%x", &task, &port);
321
322   darwin_debug_port_info (task, port);
323 }
324
325 static void
326 info_mach_threads_command (char *args, int from_tty)
327 {
328   thread_array_t threads;
329   unsigned int thread_count;
330   kern_return_t result;
331   task_t task;
332   int i;
333
334   task = get_task_from_args (args);
335   if (task == TASK_NULL)
336     return;
337
338   result = task_threads (task, &threads, &thread_count);
339   MACH_CHECK_ERROR (result);
340
341   printf_unfiltered (_("Threads in task %#x:\n"), task);
342   for (i = 0; i < thread_count; ++i)
343     {
344       printf_unfiltered (_("    %#x\n"), threads[i]);
345       mach_port_deallocate (task_self (), threads[i]);
346     }
347
348   vm_deallocate (task_self (), (vm_address_t) threads,
349                  (thread_count * sizeof (thread_t)));
350 }
351
352 static void
353 info_mach_thread_command (char *args, int from_tty)
354 {
355   union
356   {
357     struct thread_basic_info basic;
358   } thread_info_data;
359
360   thread_t thread;
361   kern_return_t result;
362   unsigned int info_count;
363
364   CHECK_ARGS (_("Thread"), args);
365   sscanf (args, "0x%x", &thread);
366
367   printf_unfiltered (_("THREAD_BASIC_INFO\n"));
368   info_count = THREAD_BASIC_INFO_COUNT;
369   result = thread_info (thread,
370                         THREAD_BASIC_INFO,
371                         (thread_info_t) & thread_info_data.basic,
372                         &info_count);
373   MACH_CHECK_ERROR (result);
374
375 #if 0
376   PRINT_FIELD (&thread_info_data.basic, user_time);
377   PRINT_FIELD (&thread_info_data.basic, system_time);
378 #endif
379   PRINT_FIELD (&thread_info_data.basic, cpu_usage);
380   PRINT_FIELD (&thread_info_data.basic, run_state);
381   PRINT_FIELD (&thread_info_data.basic, flags);
382   PRINT_FIELD (&thread_info_data.basic, suspend_count);
383   PRINT_FIELD (&thread_info_data.basic, sleep_time);
384 }
385
386 static const char *
387 unparse_protection (vm_prot_t p)
388 {
389   switch (p)
390     {
391     case VM_PROT_NONE:
392       return "---";
393     case VM_PROT_READ:
394       return "r--";
395     case VM_PROT_WRITE:
396       return "-w-";
397     case VM_PROT_READ | VM_PROT_WRITE:
398       return "rw-";
399     case VM_PROT_EXECUTE:
400       return "--x";
401     case VM_PROT_EXECUTE | VM_PROT_READ:
402       return "r-x";
403     case VM_PROT_EXECUTE | VM_PROT_WRITE:
404       return "-wx";
405     case VM_PROT_EXECUTE | VM_PROT_WRITE | VM_PROT_READ:
406       return "rwx";
407     default:
408       return "???";
409     }
410 }
411
412 static const char *
413 unparse_inheritance (vm_inherit_t i)
414 {
415   switch (i)
416     {
417     case VM_INHERIT_SHARE:
418       return _("share");
419     case VM_INHERIT_COPY:
420       return _("copy ");
421     case VM_INHERIT_NONE:
422       return _("none ");
423     default:
424       return _("???  ");
425     }
426 }
427
428 static const char *
429 unparse_share_mode (unsigned char p)
430 {
431   switch (p)
432     {
433     case SM_COW:
434       return _("cow");
435     case SM_PRIVATE:
436       return _("private");
437     case SM_EMPTY:
438       return _("empty");
439     case SM_SHARED:
440       return _("shared");
441     case SM_TRUESHARED:
442       return _("true-shrd");
443     case SM_PRIVATE_ALIASED:
444       return _("prv-alias");
445     case SM_SHARED_ALIASED:
446       return _("shr-alias");
447     default:
448       return _("???");
449     }
450 }
451
452 static const char *
453 unparse_user_tag (unsigned int tag)
454 {
455   switch (tag)
456     {
457     case 0:
458       return _("default");
459     case VM_MEMORY_MALLOC:
460       return _("malloc");
461     case VM_MEMORY_MALLOC_SMALL:
462       return _("malloc_small");
463     case VM_MEMORY_MALLOC_LARGE:
464       return _("malloc_large");
465     case VM_MEMORY_MALLOC_HUGE:
466       return _("malloc_huge");
467     case VM_MEMORY_SBRK:
468       return _("sbrk");
469     case VM_MEMORY_REALLOC:
470       return _("realloc");
471     case VM_MEMORY_MALLOC_TINY:
472       return _("malloc_tiny");
473     case VM_MEMORY_ANALYSIS_TOOL:
474       return _("analysis_tool");
475     case VM_MEMORY_MACH_MSG:
476       return _("mach_msg");
477     case VM_MEMORY_IOKIT:
478       return _("iokit");
479     case VM_MEMORY_STACK:
480       return _("stack");
481     case VM_MEMORY_GUARD:
482       return _("guard");
483     case VM_MEMORY_SHARED_PMAP:
484       return _("shared_pmap");
485     case VM_MEMORY_DYLIB:
486       return _("dylib");
487     case VM_MEMORY_APPKIT:
488       return _("appkit");
489     case VM_MEMORY_FOUNDATION:
490       return _("foundation");
491     default:
492       return NULL;
493     }
494 }
495
496 static void
497 darwin_debug_regions (task_t task, mach_vm_address_t address, int max)
498 {
499   kern_return_t kret;
500   vm_region_basic_info_data_64_t info, prev_info;
501   mach_vm_address_t prev_address;
502   mach_vm_size_t size, prev_size;
503
504   mach_port_t object_name;
505   mach_msg_type_number_t count;
506
507   int nsubregions = 0;
508   int num_printed = 0;
509
510   count = VM_REGION_BASIC_INFO_COUNT_64;
511   kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO_64,
512                          (vm_region_info_t) &info, &count, &object_name);
513   if (kret != KERN_SUCCESS)
514     {
515       printf_filtered (_("No memory regions."));
516       return;
517     }
518   memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
519   prev_address = address;
520   prev_size = size;
521   nsubregions = 1;
522
523   for (;;)
524     {
525       int print = 0;
526       int done = 0;
527
528       address = prev_address + prev_size;
529
530       /* Check to see if address space has wrapped around. */
531       if (address == 0)
532         print = done = 1;
533
534       if (!done)
535         {
536           count = VM_REGION_BASIC_INFO_COUNT_64;
537           kret =
538             mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO_64,
539                               (vm_region_info_t) &info, &count, &object_name);
540           if (kret != KERN_SUCCESS)
541             {
542               size = 0;
543               print = done = 1;
544             }
545         }
546
547       if (address != prev_address + prev_size)
548         print = 1;
549
550       if ((info.protection != prev_info.protection)
551           || (info.max_protection != prev_info.max_protection)
552           || (info.inheritance != prev_info.inheritance)
553           || (info.shared != prev_info.reserved)
554           || (info.reserved != prev_info.reserved))
555         print = 1;
556
557       if (print)
558         {
559           printf_filtered (_("%s-%s %s/%s  %s %s %s"),
560                            paddr(prev_address),
561                            paddr(prev_address + prev_size),
562                            unparse_protection (prev_info.protection),
563                            unparse_protection (prev_info.max_protection),
564                            unparse_inheritance (prev_info.inheritance),
565                            prev_info.shared ? _("shrd") : _("priv"),
566                            prev_info.reserved ? _("reserved") : _("not-rsvd"));
567
568           if (nsubregions > 1)
569             printf_filtered (_(" (%d sub-rgn)"), nsubregions);
570
571           printf_filtered (_("\n"));
572
573           prev_address = address;
574           prev_size = size;
575           memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
576           nsubregions = 1;
577
578           num_printed++;
579         }
580       else
581         {
582           prev_size += size;
583           nsubregions++;
584         }
585
586       if ((max > 0) && (num_printed >= max))
587         done = 1;
588
589       if (done)
590         break;
591     }
592 }
593
594 static void
595 darwin_debug_regions_recurse (task_t task)
596 {
597   mach_vm_address_t r_addr;
598   mach_vm_address_t r_start;
599   mach_vm_size_t r_size;
600   natural_t r_depth;
601   mach_msg_type_number_t r_info_size;
602   vm_region_submap_short_info_data_64_t r_info;
603   kern_return_t kret;
604   int ret;
605
606   r_start = 0;
607   r_depth = 0;
608   while (1)
609     {
610       const char *tag;
611
612       r_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
613       r_size = -1;
614       kret = mach_vm_region_recurse (task, &r_start, &r_size, &r_depth,
615                                      (vm_region_recurse_info_t) &r_info,
616                                      &r_info_size);
617       if (kret != KERN_SUCCESS)
618         break;
619       printf_filtered (_("%s-%s %s/%s  %-5s %-10s %2d %s"),
620                        paddr(r_start),
621                        paddr(r_start + r_size),
622                        unparse_protection (r_info.protection),
623                        unparse_protection (r_info.max_protection),
624                        unparse_inheritance (r_info.inheritance),
625                        unparse_share_mode (r_info.share_mode),
626                        r_depth,
627                        r_info.is_submap ? _("sm ") : _("obj"));
628       tag = unparse_user_tag (r_info.user_tag);
629       if (tag)
630         printf_unfiltered (_(" %s\n"), tag);
631       else
632         printf_unfiltered (_(" %u\n"), r_info.user_tag);
633       if (r_info.is_submap)
634         r_depth++;
635       else
636         r_start += r_size;
637     }
638 }
639
640
641 static void
642 darwin_debug_region (task_t task, mach_vm_address_t address)
643 {
644   darwin_debug_regions (task, address, 1);
645 }
646
647 static void
648 info_mach_regions_command (char *args, int from_tty)
649 {
650   task_t task;
651
652   task = get_task_from_args (args);
653   if (task == TASK_NULL)
654     return;
655   
656   darwin_debug_regions (task, 0, -1);
657 }
658
659 static void
660 info_mach_regions_recurse_command (char *args, int from_tty)
661 {
662   task_t task;
663
664   task = get_task_from_args (args);
665   if (task == TASK_NULL)
666     return;
667   
668   darwin_debug_regions_recurse (task);
669 }
670
671 static void
672 info_mach_region_command (char *exp, int from_tty)
673 {
674   struct expression *expr;
675   struct value *val;
676   mach_vm_address_t address;
677
678   expr = parse_expression (exp);
679   val = evaluate_expression (expr);
680   if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF)
681     {
682       val = value_ind (val);
683     }
684   /* In rvalue contexts, such as this, functions are coerced into
685      pointers to functions. */
686   if (TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC
687       && VALUE_LVAL (val) == lval_memory)
688     {
689       address = VALUE_ADDRESS (val);
690     }
691   else
692     {
693       address = value_as_address (val);
694     }
695
696   if ((!darwin_inf) || (darwin_inf->task == TASK_NULL))
697     error (_("Inferior not available"));
698
699   darwin_debug_region (darwin_inf->task, address);
700 }
701
702 static void
703 disp_exception (const darwin_exception_info *info)
704 {
705   int i;
706
707   printf_filtered (_("%d exceptions:\n"), info->count);
708   for (i = 0; i < info->count; i++)
709     {
710       exception_mask_t mask = info->masks[i];
711
712       printf_filtered (_("port 0x%04x, behavior: "), info->ports[i]);
713       switch (info->behaviors[i])
714         {
715         case EXCEPTION_DEFAULT:
716           printf_unfiltered (_("default"));
717           break;
718         case EXCEPTION_STATE:
719           printf_unfiltered (_("state"));
720           break;
721         case EXCEPTION_STATE_IDENTITY:
722           printf_unfiltered (_("state-identity"));
723           break;
724         default:
725           printf_unfiltered (_("0x%x"), info->behaviors[i]);
726         }
727       printf_unfiltered (_(", masks:"));
728       if (mask & EXC_MASK_BAD_ACCESS)
729         printf_unfiltered (_(" BAD_ACCESS"));
730       if (mask & EXC_MASK_BAD_INSTRUCTION)
731         printf_unfiltered (_(" BAD_INSTRUCTION"));
732       if (mask & EXC_MASK_ARITHMETIC)
733         printf_unfiltered (_(" ARITHMETIC"));
734       if (mask & EXC_MASK_EMULATION)
735         printf_unfiltered (_(" EMULATION"));
736       if (mask & EXC_MASK_SOFTWARE)
737         printf_unfiltered (_(" SOFTWARE"));
738       if (mask & EXC_MASK_BREAKPOINT)
739         printf_unfiltered (_(" BREAKPOINT"));
740       if (mask & EXC_MASK_SYSCALL)
741         printf_unfiltered (_(" SYSCALL"));
742       if (mask & EXC_MASK_MACH_SYSCALL)
743         printf_unfiltered (_(" MACH_SYSCALL"));
744       if (mask & EXC_MASK_RPC_ALERT)
745         printf_unfiltered (_(" RPC_ALERT"));
746       if (mask & EXC_MASK_CRASH)
747         printf_unfiltered (_(" CRASH"));
748       printf_unfiltered (_("\n"));
749     }
750 }
751
752 static void
753 info_mach_exceptions_command (char *args, int from_tty)
754 {
755   int i;
756   task_t task;
757   kern_return_t kret;
758   darwin_exception_info info;
759
760   info.count = sizeof (info.ports) / sizeof (info.ports[0]);
761
762   if (args != NULL)
763     {
764       if (strcmp (args, "saved") == 0)
765         {
766           if (darwin_inf->task == TASK_NULL)
767             error (_("No inferior running\n"));
768           disp_exception (&darwin_inf->exception_info);
769           return;
770         }
771       else if (strcmp (args, "host") == 0)
772         {
773           /* FIXME: This need a the privilegied host port!  */
774           kret = host_get_exception_ports
775             (darwin_host_self, EXC_MASK_ALL, info.masks,
776              &info.count, info.ports, info.behaviors, info.flavors);
777           MACH_CHECK_ERROR (kret);
778           disp_exception (&info);
779         }
780       else
781         error (_("Parameter is saved, host or none"));
782     }
783   else
784     {
785       if (darwin_inf->task == TASK_NULL)
786         error (_("No inferior running\n"));
787       
788       kret = task_get_exception_ports
789         (darwin_inf->task, EXC_MASK_ALL, info.masks,
790          &info.count, info.ports, info.behaviors, info.flavors);
791       MACH_CHECK_ERROR (kret);
792       disp_exception (&info);
793     }
794 }
795
796 static void
797 darwin_list_gdb_ports (const char *msg)
798 {
799   mach_port_name_array_t names;
800   mach_port_type_array_t types;
801   unsigned int name_count, type_count;
802   kern_return_t result;
803   int i;
804
805   result = mach_port_names (mach_task_self (),
806                             &names, &name_count, &types, &type_count);
807   MACH_CHECK_ERROR (result);
808
809   gdb_assert (name_count == type_count);
810
811   printf_unfiltered (_("Ports for %s:"), msg);
812   for (i = 0; i < name_count; ++i)
813     printf_unfiltered (_(" 0x%04x"), names[i]);
814   printf_unfiltered (_("\n"));
815
816   vm_deallocate (mach_task_self (), (vm_address_t) names,
817                  (name_count * sizeof (mach_port_t)));
818   vm_deallocate (mach_task_self (), (vm_address_t) types,
819                  (type_count * sizeof (mach_port_type_t)));
820 }
821
822 void
823 _initialize_darwin_info_commands (void)
824 {
825   add_info ("mach-tasks", info_mach_tasks_command,
826             _("Get list of tasks in system."));
827   add_info ("mach-ports", info_mach_ports_command,
828             _("Get list of ports in a task."));
829   add_info ("mach-port", info_mach_port_command,
830             _("Get info on a specific port."));
831   add_info ("mach-task", info_mach_task_command,
832             _("Get info on a specific task."));
833   add_info ("mach-threads", info_mach_threads_command,
834             _("Get list of threads in a task."));
835   add_info ("mach-thread", info_mach_thread_command,
836             _("Get info on a specific thread."));
837
838   add_info ("mach-regions", info_mach_regions_command,
839             _("Get information on all mach region for the task."));
840   add_info ("mach-regions-rec", info_mach_regions_recurse_command,
841             _("Get information on all mach sub region for the task."));
842   add_info ("mach-region", info_mach_region_command,
843             _("Get information on mach region at given address."));
844
845   add_info ("mach-exceptions", info_mach_exceptions_command,
846             _("Disp mach exceptions."));
847 }