GDB (API)
|
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 (¤t_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 }