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