gdb/
[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, 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   struct ui_out *uiout = current_uiout;
624
625   table_chain = make_cleanup_ui_out_table_begin_end (uiout, 9, -1, "regions");
626
627   if (gdbarch_addr_bit (target_gdbarch) <= 32)
628     {
629       ui_out_table_header (uiout, 10, ui_left, "start", "Start");
630       ui_out_table_header (uiout, 10, ui_left, "end", "End");
631     }
632   else
633     {
634       ui_out_table_header (uiout, 18, ui_left, "start", "Start");
635       ui_out_table_header (uiout, 18, ui_left, "end", "End");
636     }
637   ui_out_table_header (uiout, 3, ui_left, "min-prot", "Min");
638   ui_out_table_header (uiout, 3, ui_left, "max-prot", "Max");
639   ui_out_table_header (uiout, 5, ui_left, "inheritence", "Inh");
640   ui_out_table_header (uiout, 9, ui_left, "share-mode", "Shr");
641   ui_out_table_header (uiout, 1, ui_left, "depth", "D");
642   ui_out_table_header (uiout, 3, ui_left, "submap", "Sm");
643   ui_out_table_header (uiout, 0, ui_noalign, "tag", "Tag");
644
645   ui_out_table_body (uiout);
646
647   r_start = 0;
648   r_depth = 0;
649   while (1)
650     {
651       const char *tag;
652       struct cleanup *row_chain;
653
654       r_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
655       r_size = -1;
656       kret = mach_vm_region_recurse (task, &r_start, &r_size, &r_depth,
657                                      (vm_region_recurse_info_t) &r_info,
658                                      &r_info_size);
659       if (kret != KERN_SUCCESS)
660         break;
661       row_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "regions-row");
662
663       ui_out_field_core_addr (uiout, "start", target_gdbarch, r_start);
664       ui_out_field_core_addr (uiout, "end", target_gdbarch, r_start + r_size);
665       ui_out_field_string (uiout, "min-prot", 
666                            unparse_protection (r_info.protection));
667       ui_out_field_string (uiout, "max-prot", 
668                            unparse_protection (r_info.max_protection));
669       ui_out_field_string (uiout, "inheritence",
670                            unparse_inheritance (r_info.inheritance));
671       ui_out_field_string (uiout, "share-mode",
672                            unparse_share_mode (r_info.share_mode));
673       ui_out_field_int (uiout, "depth", r_depth);
674       ui_out_field_string (uiout, "submap",
675                            r_info.is_submap ? _("sm ") : _("obj"));
676       tag = unparse_user_tag (r_info.user_tag);
677       if (tag)
678         ui_out_field_string (uiout, "tag", tag);
679       else
680         ui_out_field_int (uiout, "tag", r_info.user_tag);
681
682       do_cleanups (row_chain);
683
684       if (!ui_out_is_mi_like_p (uiout))
685         ui_out_text (uiout, "\n");
686
687       if (r_info.is_submap)
688         r_depth++;
689       else
690         r_start += r_size;
691     }
692   do_cleanups (table_chain);
693
694 }
695
696
697 static void
698 darwin_debug_region (task_t task, mach_vm_address_t address)
699 {
700   darwin_debug_regions (task, address, 1);
701 }
702
703 static void
704 info_mach_regions_command (char *args, int from_tty)
705 {
706   task_t task;
707
708   task = get_task_from_args (args);
709   if (task == TASK_NULL)
710     return;
711   
712   darwin_debug_regions (task, 0, -1);
713 }
714
715 static void
716 info_mach_regions_recurse_command (char *args, int from_tty)
717 {
718   task_t task;
719
720   task = get_task_from_args (args);
721   if (task == TASK_NULL)
722     return;
723   
724   darwin_debug_regions_recurse (task);
725 }
726
727 static void
728 info_mach_region_command (char *exp, int from_tty)
729 {
730   struct expression *expr;
731   struct value *val;
732   mach_vm_address_t address;
733   struct inferior *inf;
734
735   expr = parse_expression (exp);
736   val = evaluate_expression (expr);
737   if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF)
738     {
739       val = value_ind (val);
740     }
741   address = value_as_address (val);
742
743   if (ptid_equal (inferior_ptid, null_ptid))
744     error (_("Inferior not available"));
745
746   inf = current_inferior ();
747   darwin_debug_region (inf->private->task, address);
748 }
749
750 static void
751 disp_exception (const darwin_exception_info *info)
752 {
753   int i;
754
755   printf_filtered (_("%d exceptions:\n"), info->count);
756   for (i = 0; i < info->count; i++)
757     {
758       exception_mask_t mask = info->masks[i];
759
760       printf_filtered (_("port 0x%04x, behavior: "), info->ports[i]);
761       switch (info->behaviors[i])
762         {
763         case EXCEPTION_DEFAULT:
764           printf_unfiltered (_("default"));
765           break;
766         case EXCEPTION_STATE:
767           printf_unfiltered (_("state"));
768           break;
769         case EXCEPTION_STATE_IDENTITY:
770           printf_unfiltered (_("state-identity"));
771           break;
772         default:
773           printf_unfiltered (_("0x%x"), info->behaviors[i]);
774         }
775       printf_unfiltered (_(", masks:"));
776       if (mask & EXC_MASK_BAD_ACCESS)
777         printf_unfiltered (_(" BAD_ACCESS"));
778       if (mask & EXC_MASK_BAD_INSTRUCTION)
779         printf_unfiltered (_(" BAD_INSTRUCTION"));
780       if (mask & EXC_MASK_ARITHMETIC)
781         printf_unfiltered (_(" ARITHMETIC"));
782       if (mask & EXC_MASK_EMULATION)
783         printf_unfiltered (_(" EMULATION"));
784       if (mask & EXC_MASK_SOFTWARE)
785         printf_unfiltered (_(" SOFTWARE"));
786       if (mask & EXC_MASK_BREAKPOINT)
787         printf_unfiltered (_(" BREAKPOINT"));
788       if (mask & EXC_MASK_SYSCALL)
789         printf_unfiltered (_(" SYSCALL"));
790       if (mask & EXC_MASK_MACH_SYSCALL)
791         printf_unfiltered (_(" MACH_SYSCALL"));
792       if (mask & EXC_MASK_RPC_ALERT)
793         printf_unfiltered (_(" RPC_ALERT"));
794       if (mask & EXC_MASK_CRASH)
795         printf_unfiltered (_(" CRASH"));
796       printf_unfiltered (_("\n"));
797     }
798 }
799
800 static void
801 info_mach_exceptions_command (char *args, int from_tty)
802 {
803   int i;
804   task_t task;
805   kern_return_t kret;
806   darwin_exception_info info;
807
808   info.count = sizeof (info.ports) / sizeof (info.ports[0]);
809
810   if (args != NULL)
811     {
812       if (strcmp (args, "saved") == 0)
813         {
814           if (ptid_equal (inferior_ptid, null_ptid))
815             printf_unfiltered (_("No inferior running\n"));
816           disp_exception (&current_inferior ()->private->exception_info);
817           return;
818         }
819       else if (strcmp (args, "host") == 0)
820         {
821           /* FIXME: This need a privilegied host port!  */
822           kret = host_get_exception_ports
823             (darwin_host_self, EXC_MASK_ALL, info.masks,
824              &info.count, info.ports, info.behaviors, info.flavors);
825           MACH_CHECK_ERROR (kret);
826           disp_exception (&info);
827         }
828       else
829         error (_("Parameter is saved, host or none"));
830     }
831   else
832     {
833       struct inferior *inf;
834
835       if (ptid_equal (inferior_ptid, null_ptid))
836         printf_unfiltered (_("No inferior running\n"));
837       inf = current_inferior ();
838       
839       kret = task_get_exception_ports
840         (inf->private->task, EXC_MASK_ALL, info.masks,
841          &info.count, info.ports, info.behaviors, info.flavors);
842       MACH_CHECK_ERROR (kret);
843       disp_exception (&info);
844     }
845 }
846
847 void
848 _initialize_darwin_info_commands (void)
849 {
850   add_info ("mach-tasks", info_mach_tasks_command,
851             _("Get list of tasks in system."));
852   add_info ("mach-ports", info_mach_ports_command,
853             _("Get list of ports in a task."));
854   add_info ("mach-port", info_mach_port_command,
855             _("Get info on a specific port."));
856   add_info ("mach-task", info_mach_task_command,
857             _("Get info on a specific task."));
858   add_info ("mach-threads", info_mach_threads_command,
859             _("Get list of threads in a task."));
860   add_info ("mach-thread", info_mach_thread_command,
861             _("Get info on a specific thread."));
862
863   add_info ("mach-regions", info_mach_regions_command,
864             _("Get information on all mach region for the task."));
865   add_info ("mach-regions-rec", info_mach_regions_recurse_command,
866             _("Get information on all mach sub region for the task."));
867   add_info ("mach-region", info_mach_region_command,
868             _("Get information on mach region at given address."));
869
870   add_info ("mach-exceptions", info_mach_exceptions_command,
871             _("Disp mach exceptions."));
872 }