GDB (API)
/home/stan/gdb/src/gdb/darwin-nat-info.c
Go to the documentation of this file.
00001 /* Darwin support for GDB, the GNU debugger.
00002    Copyright (C) 1997-2013 Free Software Foundation, Inc.
00003 
00004    Contributed by Apple Computer, Inc.
00005 
00006    This file is part of GDB.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 3 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00020 
00021 /* The name of the ppc_thread_state structure, and the names of its
00022    members, have been changed for Unix conformance reasons.  The easiest
00023    way to have gdb build on systems with the older names and systems
00024    with the newer names is to build this compilation unit with the
00025    non-conformant define below.  This doesn't seem to cause the resulting
00026    binary any problems but it seems like it could cause us problems in
00027    the future.  It'd be good to remove this at some point when compiling on
00028    Tiger is no longer important.  */
00029 
00030 #include "defs.h"
00031 #include "symtab.h"
00032 #include "gdbtypes.h"
00033 #include "gdbcore.h"
00034 #include "value.h"
00035 #include "gdbcmd.h"
00036 #include "inferior.h"
00037 
00038 #include <sys/sysctl.h>
00039 
00040 #include "darwin-nat.h"
00041 
00042 #include <mach/thread_info.h>
00043 #include <mach/thread_act.h>
00044 #include <mach/task.h>
00045 #include <mach/vm_map.h>
00046 #include <mach/mach_port.h>
00047 #include <mach/mach_init.h>
00048 #include <mach/mach_vm.h>
00049 
00050 #define CHECK_ARGS(what, args) do { \
00051   if ((NULL == args) || ((args[0] != '0') && (args[1] != 'x'))) \
00052     error(_("%s must be specified with 0x..."), what);          \
00053 } while (0)
00054 
00055 #define PRINT_FIELD(structure, field) \
00056   printf_unfiltered(_(#field":\t%#lx\n"), (unsigned long) (structure)->field)
00057 
00058 #define PRINT_TV_FIELD(structure, field) \
00059   printf_unfiltered(_(#field":\t%u.%06u sec\n"),        \
00060   (unsigned) (structure)->field.seconds, \
00061   (unsigned) (structure)->field.microseconds)
00062 
00063 #define task_self mach_task_self
00064 #define task_by_unix_pid task_for_pid
00065 #define port_name_array_t mach_port_array_t
00066 #define port_type_array_t mach_port_array_t
00067 
00068 static void
00069 info_mach_tasks_command (char *args, int from_tty)
00070 {
00071   int sysControl[4];
00072   int count, index;
00073   size_t length;
00074   struct kinfo_proc *procInfo;
00075 
00076   sysControl[0] = CTL_KERN;
00077   sysControl[1] = KERN_PROC;
00078   sysControl[2] = KERN_PROC_ALL;
00079 
00080   sysctl (sysControl, 3, NULL, &length, NULL, 0);
00081   procInfo = (struct kinfo_proc *) xmalloc (length);
00082   sysctl (sysControl, 3, procInfo, &length, NULL, 0);
00083 
00084   count = (length / sizeof (struct kinfo_proc));
00085   printf_unfiltered (_("%d processes:\n"), count);
00086   for (index = 0; index < count; ++index)
00087     {
00088       kern_return_t result;
00089       mach_port_t taskPort;
00090 
00091       result =
00092         task_by_unix_pid (mach_task_self (), procInfo[index].kp_proc.p_pid,
00093                           &taskPort);
00094       if (KERN_SUCCESS == result)
00095         {
00096           printf_unfiltered (_("    %s is %d has task %#x\n"),
00097                              procInfo[index].kp_proc.p_comm,
00098                              procInfo[index].kp_proc.p_pid, taskPort);
00099         }
00100       else
00101         {
00102           printf_unfiltered (_("    %s is %d unknown task port\n"),
00103                              procInfo[index].kp_proc.p_comm,
00104                              procInfo[index].kp_proc.p_pid);
00105         }
00106     }
00107 
00108   xfree (procInfo);
00109 }
00110 
00111 static task_t
00112 get_task_from_args (char *args)
00113 {
00114   task_t task;
00115   char *eptr;
00116 
00117   if (args == NULL || *args == 0)
00118     {
00119       if (ptid_equal (inferior_ptid, null_ptid))
00120         printf_unfiltered (_("No inferior running\n"));
00121       return current_inferior ()->private->task;
00122     }
00123   if (strcmp (args, "gdb") == 0)
00124     return mach_task_self ();
00125   task = strtoul (args, &eptr, 0);
00126   if (*eptr)
00127     {
00128       printf_unfiltered (_("cannot parse task id '%s'\n"), args);
00129       return TASK_NULL;
00130     }
00131   return task;
00132 }
00133 
00134 static void
00135 info_mach_task_command (char *args, int from_tty)
00136 {
00137   union
00138   {
00139     struct task_basic_info basic;
00140     struct task_events_info events;
00141     struct task_thread_times_info thread_times;
00142   } task_info_data;
00143 
00144   kern_return_t result;
00145   unsigned int info_count;
00146   task_t task;
00147 
00148   task = get_task_from_args (args);
00149   if (task == TASK_NULL)
00150     return;
00151 
00152   printf_unfiltered (_("TASK_BASIC_INFO for 0x%x:\n"), task);
00153   info_count = TASK_BASIC_INFO_COUNT;
00154   result = task_info (task,
00155                       TASK_BASIC_INFO,
00156                       (task_info_t) & task_info_data.basic, &info_count);
00157   MACH_CHECK_ERROR (result);
00158 
00159   PRINT_FIELD (&task_info_data.basic, suspend_count);
00160   PRINT_FIELD (&task_info_data.basic, virtual_size);
00161   PRINT_FIELD (&task_info_data.basic, resident_size);
00162   PRINT_TV_FIELD (&task_info_data.basic, user_time);
00163   PRINT_TV_FIELD (&task_info_data.basic, system_time);
00164   printf_unfiltered (_("\nTASK_EVENTS_INFO:\n"));
00165   info_count = TASK_EVENTS_INFO_COUNT;
00166   result = task_info (task,
00167                       TASK_EVENTS_INFO,
00168                       (task_info_t) & task_info_data.events, &info_count);
00169   MACH_CHECK_ERROR (result);
00170 
00171   PRINT_FIELD (&task_info_data.events, faults);
00172 #if 0
00173   PRINT_FIELD (&task_info_data.events, zero_fills);
00174   PRINT_FIELD (&task_info_data.events, reactivations);
00175 #endif
00176   PRINT_FIELD (&task_info_data.events, pageins);
00177   PRINT_FIELD (&task_info_data.events, cow_faults);
00178   PRINT_FIELD (&task_info_data.events, messages_sent);
00179   PRINT_FIELD (&task_info_data.events, messages_received);
00180   printf_unfiltered (_("\nTASK_THREAD_TIMES_INFO:\n"));
00181   info_count = TASK_THREAD_TIMES_INFO_COUNT;
00182   result = task_info (task,
00183                       TASK_THREAD_TIMES_INFO,
00184                       (task_info_t) & task_info_data.thread_times,
00185                       &info_count);
00186   MACH_CHECK_ERROR (result);
00187   PRINT_TV_FIELD (&task_info_data.thread_times, user_time);
00188   PRINT_TV_FIELD (&task_info_data.thread_times, system_time);
00189 }
00190 
00191 static void
00192 info_mach_ports_command (char *args, int from_tty)
00193 {
00194   port_name_array_t names;
00195   port_type_array_t types;
00196   unsigned int name_count, type_count;
00197   kern_return_t result;
00198   int index;
00199   task_t task;
00200 
00201   task = get_task_from_args (args);
00202   if (task == TASK_NULL)
00203     return;
00204 
00205   result = mach_port_names (task, &names, &name_count, &types, &type_count);
00206   MACH_CHECK_ERROR (result);
00207 
00208   gdb_assert (name_count == type_count);
00209 
00210   printf_unfiltered (_("Ports for task 0x%x:\n"), task);
00211   printf_unfiltered (_("port   type\n"));
00212   for (index = 0; index < name_count; ++index)
00213     {
00214       mach_port_t port = names[index];
00215       unsigned int j;
00216       struct type_descr
00217       {
00218         mach_port_type_t type;
00219         const char *name;
00220         mach_port_right_t right;
00221       };
00222       static struct type_descr descrs[] =
00223         {
00224           {MACH_PORT_TYPE_SEND, "send", MACH_PORT_RIGHT_SEND},
00225           {MACH_PORT_TYPE_SEND_ONCE, "send-once", MACH_PORT_RIGHT_SEND_ONCE},
00226           {MACH_PORT_TYPE_RECEIVE, "receive", MACH_PORT_RIGHT_RECEIVE},
00227           {MACH_PORT_TYPE_PORT_SET, "port-set", MACH_PORT_RIGHT_PORT_SET},
00228           {MACH_PORT_TYPE_DEAD_NAME, "dead", MACH_PORT_RIGHT_DEAD_NAME}
00229         };
00230 
00231       printf_unfiltered (_("%04x: %08x "), port, types[index]);
00232       for (j = 0; j < sizeof(descrs) / sizeof(*descrs); j++)
00233         if (types[index] & descrs[j].type)
00234           {
00235             mach_port_urefs_t ref;
00236             kern_return_t ret;
00237 
00238             printf_unfiltered (_(" %s("), descrs[j].name);
00239             ret = mach_port_get_refs (task, port, descrs[j].right, &ref);
00240             if (ret != KERN_SUCCESS)
00241               printf_unfiltered (_("??"));
00242             else
00243               printf_unfiltered (_("%u"), ref);
00244             printf_unfiltered (_(" refs)"));
00245           }
00246       
00247       if (task == task_self ())
00248         {
00249           if (port == task_self())
00250             printf_unfiltered (_(" gdb-task"));
00251           else if (port == darwin_host_self)
00252             printf_unfiltered (_(" host-self"));
00253           else if (port == darwin_ex_port)
00254             printf_unfiltered (_(" gdb-exception"));
00255           else if (port == darwin_port_set)
00256             printf_unfiltered (_(" gdb-port_set"));
00257           else if (!ptid_equal (inferior_ptid, null_ptid))
00258             {
00259               struct inferior *inf = current_inferior ();
00260 
00261               if (port == inf->private->task)
00262                 printf_unfiltered (_(" inferior-task"));
00263               else if (port == inf->private->notify_port)
00264                 printf_unfiltered (_(" inferior-notify"));
00265               else
00266                 {
00267                   int k;
00268                   darwin_thread_t *t;
00269 
00270                   for (k = 0; k < inf->private->exception_info.count; k++)
00271                     if (port == inf->private->exception_info.ports[k])
00272                       {
00273                         printf_unfiltered (_(" inferior-excp-port"));
00274                         break;
00275                       }
00276 
00277                   if (inf->private->threads)
00278                     {
00279                       for (k = 0;
00280                            VEC_iterate(darwin_thread_t,
00281                                        inf->private->threads, k, t);
00282                            k++)
00283                         if (port == t->gdb_port)
00284                           {
00285                             printf_unfiltered (_(" inferior-thread for 0x%x"),
00286                                                inf->private->task);
00287                             break;
00288                           }
00289                     }
00290                 }
00291             }
00292         }
00293       printf_unfiltered (_("\n"));
00294     }
00295 
00296   vm_deallocate (task_self (), (vm_address_t) names,
00297                  (name_count * sizeof (mach_port_t)));
00298   vm_deallocate (task_self (), (vm_address_t) types,
00299                  (type_count * sizeof (mach_port_type_t)));
00300 }
00301 
00302 
00303 static void
00304 darwin_debug_port_info (task_t task, mach_port_t port)
00305 {
00306   kern_return_t kret;
00307   mach_port_status_t status;
00308   mach_msg_type_number_t len = sizeof (status);
00309 
00310   kret = mach_port_get_attributes
00311     (task, port, MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &len);
00312   MACH_CHECK_ERROR (kret);
00313 
00314   printf_unfiltered (_("Port 0x%lx in task 0x%lx:\n"), (unsigned long) port,
00315                      (unsigned long) task);
00316   printf_unfiltered (_("  port set: 0x%x\n"), status.mps_pset);
00317   printf_unfiltered (_("     seqno: 0x%x\n"), status.mps_seqno);
00318   printf_unfiltered (_("   mscount: 0x%x\n"), status.mps_mscount);
00319   printf_unfiltered (_("    qlimit: 0x%x\n"), status.mps_qlimit);
00320   printf_unfiltered (_("  msgcount: 0x%x\n"), status.mps_msgcount);
00321   printf_unfiltered (_("  sorights: 0x%x\n"), status.mps_sorights);
00322   printf_unfiltered (_("   srights: 0x%x\n"), status.mps_srights);
00323   printf_unfiltered (_(" pdrequest: 0x%x\n"), status.mps_pdrequest);
00324   printf_unfiltered (_(" nsrequest: 0x%x\n"), status.mps_nsrequest);
00325   printf_unfiltered (_("     flags: 0x%x\n"), status.mps_flags);
00326 }
00327 
00328 static void
00329 info_mach_port_command (char *args, int from_tty)
00330 {
00331   task_t task;
00332   mach_port_t port;
00333 
00334   CHECK_ARGS (_("Task and port"), args);
00335   sscanf (args, "0x%x 0x%x", &task, &port);
00336 
00337   darwin_debug_port_info (task, port);
00338 }
00339 
00340 static void
00341 info_mach_threads_command (char *args, int from_tty)
00342 {
00343   thread_array_t threads;
00344   unsigned int thread_count;
00345   kern_return_t result;
00346   task_t task;
00347   int i;
00348 
00349   task = get_task_from_args (args);
00350   if (task == TASK_NULL)
00351     return;
00352 
00353   result = task_threads (task, &threads, &thread_count);
00354   MACH_CHECK_ERROR (result);
00355 
00356   printf_unfiltered (_("Threads in task %#x:\n"), task);
00357   for (i = 0; i < thread_count; ++i)
00358     {
00359       printf_unfiltered (_("    %#x\n"), threads[i]);
00360       mach_port_deallocate (task_self (), threads[i]);
00361     }
00362 
00363   vm_deallocate (task_self (), (vm_address_t) threads,
00364                  (thread_count * sizeof (thread_t)));
00365 }
00366 
00367 static void
00368 info_mach_thread_command (char *args, int from_tty)
00369 {
00370   union
00371   {
00372     struct thread_basic_info basic;
00373   } thread_info_data;
00374 
00375   thread_t thread;
00376   kern_return_t result;
00377   unsigned int info_count;
00378 
00379   CHECK_ARGS (_("Thread"), args);
00380   sscanf (args, "0x%x", &thread);
00381 
00382   printf_unfiltered (_("THREAD_BASIC_INFO\n"));
00383   info_count = THREAD_BASIC_INFO_COUNT;
00384   result = thread_info (thread,
00385                         THREAD_BASIC_INFO,
00386                         (thread_info_t) & thread_info_data.basic,
00387                         &info_count);
00388   MACH_CHECK_ERROR (result);
00389 
00390 #if 0
00391   PRINT_FIELD (&thread_info_data.basic, user_time);
00392   PRINT_FIELD (&thread_info_data.basic, system_time);
00393 #endif
00394   PRINT_FIELD (&thread_info_data.basic, cpu_usage);
00395   PRINT_FIELD (&thread_info_data.basic, run_state);
00396   PRINT_FIELD (&thread_info_data.basic, flags);
00397   PRINT_FIELD (&thread_info_data.basic, suspend_count);
00398   PRINT_FIELD (&thread_info_data.basic, sleep_time);
00399 }
00400 
00401 static const char *
00402 unparse_protection (vm_prot_t p)
00403 {
00404   switch (p)
00405     {
00406     case VM_PROT_NONE:
00407       return "---";
00408     case VM_PROT_READ:
00409       return "r--";
00410     case VM_PROT_WRITE:
00411       return "-w-";
00412     case VM_PROT_READ | VM_PROT_WRITE:
00413       return "rw-";
00414     case VM_PROT_EXECUTE:
00415       return "--x";
00416     case VM_PROT_EXECUTE | VM_PROT_READ:
00417       return "r-x";
00418     case VM_PROT_EXECUTE | VM_PROT_WRITE:
00419       return "-wx";
00420     case VM_PROT_EXECUTE | VM_PROT_WRITE | VM_PROT_READ:
00421       return "rwx";
00422     default:
00423       return "???";
00424     }
00425 }
00426 
00427 static const char *
00428 unparse_inheritance (vm_inherit_t i)
00429 {
00430   switch (i)
00431     {
00432     case VM_INHERIT_SHARE:
00433       return _("share");
00434     case VM_INHERIT_COPY:
00435       return _("copy ");
00436     case VM_INHERIT_NONE:
00437       return _("none ");
00438     default:
00439       return _("???  ");
00440     }
00441 }
00442 
00443 static const char *
00444 unparse_share_mode (unsigned char p)
00445 {
00446   switch (p)
00447     {
00448     case SM_COW:
00449       return _("cow");
00450     case SM_PRIVATE:
00451       return _("private");
00452     case SM_EMPTY:
00453       return _("empty");
00454     case SM_SHARED:
00455       return _("shared");
00456     case SM_TRUESHARED:
00457       return _("true-shrd");
00458     case SM_PRIVATE_ALIASED:
00459       return _("prv-alias");
00460     case SM_SHARED_ALIASED:
00461       return _("shr-alias");
00462     default:
00463       return _("???");
00464     }
00465 }
00466 
00467 static const char *
00468 unparse_user_tag (unsigned int tag)
00469 {
00470   switch (tag)
00471     {
00472     case 0:
00473       return _("default");
00474     case VM_MEMORY_MALLOC:
00475       return _("malloc");
00476     case VM_MEMORY_MALLOC_SMALL:
00477       return _("malloc_small");
00478     case VM_MEMORY_MALLOC_LARGE:
00479       return _("malloc_large");
00480     case VM_MEMORY_MALLOC_HUGE:
00481       return _("malloc_huge");
00482     case VM_MEMORY_SBRK:
00483       return _("sbrk");
00484     case VM_MEMORY_REALLOC:
00485       return _("realloc");
00486     case VM_MEMORY_MALLOC_TINY:
00487       return _("malloc_tiny");
00488     case VM_MEMORY_ANALYSIS_TOOL:
00489       return _("analysis_tool");
00490     case VM_MEMORY_MACH_MSG:
00491       return _("mach_msg");
00492     case VM_MEMORY_IOKIT:
00493       return _("iokit");
00494     case VM_MEMORY_STACK:
00495       return _("stack");
00496     case VM_MEMORY_GUARD:
00497       return _("guard");
00498     case VM_MEMORY_SHARED_PMAP:
00499       return _("shared_pmap");
00500     case VM_MEMORY_DYLIB:
00501       return _("dylib");
00502     case VM_MEMORY_APPKIT:
00503       return _("appkit");
00504     case VM_MEMORY_FOUNDATION:
00505       return _("foundation");
00506     default:
00507       return NULL;
00508     }
00509 }
00510 
00511 static void
00512 darwin_debug_regions (task_t task, mach_vm_address_t address, int max)
00513 {
00514   kern_return_t kret;
00515   vm_region_basic_info_data_64_t info, prev_info;
00516   mach_vm_address_t prev_address;
00517   mach_vm_size_t size, prev_size;
00518 
00519   mach_port_t object_name;
00520   mach_msg_type_number_t count;
00521 
00522   int nsubregions = 0;
00523   int num_printed = 0;
00524 
00525   count = VM_REGION_BASIC_INFO_COUNT_64;
00526   kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO_64,
00527                          (vm_region_info_t) &info, &count, &object_name);
00528   if (kret != KERN_SUCCESS)
00529     {
00530       printf_filtered (_("No memory regions."));
00531       return;
00532     }
00533   memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
00534   prev_address = address;
00535   prev_size = size;
00536   nsubregions = 1;
00537 
00538   for (;;)
00539     {
00540       int print = 0;
00541       int done = 0;
00542 
00543       address = prev_address + prev_size;
00544 
00545       /* Check to see if address space has wrapped around.  */
00546       if (address == 0)
00547         print = done = 1;
00548 
00549       if (!done)
00550         {
00551           count = VM_REGION_BASIC_INFO_COUNT_64;
00552           kret =
00553             mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO_64,
00554                               (vm_region_info_t) &info, &count, &object_name);
00555           if (kret != KERN_SUCCESS)
00556             {
00557               size = 0;
00558               print = done = 1;
00559             }
00560         }
00561 
00562       if (address != prev_address + prev_size)
00563         print = 1;
00564 
00565       if ((info.protection != prev_info.protection)
00566           || (info.max_protection != prev_info.max_protection)
00567           || (info.inheritance != prev_info.inheritance)
00568           || (info.shared != prev_info.reserved)
00569           || (info.reserved != prev_info.reserved))
00570         print = 1;
00571 
00572       if (print)
00573         {
00574           printf_filtered (_("%s-%s %s/%s  %s %s %s"),
00575                            paddress (target_gdbarch (), prev_address),
00576                            paddress (target_gdbarch (), prev_address + prev_size),
00577                            unparse_protection (prev_info.protection),
00578                            unparse_protection (prev_info.max_protection),
00579                            unparse_inheritance (prev_info.inheritance),
00580                            prev_info.shared ? _("shrd") : _("priv"),
00581                            prev_info.reserved ? _("reserved") : _("not-rsvd"));
00582 
00583           if (nsubregions > 1)
00584             printf_filtered (_(" (%d sub-rgn)"), nsubregions);
00585 
00586           printf_filtered (_("\n"));
00587 
00588           prev_address = address;
00589           prev_size = size;
00590           memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
00591           nsubregions = 1;
00592 
00593           num_printed++;
00594         }
00595       else
00596         {
00597           prev_size += size;
00598           nsubregions++;
00599         }
00600 
00601       if ((max > 0) && (num_printed >= max))
00602         done = 1;
00603 
00604       if (done)
00605         break;
00606     }
00607 }
00608 
00609 static void
00610 darwin_debug_regions_recurse (task_t task)
00611 {
00612   mach_vm_address_t r_addr;
00613   mach_vm_address_t r_start;
00614   mach_vm_size_t r_size;
00615   natural_t r_depth;
00616   mach_msg_type_number_t r_info_size;
00617   vm_region_submap_short_info_data_64_t r_info;
00618   kern_return_t kret;
00619   int ret;
00620   struct cleanup *table_chain;
00621   struct ui_out *uiout = current_uiout;
00622 
00623   table_chain = make_cleanup_ui_out_table_begin_end (uiout, 9, -1, "regions");
00624 
00625   if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
00626     {
00627       ui_out_table_header (uiout, 10, ui_left, "start", "Start");
00628       ui_out_table_header (uiout, 10, ui_left, "end", "End");
00629     }
00630   else
00631     {
00632       ui_out_table_header (uiout, 18, ui_left, "start", "Start");
00633       ui_out_table_header (uiout, 18, ui_left, "end", "End");
00634     }
00635   ui_out_table_header (uiout, 3, ui_left, "min-prot", "Min");
00636   ui_out_table_header (uiout, 3, ui_left, "max-prot", "Max");
00637   ui_out_table_header (uiout, 5, ui_left, "inheritence", "Inh");
00638   ui_out_table_header (uiout, 9, ui_left, "share-mode", "Shr");
00639   ui_out_table_header (uiout, 1, ui_left, "depth", "D");
00640   ui_out_table_header (uiout, 3, ui_left, "submap", "Sm");
00641   ui_out_table_header (uiout, 0, ui_noalign, "tag", "Tag");
00642 
00643   ui_out_table_body (uiout);
00644 
00645   r_start = 0;
00646   r_depth = 0;
00647   while (1)
00648     {
00649       const char *tag;
00650       struct cleanup *row_chain;
00651 
00652       r_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
00653       r_size = -1;
00654       kret = mach_vm_region_recurse (task, &r_start, &r_size, &r_depth,
00655                                      (vm_region_recurse_info_t) &r_info,
00656                                      &r_info_size);
00657       if (kret != KERN_SUCCESS)
00658         break;
00659       row_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "regions-row");
00660 
00661       ui_out_field_core_addr (uiout, "start", target_gdbarch (), r_start);
00662       ui_out_field_core_addr (uiout, "end", target_gdbarch (), r_start + r_size);
00663       ui_out_field_string (uiout, "min-prot", 
00664                            unparse_protection (r_info.protection));
00665       ui_out_field_string (uiout, "max-prot", 
00666                            unparse_protection (r_info.max_protection));
00667       ui_out_field_string (uiout, "inheritence",
00668                            unparse_inheritance (r_info.inheritance));
00669       ui_out_field_string (uiout, "share-mode",
00670                            unparse_share_mode (r_info.share_mode));
00671       ui_out_field_int (uiout, "depth", r_depth);
00672       ui_out_field_string (uiout, "submap",
00673                            r_info.is_submap ? _("sm ") : _("obj"));
00674       tag = unparse_user_tag (r_info.user_tag);
00675       if (tag)
00676         ui_out_field_string (uiout, "tag", tag);
00677       else
00678         ui_out_field_int (uiout, "tag", r_info.user_tag);
00679 
00680       do_cleanups (row_chain);
00681 
00682       if (!ui_out_is_mi_like_p (uiout))
00683         ui_out_text (uiout, "\n");
00684 
00685       if (r_info.is_submap)
00686         r_depth++;
00687       else
00688         r_start += r_size;
00689     }
00690   do_cleanups (table_chain);
00691 
00692 }
00693 
00694 
00695 static void
00696 darwin_debug_region (task_t task, mach_vm_address_t address)
00697 {
00698   darwin_debug_regions (task, address, 1);
00699 }
00700 
00701 static void
00702 info_mach_regions_command (char *args, int from_tty)
00703 {
00704   task_t task;
00705 
00706   task = get_task_from_args (args);
00707   if (task == TASK_NULL)
00708     return;
00709   
00710   darwin_debug_regions (task, 0, -1);
00711 }
00712 
00713 static void
00714 info_mach_regions_recurse_command (char *args, int from_tty)
00715 {
00716   task_t task;
00717 
00718   task = get_task_from_args (args);
00719   if (task == TASK_NULL)
00720     return;
00721   
00722   darwin_debug_regions_recurse (task);
00723 }
00724 
00725 static void
00726 info_mach_region_command (char *exp, int from_tty)
00727 {
00728   struct expression *expr;
00729   struct value *val;
00730   mach_vm_address_t address;
00731   struct inferior *inf;
00732 
00733   expr = parse_expression (exp);
00734   val = evaluate_expression (expr);
00735   if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF)
00736     {
00737       val = value_ind (val);
00738     }
00739   address = value_as_address (val);
00740 
00741   if (ptid_equal (inferior_ptid, null_ptid))
00742     error (_("Inferior not available"));
00743 
00744   inf = current_inferior ();
00745   darwin_debug_region (inf->private->task, address);
00746 }
00747 
00748 static void
00749 disp_exception (const darwin_exception_info *info)
00750 {
00751   int i;
00752 
00753   printf_filtered (_("%d exceptions:\n"), info->count);
00754   for (i = 0; i < info->count; i++)
00755     {
00756       exception_mask_t mask = info->masks[i];
00757 
00758       printf_filtered (_("port 0x%04x, behavior: "), info->ports[i]);
00759       switch (info->behaviors[i])
00760         {
00761         case EXCEPTION_DEFAULT:
00762           printf_unfiltered (_("default"));
00763           break;
00764         case EXCEPTION_STATE:
00765           printf_unfiltered (_("state"));
00766           break;
00767         case EXCEPTION_STATE_IDENTITY:
00768           printf_unfiltered (_("state-identity"));
00769           break;
00770         default:
00771           printf_unfiltered (_("0x%x"), info->behaviors[i]);
00772         }
00773       printf_unfiltered (_(", masks:"));
00774       if (mask & EXC_MASK_BAD_ACCESS)
00775         printf_unfiltered (_(" BAD_ACCESS"));
00776       if (mask & EXC_MASK_BAD_INSTRUCTION)
00777         printf_unfiltered (_(" BAD_INSTRUCTION"));
00778       if (mask & EXC_MASK_ARITHMETIC)
00779         printf_unfiltered (_(" ARITHMETIC"));
00780       if (mask & EXC_MASK_EMULATION)
00781         printf_unfiltered (_(" EMULATION"));
00782       if (mask & EXC_MASK_SOFTWARE)
00783         printf_unfiltered (_(" SOFTWARE"));
00784       if (mask & EXC_MASK_BREAKPOINT)
00785         printf_unfiltered (_(" BREAKPOINT"));
00786       if (mask & EXC_MASK_SYSCALL)
00787         printf_unfiltered (_(" SYSCALL"));
00788       if (mask & EXC_MASK_MACH_SYSCALL)
00789         printf_unfiltered (_(" MACH_SYSCALL"));
00790       if (mask & EXC_MASK_RPC_ALERT)
00791         printf_unfiltered (_(" RPC_ALERT"));
00792       if (mask & EXC_MASK_CRASH)
00793         printf_unfiltered (_(" CRASH"));
00794       printf_unfiltered (_("\n"));
00795     }
00796 }
00797 
00798 static void
00799 info_mach_exceptions_command (char *args, int from_tty)
00800 {
00801   int i;
00802   task_t task;
00803   kern_return_t kret;
00804   darwin_exception_info info;
00805 
00806   info.count = sizeof (info.ports) / sizeof (info.ports[0]);
00807 
00808   if (args != NULL)
00809     {
00810       if (strcmp (args, "saved") == 0)
00811         {
00812           if (ptid_equal (inferior_ptid, null_ptid))
00813             printf_unfiltered (_("No inferior running\n"));
00814           disp_exception (&current_inferior ()->private->exception_info);
00815           return;
00816         }
00817       else if (strcmp (args, "host") == 0)
00818         {
00819           /* FIXME: This need a privilegied host port!  */
00820           kret = host_get_exception_ports
00821             (darwin_host_self, EXC_MASK_ALL, info.masks,
00822              &info.count, info.ports, info.behaviors, info.flavors);
00823           MACH_CHECK_ERROR (kret);
00824           disp_exception (&info);
00825         }
00826       else
00827         error (_("Parameter is saved, host or none"));
00828     }
00829   else
00830     {
00831       struct inferior *inf;
00832 
00833       if (ptid_equal (inferior_ptid, null_ptid))
00834         printf_unfiltered (_("No inferior running\n"));
00835       inf = current_inferior ();
00836       
00837       kret = task_get_exception_ports
00838         (inf->private->task, EXC_MASK_ALL, info.masks,
00839          &info.count, info.ports, info.behaviors, info.flavors);
00840       MACH_CHECK_ERROR (kret);
00841       disp_exception (&info);
00842     }
00843 }
00844 
00845 /* -Wmissing-prototypes */
00846 extern initialize_file_ftype _initialize_darwin_info_commands;
00847 
00848 void
00849 _initialize_darwin_info_commands (void)
00850 {
00851   add_info ("mach-tasks", info_mach_tasks_command,
00852             _("Get list of tasks in system."));
00853   add_info ("mach-ports", info_mach_ports_command,
00854             _("Get list of ports in a task."));
00855   add_info ("mach-port", info_mach_port_command,
00856             _("Get info on a specific port."));
00857   add_info ("mach-task", info_mach_task_command,
00858             _("Get info on a specific task."));
00859   add_info ("mach-threads", info_mach_threads_command,
00860             _("Get list of threads in a task."));
00861   add_info ("mach-thread", info_mach_thread_command,
00862             _("Get info on a specific thread."));
00863 
00864   add_info ("mach-regions", info_mach_regions_command,
00865             _("Get information on all mach region for the task."));
00866   add_info ("mach-regions-rec", info_mach_regions_recurse_command,
00867             _("Get information on all mach sub region for the task."));
00868   add_info ("mach-region", info_mach_region_command,
00869             _("Get information on mach region at given address."));
00870 
00871   add_info ("mach-exceptions", info_mach_exceptions_command,
00872             _("Disp mach exceptions."));
00873 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines