|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: ipc/mach_debug.c ! 54: * Author: Rich Draves ! 55: * Date: 1989 ! 56: * ! 57: * Exported IPC debug calls. ! 58: */ ! 59: #include <mach_ipc_debug.h> ! 60: ! 61: #include <mach/vm_param.h> ! 62: #include <mach/kern_return.h> ! 63: #include <mach/machine/vm_types.h> ! 64: #include <mach/mach_host_server.h> ! 65: #include <mach/mach_port_server.h> ! 66: #include <mach_debug/ipc_info.h> ! 67: #include <mach_debug/hash_info.h> ! 68: ! 69: #if MACH_IPC_DEBUG ! 70: #include <kern/host.h> ! 71: #include <kern/misc_protos.h> ! 72: #include <vm/vm_map.h> ! 73: #include <vm/vm_kern.h> ! 74: #include <ipc/ipc_space.h> ! 75: #include <ipc/ipc_port.h> ! 76: #include <ipc/ipc_hash.h> ! 77: #include <ipc/ipc_table.h> ! 78: #include <ipc/ipc_right.h> ! 79: #endif ! 80: ! 81: /* ! 82: * Routine: mach_port_get_srights [kernel call] ! 83: * Purpose: ! 84: * Retrieve the number of extant send rights ! 85: * that a receive right has. ! 86: * Conditions: ! 87: * Nothing locked. ! 88: * Returns: ! 89: * KERN_SUCCESS Retrieved number of send rights. ! 90: * KERN_INVALID_TASK The space is null. ! 91: * KERN_INVALID_TASK The space is dead. ! 92: * KERN_INVALID_NAME The name doesn't denote a right. ! 93: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 94: */ ! 95: ! 96: kern_return_t ! 97: mach_port_get_srights( ! 98: ipc_space_t space, ! 99: mach_port_name_t name, ! 100: mach_port_rights_t *srightsp) ! 101: { ! 102: #if !MACH_IPC_DEBUG ! 103: return KERN_FAILURE; ! 104: #else ! 105: ipc_port_t port; ! 106: kern_return_t kr; ! 107: mach_port_rights_t srights; ! 108: ! 109: if (space == IS_NULL) ! 110: return KERN_INVALID_TASK; ! 111: ! 112: kr = ipc_port_translate_receive(space, name, &port); ! 113: if (kr != KERN_SUCCESS) ! 114: return kr; ! 115: /* port is locked and active */ ! 116: ! 117: srights = port->ip_srights; ! 118: ip_unlock(port); ! 119: ! 120: *srightsp = srights; ! 121: return KERN_SUCCESS; ! 122: #endif /* MACH_IPC_DEBUG */ ! 123: } ! 124: ! 125: /* ! 126: * Routine: host_ipc_hash_info ! 127: * Purpose: ! 128: * Return information about the global reverse hash table. ! 129: * Conditions: ! 130: * Nothing locked. Obeys CountInOut protocol. ! 131: * Returns: ! 132: * KERN_SUCCESS Returned information. ! 133: * KERN_INVALID_HOST The host is null. ! 134: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 135: */ ! 136: ! 137: kern_return_t ! 138: host_ipc_hash_info( ! 139: host_t host, ! 140: hash_info_bucket_array_t *infop, ! 141: mach_msg_type_number_t *countp) ! 142: { ! 143: #if !MACH_IPC_DEBUG ! 144: return KERN_FAILURE; ! 145: #else ! 146: vm_offset_t addr; ! 147: vm_size_t size; ! 148: hash_info_bucket_t *info; ! 149: unsigned int potential, actual; ! 150: kern_return_t kr; ! 151: ! 152: if (host == HOST_NULL) ! 153: return KERN_INVALID_HOST; ! 154: ! 155: /* start with in-line data */ ! 156: ! 157: info = *infop; ! 158: potential = *countp; ! 159: ! 160: for (;;) { ! 161: actual = ipc_hash_info(info, potential); ! 162: if (actual <= potential) ! 163: break; ! 164: ! 165: /* allocate more memory */ ! 166: ! 167: if (info != *infop) ! 168: kmem_free(ipc_kernel_map, addr, size); ! 169: ! 170: size = round_page(actual * sizeof *info); ! 171: kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size); ! 172: if (kr != KERN_SUCCESS) ! 173: return KERN_RESOURCE_SHORTAGE; ! 174: ! 175: info = (hash_info_bucket_t *) addr; ! 176: potential = size/sizeof *info; ! 177: } ! 178: ! 179: if (info == *infop) { ! 180: /* data fit in-line; nothing to deallocate */ ! 181: ! 182: *countp = actual; ! 183: } else if (actual == 0) { ! 184: kmem_free(ipc_kernel_map, addr, size); ! 185: ! 186: *countp = 0; ! 187: } else { ! 188: vm_map_copy_t copy; ! 189: vm_size_t used; ! 190: ! 191: used = round_page(actual * sizeof *info); ! 192: ! 193: if (used != size) ! 194: kmem_free(ipc_kernel_map, addr + used, size - used); ! 195: ! 196: kr = vm_map_copyin(ipc_kernel_map, addr, used, ! 197: TRUE, ©); ! 198: assert(kr == KERN_SUCCESS); ! 199: ! 200: *infop = (hash_info_bucket_t *) copy; ! 201: *countp = actual; ! 202: } ! 203: ! 204: return KERN_SUCCESS; ! 205: #endif /* MACH_IPC_DEBUG */ ! 206: } ! 207: ! 208: /* ! 209: * Routine: mach_port_space_info ! 210: * Purpose: ! 211: * Returns information about an IPC space. ! 212: * Conditions: ! 213: * Nothing locked. Obeys CountInOut protocol. ! 214: * Returns: ! 215: * KERN_SUCCESS Returned information. ! 216: * KERN_INVALID_TASK The space is null. ! 217: * KERN_INVALID_TASK The space is dead. ! 218: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 219: */ ! 220: ! 221: kern_return_t ! 222: mach_port_space_info( ! 223: ipc_space_t space, ! 224: ipc_info_space_t *infop, ! 225: ipc_info_name_array_t *tablep, ! 226: mach_msg_type_number_t *tableCntp, ! 227: ipc_info_tree_name_array_t *treep, ! 228: mach_msg_type_number_t *treeCntp) ! 229: { ! 230: #if !MACH_IPC_DEBUG ! 231: return KERN_FAILURE; ! 232: #else ! 233: ipc_info_name_t *table_info; ! 234: unsigned int table_potential, table_actual; ! 235: vm_offset_t table_addr; ! 236: vm_size_t table_size; ! 237: ipc_info_tree_name_t *tree_info; ! 238: unsigned int tree_potential, tree_actual; ! 239: vm_offset_t tree_addr; ! 240: vm_size_t tree_size; ! 241: ipc_tree_entry_t tentry; ! 242: ipc_entry_t table; ! 243: ipc_entry_num_t tsize; ! 244: mach_port_index_t index; ! 245: kern_return_t kr; ! 246: ipc_entry_bits_t *capability; ! 247: ! 248: if (space == IS_NULL) ! 249: return KERN_INVALID_TASK; ! 250: ! 251: /* start with in-line memory */ ! 252: ! 253: table_info = *tablep; ! 254: table_potential = *tableCntp; ! 255: tree_info = *treep; ! 256: tree_potential = *treeCntp; ! 257: ! 258: for (;;) { ! 259: is_read_lock(space); ! 260: if (!space->is_active) { ! 261: is_read_unlock(space); ! 262: if (table_info != *tablep) ! 263: kmem_free(ipc_kernel_map, ! 264: table_addr, table_size); ! 265: if (tree_info != *treep) ! 266: kmem_free(ipc_kernel_map, ! 267: tree_addr, tree_size); ! 268: return KERN_INVALID_TASK; ! 269: } ! 270: ! 271: table_actual = space->is_table_size; ! 272: tree_actual = space->is_tree_total; ! 273: ! 274: if ((table_actual <= table_potential) && ! 275: (tree_actual <= tree_potential)) ! 276: break; ! 277: ! 278: is_read_unlock(space); ! 279: ! 280: if (table_actual > table_potential) { ! 281: if (table_info != *tablep) ! 282: kmem_free(ipc_kernel_map, ! 283: table_addr, table_size); ! 284: ! 285: table_size = round_page(table_actual * ! 286: sizeof *table_info); ! 287: kr = kmem_alloc(ipc_kernel_map, ! 288: &table_addr, table_size); ! 289: if (kr != KERN_SUCCESS) { ! 290: if (tree_info != *treep) ! 291: kmem_free(ipc_kernel_map, ! 292: tree_addr, tree_size); ! 293: ! 294: return KERN_RESOURCE_SHORTAGE; ! 295: } ! 296: ! 297: table_info = (ipc_info_name_t *) table_addr; ! 298: table_potential = table_size/sizeof *table_info; ! 299: } ! 300: ! 301: if (tree_actual > tree_potential) { ! 302: if (tree_info != *treep) ! 303: kmem_free(ipc_kernel_map, ! 304: tree_addr, tree_size); ! 305: ! 306: tree_size = round_page(tree_actual * ! 307: sizeof *tree_info); ! 308: kr = kmem_alloc(ipc_kernel_map, ! 309: &tree_addr, tree_size); ! 310: if (kr != KERN_SUCCESS) { ! 311: if (table_info != *tablep) ! 312: kmem_free(ipc_kernel_map, ! 313: table_addr, table_size); ! 314: ! 315: return KERN_RESOURCE_SHORTAGE; ! 316: } ! 317: ! 318: tree_info = (ipc_info_tree_name_t *) tree_addr; ! 319: tree_potential = tree_size/sizeof *tree_info; ! 320: } ! 321: } ! 322: /* space is read-locked and active; we have enough wired memory */ ! 323: ! 324: infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD); ! 325: infop->iis_table_size = space->is_table_size; ! 326: infop->iis_table_next = space->is_table_next->its_size; ! 327: infop->iis_tree_size = space->is_tree_total; ! 328: infop->iis_tree_small = space->is_tree_small; ! 329: infop->iis_tree_hash = space->is_tree_hash; ! 330: ! 331: table = space->is_table; ! 332: tsize = space->is_table_size; ! 333: ! 334: for (index = 0; index < tsize; index++) { ! 335: ipc_info_name_t *iin = &table_info[index]; ! 336: ipc_entry_t entry = &table[index]; ! 337: ipc_entry_bits_t bits; ! 338: ! 339: bits = entry->ie_bits; ! 340: iin->iin_name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits)); ! 341: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; ! 342: iin->iin_type = IE_BITS_TYPE(bits); ! 343: iin->iin_urefs = IE_BITS_UREFS(bits); ! 344: iin->iin_object = (vm_offset_t) entry->ie_object; ! 345: iin->iin_next = entry->ie_next; ! 346: iin->iin_hash = entry->ie_index; ! 347: } ! 348: ! 349: for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0; ! 350: tentry != ITE_NULL; ! 351: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { ! 352: ipc_info_tree_name_t *iitn = &tree_info[index++]; ! 353: ipc_info_name_t *iin = &iitn->iitn_name; ! 354: ipc_entry_t entry = &tentry->ite_entry; ! 355: ipc_entry_bits_t bits = entry->ie_bits; ! 356: ! 357: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE); ! 358: ! 359: iin->iin_name = tentry->ite_name; ! 360: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; ! 361: iin->iin_type = IE_BITS_TYPE(bits); ! 362: iin->iin_urefs = IE_BITS_UREFS(bits); ! 363: iin->iin_object = (vm_offset_t) entry->ie_object; ! 364: iin->iin_next = entry->ie_next; ! 365: iin->iin_hash = entry->ie_index; ! 366: ! 367: if (tentry->ite_lchild == ITE_NULL) ! 368: iitn->iitn_lchild = MACH_PORT_NULL; ! 369: else ! 370: iitn->iitn_lchild = tentry->ite_lchild->ite_name; ! 371: ! 372: if (tentry->ite_rchild == ITE_NULL) ! 373: iitn->iitn_rchild = MACH_PORT_NULL; ! 374: else ! 375: iitn->iitn_rchild = tentry->ite_rchild->ite_name; ! 376: ! 377: } ! 378: ipc_splay_traverse_finish(&space->is_tree); ! 379: is_read_unlock(space); ! 380: ! 381: if (table_info == *tablep) { ! 382: /* data fit in-line; nothing to deallocate */ ! 383: ! 384: *tableCntp = table_actual; ! 385: } else if (table_actual == 0) { ! 386: kmem_free(ipc_kernel_map, table_addr, table_size); ! 387: ! 388: *tableCntp = 0; ! 389: } else { ! 390: vm_size_t size_used, rsize_used; ! 391: vm_map_copy_t copy; ! 392: ! 393: /* kmem_alloc doesn't zero memory */ ! 394: ! 395: size_used = table_actual * sizeof *table_info; ! 396: rsize_used = round_page(size_used); ! 397: ! 398: if (rsize_used != table_size) ! 399: kmem_free(ipc_kernel_map, ! 400: table_addr + rsize_used, ! 401: table_size - rsize_used); ! 402: ! 403: if (size_used != rsize_used) ! 404: bzero((char *) (table_addr + size_used), ! 405: rsize_used - size_used); ! 406: ! 407: kr = vm_map_unwire(ipc_kernel_map, table_addr, ! 408: table_addr + rsize_used, FALSE); ! 409: assert(kr == KERN_SUCCESS); ! 410: ! 411: kr = vm_map_copyin(ipc_kernel_map, table_addr, rsize_used, ! 412: TRUE, ©); ! 413: assert(kr == KERN_SUCCESS); ! 414: ! 415: *tablep = (ipc_info_name_t *) copy; ! 416: *tableCntp = table_actual; ! 417: } ! 418: ! 419: if (tree_info == *treep) { ! 420: /* data fit in-line; nothing to deallocate */ ! 421: ! 422: *treeCntp = tree_actual; ! 423: } else if (tree_actual == 0) { ! 424: kmem_free(ipc_kernel_map, tree_addr, tree_size); ! 425: ! 426: *treeCntp = 0; ! 427: } else { ! 428: vm_size_t size_used, rsize_used; ! 429: vm_map_copy_t copy; ! 430: ! 431: /* kmem_alloc doesn't zero memory */ ! 432: ! 433: size_used = tree_actual * sizeof *tree_info; ! 434: rsize_used = round_page(size_used); ! 435: ! 436: if (rsize_used != tree_size) ! 437: kmem_free(ipc_kernel_map, ! 438: tree_addr + rsize_used, ! 439: tree_size - rsize_used); ! 440: ! 441: if (size_used != rsize_used) ! 442: bzero((char *) (tree_addr + size_used), ! 443: rsize_used - size_used); ! 444: ! 445: kr = vm_map_unwire(ipc_kernel_map, tree_addr, ! 446: tree_addr + rsize_used, FALSE); ! 447: assert(kr == KERN_SUCCESS); ! 448: ! 449: kr = vm_map_copyin(ipc_kernel_map, tree_addr, rsize_used, ! 450: TRUE, ©); ! 451: assert(kr == KERN_SUCCESS); ! 452: ! 453: *treep = (ipc_info_tree_name_t *) copy; ! 454: *treeCntp = tree_actual; ! 455: } ! 456: ! 457: return KERN_SUCCESS; ! 458: #endif /* MACH_IPC_DEBUG */ ! 459: } ! 460: ! 461: /* ! 462: * Routine: mach_port_dnrequest_info ! 463: * Purpose: ! 464: * Returns information about the dead-name requests ! 465: * registered with the named receive right. ! 466: * Conditions: ! 467: * Nothing locked. ! 468: * Returns: ! 469: * KERN_SUCCESS Retrieved information. ! 470: * KERN_INVALID_TASK The space is null. ! 471: * KERN_INVALID_TASK The space is dead. ! 472: * KERN_INVALID_NAME The name doesn't denote a right. ! 473: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 474: */ ! 475: ! 476: kern_return_t ! 477: mach_port_dnrequest_info( ! 478: ipc_space_t space, ! 479: mach_port_name_t name, ! 480: unsigned int *totalp, ! 481: unsigned int *usedp) ! 482: { ! 483: #if !MACH_IPC_DEBUG ! 484: return KERN_FAILURE; ! 485: #else ! 486: unsigned int total, used; ! 487: ipc_port_t port; ! 488: kern_return_t kr; ! 489: ! 490: if (space == IS_NULL) ! 491: return KERN_INVALID_TASK; ! 492: ! 493: kr = ipc_port_translate_receive(space, name, &port); ! 494: if (kr != KERN_SUCCESS) ! 495: return kr; ! 496: /* port is locked and active */ ! 497: ! 498: if (port->ip_dnrequests == IPR_NULL) { ! 499: total = 0; ! 500: used = 0; ! 501: } else { ! 502: ipc_port_request_t dnrequests = port->ip_dnrequests; ! 503: ipc_port_request_index_t index; ! 504: ! 505: total = dnrequests->ipr_size->its_size; ! 506: ! 507: for (index = 1, used = 0; ! 508: index < total; index++) { ! 509: ipc_port_request_t ipr = &dnrequests[index]; ! 510: ! 511: if (ipr->ipr_name != MACH_PORT_NULL) ! 512: used++; ! 513: } ! 514: } ! 515: ip_unlock(port); ! 516: ! 517: *totalp = total; ! 518: *usedp = used; ! 519: return KERN_SUCCESS; ! 520: #endif /* MACH_IPC_DEBUG */ ! 521: } ! 522: ! 523: /* ! 524: * Routine: mach_port_kernel_object [kernel call] ! 525: * Purpose: ! 526: * Retrieve the type and address of the kernel object ! 527: * represented by a send or receive right. ! 528: * Conditions: ! 529: * Nothing locked. ! 530: * Returns: ! 531: * KERN_SUCCESS Retrieved kernel object info. ! 532: * KERN_INVALID_TASK The space is null. ! 533: * KERN_INVALID_TASK The space is dead. ! 534: * KERN_INVALID_NAME The name doesn't denote a right. ! 535: * KERN_INVALID_RIGHT Name doesn't denote ! 536: * send or receive rights. ! 537: */ ! 538: ! 539: kern_return_t ! 540: mach_port_kernel_object( ! 541: ipc_space_t space, ! 542: mach_port_name_t name, ! 543: unsigned int *typep, ! 544: vm_offset_t *addrp) ! 545: { ! 546: #if !MACH_IPC_DEBUG ! 547: return KERN_FAILURE; ! 548: #else ! 549: ipc_entry_t entry; ! 550: ipc_port_t port; ! 551: kern_return_t kr; ! 552: ! 553: kr = ipc_right_lookup_read(space, name, &entry); ! 554: if (kr != KERN_SUCCESS) ! 555: return kr; ! 556: /* space is read-locked and active */ ! 557: ! 558: if ((entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) { ! 559: is_read_unlock(space); ! 560: return KERN_INVALID_RIGHT; ! 561: } ! 562: ! 563: port = (ipc_port_t) entry->ie_object; ! 564: assert(port != IP_NULL); ! 565: ! 566: ip_lock(port); ! 567: is_read_unlock(space); ! 568: ! 569: if (!ip_active(port)) { ! 570: ip_unlock(port); ! 571: return KERN_INVALID_RIGHT; ! 572: } ! 573: ! 574: *typep = (unsigned int) ip_kotype(port); ! 575: *addrp = (vm_offset_t) port->ip_kobject; ! 576: ip_unlock(port); ! 577: return KERN_SUCCESS; ! 578: ! 579: #endif /* MACH_IPC_DEBUG */ ! 580: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.