OSDN Git Service

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