X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8ad349bb6ed4a0be06e34c92be0d98b92e078db4..7e41aa883dd258f888d0470250eead40a53ef1f5:/osfmk/ipc/mach_debug.c?ds=sidebyside diff --git a/osfmk/ipc/mach_debug.c b/osfmk/ipc/mach_debug.c index 2bdb1eb32..25c472e15 100644 --- a/osfmk/ipc/mach_debug.c +++ b/osfmk/ipc/mach_debug.c @@ -1,31 +1,29 @@ /* * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the - * License may not be used to create, or enable the creation or - * redistribution of, unlawful or unlicensed copies of an Apple operating - * system, or to circumvent, violate, or enable the circumvention or - * violation of, any terms of an Apple operating system software license - * agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and * limitations under the License. - * - * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -86,6 +84,8 @@ #include #include #include + +#include #endif /* @@ -139,95 +139,6 @@ mach_port_get_srights( } #endif /* MACH_IPC_DEBUG */ -/* - * Routine: host_ipc_hash_info - * Purpose: - * Return information about the global reverse hash table. - * Conditions: - * Nothing locked. Obeys CountInOut protocol. - * Returns: - * KERN_SUCCESS Returned information. - * KERN_INVALID_HOST The host is null. - * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. - */ - -#if !MACH_IPC_DEBUG -kern_return_t -host_ipc_hash_info( - __unused host_t host, - __unused hash_info_bucket_array_t *infop, - __unused mach_msg_type_number_t *countp) -{ - return KERN_FAILURE; -} -#else -kern_return_t -host_ipc_hash_info( - host_t host, - hash_info_bucket_array_t *infop, - mach_msg_type_number_t *countp) -{ - vm_offset_t addr; - vm_size_t size = 0; - hash_info_bucket_t *info; - unsigned int potential, actual; - kern_return_t kr; - - if (host == HOST_NULL) - return KERN_INVALID_HOST; - - /* start with in-line data */ - - info = *infop; - potential = *countp; - - for (;;) { - actual = ipc_hash_info(info, potential); - if (actual <= potential) - break; - - /* allocate more memory */ - - if (info != *infop) - kmem_free(ipc_kernel_map, addr, size); - - size = round_page(actual * sizeof *info); - kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size); - if (kr != KERN_SUCCESS) - return KERN_RESOURCE_SHORTAGE; - - info = (hash_info_bucket_t *) addr; - potential = size/sizeof *info; - } - - if (info == *infop) { - /* data fit in-line; nothing to deallocate */ - - *countp = actual; - } else if (actual == 0) { - kmem_free(ipc_kernel_map, addr, size); - - *countp = 0; - } else { - vm_map_copy_t copy; - vm_size_t used; - - used = round_page(actual * sizeof *info); - - if (used != size) - kmem_free(ipc_kernel_map, addr + used, size - used); - - kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr, - (vm_map_size_t)used, TRUE, ©); - assert(kr == KERN_SUCCESS); - - *infop = (hash_info_bucket_t *) copy; - *countp = actual; - } - - return KERN_SUCCESS; -} -#endif /* MACH_IPC_DEBUG */ /* * Routine: mach_port_space_info @@ -257,115 +168,78 @@ mach_port_space_info( #else kern_return_t mach_port_space_info( - ipc_space_t space, - ipc_info_space_t *infop, + ipc_space_t space, + ipc_info_space_t *infop, ipc_info_name_array_t *tablep, mach_msg_type_number_t *tableCntp, - ipc_info_tree_name_array_t *treep, - mach_msg_type_number_t *treeCntp) + __unused ipc_info_tree_name_array_t *treep, + __unused mach_msg_type_number_t *treeCntp) { ipc_info_name_t *table_info; - unsigned int table_potential, table_actual; vm_offset_t table_addr; - vm_size_t table_size; - ipc_info_tree_name_t *tree_info; - unsigned int tree_potential, tree_actual; - vm_offset_t tree_addr; - vm_size_t tree_size; - ipc_tree_entry_t tentry; + vm_size_t table_size, table_size_needed; ipc_entry_t table; ipc_entry_num_t tsize; mach_port_index_t index; kern_return_t kr; + vm_map_copy_t copy; + if (space == IS_NULL) return KERN_INVALID_TASK; +#if !(DEVELOPMENT | DEBUG) + const boolean_t dbg_ok = (mac_task_check_expose_task(kernel_task) == 0); +#else + const boolean_t dbg_ok = TRUE; +#endif + /* start with in-line memory */ table_size = 0; - table_info = *tablep; - table_potential = *tableCntp; - tree_size = 0; - tree_info = *treep; - tree_potential = *treeCntp; for (;;) { is_read_lock(space); - if (!space->is_active) { + if (!is_active(space)) { is_read_unlock(space); - if (table_info != *tablep) + if (table_size != 0) kmem_free(ipc_kernel_map, table_addr, table_size); - if (tree_info != *treep) - kmem_free(ipc_kernel_map, - tree_addr, tree_size); return KERN_INVALID_TASK; } - table_actual = space->is_table_size; - tree_actual = space->is_tree_total; + table_size_needed = + vm_map_round_page((space->is_table_size + * sizeof(ipc_info_name_t)), + VM_MAP_PAGE_MASK(ipc_kernel_map)); - if ((table_actual <= table_potential) && - (tree_actual <= tree_potential)) + if (table_size_needed == table_size) break; is_read_unlock(space); - if (table_actual > table_potential) { - if (table_info != *tablep) - kmem_free(ipc_kernel_map, - table_addr, table_size); - - table_size = round_page(table_actual * - sizeof *table_info); - kr = kmem_alloc(ipc_kernel_map, - &table_addr, table_size); + if (table_size != table_size_needed) { + if (table_size != 0) + kmem_free(ipc_kernel_map, table_addr, table_size); + kr = kmem_alloc(ipc_kernel_map, &table_addr, table_size_needed, VM_KERN_MEMORY_IPC); if (kr != KERN_SUCCESS) { - if (tree_info != *treep) - kmem_free(ipc_kernel_map, - tree_addr, tree_size); - return KERN_RESOURCE_SHORTAGE; } - - table_info = (ipc_info_name_t *) table_addr; - table_potential = table_size/sizeof *table_info; + table_size = table_size_needed; } - if (tree_actual > tree_potential) { - if (tree_info != *treep) - kmem_free(ipc_kernel_map, - tree_addr, tree_size); - - tree_size = round_page(tree_actual * - sizeof *tree_info); - kr = kmem_alloc(ipc_kernel_map, - &tree_addr, tree_size); - if (kr != KERN_SUCCESS) { - if (table_info != *tablep) - kmem_free(ipc_kernel_map, - table_addr, table_size); - - return KERN_RESOURCE_SHORTAGE; - } - - tree_info = (ipc_info_tree_name_t *) tree_addr; - tree_potential = tree_size/sizeof *tree_info; - } } /* space is read-locked and active; we have enough wired memory */ + /* get the overall space info */ infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD); infop->iis_table_size = space->is_table_size; infop->iis_table_next = space->is_table_next->its_size; - infop->iis_tree_size = space->is_tree_total; - infop->iis_tree_small = space->is_tree_small; - infop->iis_tree_hash = space->is_tree_hash; + /* walk the table for this space */ table = space->is_table; tsize = space->is_table_size; - + table_info = (ipc_info_name_array_t)table_addr; for (index = 0; index < tsize; index++) { ipc_info_name_t *iin = &table_info[index]; ipc_entry_t entry = &table[index]; @@ -373,121 +247,105 @@ mach_port_space_info( bits = entry->ie_bits; iin->iin_name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits)); - iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; + iin->iin_collision = 0; iin->iin_type = IE_BITS_TYPE(bits); - iin->iin_urefs = IE_BITS_UREFS(bits); - iin->iin_object = (vm_offset_t) entry->ie_object; - iin->iin_next = entry->ie_next; - iin->iin_hash = entry->ie_index; - } - - for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0; - tentry != ITE_NULL; - tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { - ipc_info_tree_name_t *iitn = &tree_info[index++]; - ipc_info_name_t *iin = &iitn->iitn_name; - ipc_entry_t entry = &tentry->ite_entry; - ipc_entry_bits_t bits = entry->ie_bits; - - assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE); + if ((entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) != MACH_PORT_TYPE_NONE && + entry->ie_request != IE_REQ_NONE) { + __IGNORE_WCASTALIGN(ipc_port_t port = (ipc_port_t) entry->ie_object); + + assert(IP_VALID(port)); + ip_lock(port); + iin->iin_type |= ipc_port_request_type(port, iin->iin_name, entry->ie_request); + ip_unlock(port); + } - iin->iin_name = tentry->ite_name; - iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; - iin->iin_type = IE_BITS_TYPE(bits); iin->iin_urefs = IE_BITS_UREFS(bits); - iin->iin_object = (vm_offset_t) entry->ie_object; + iin->iin_object = (dbg_ok) ? (natural_t)VM_KERNEL_ADDRPERM((uintptr_t)entry->ie_object) : 0; iin->iin_next = entry->ie_next; iin->iin_hash = entry->ie_index; - - if (tentry->ite_lchild == ITE_NULL) - iitn->iitn_lchild = MACH_PORT_NULL; - else - iitn->iitn_lchild = tentry->ite_lchild->ite_name; - - if (tentry->ite_rchild == ITE_NULL) - iitn->iitn_rchild = MACH_PORT_NULL; - else - iitn->iitn_rchild = tentry->ite_rchild->ite_name; - } - ipc_splay_traverse_finish(&space->is_tree); - is_read_unlock(space); - - if (table_info == *tablep) { - /* data fit in-line; nothing to deallocate */ - - *tableCntp = table_actual; - } else if (table_actual == 0) { - kmem_free(ipc_kernel_map, table_addr, table_size); - - *tableCntp = 0; - } else { - vm_size_t size_used, rsize_used; - vm_map_copy_t copy; - - /* kmem_alloc doesn't zero memory */ - size_used = table_actual * sizeof *table_info; - rsize_used = round_page(size_used); - - if (rsize_used != table_size) - kmem_free(ipc_kernel_map, - table_addr + rsize_used, - table_size - rsize_used); - - if (size_used != rsize_used) - bzero((char *) (table_addr + size_used), - rsize_used - size_used); + is_read_unlock(space); - kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(table_addr), - vm_map_round_page(table_addr + rsize_used), FALSE); + /* prepare the table out-of-line data for return */ + if (table_size > 0) { + vm_size_t used_table_size; + + used_table_size = infop->iis_table_size * sizeof(ipc_info_name_t); + if (table_size > used_table_size) + bzero((char *)&table_info[infop->iis_table_size], + table_size - used_table_size); + + kr = vm_map_unwire( + ipc_kernel_map, + vm_map_trunc_page(table_addr, + VM_MAP_PAGE_MASK(ipc_kernel_map)), + vm_map_round_page(table_addr + table_size, + VM_MAP_PAGE_MASK(ipc_kernel_map)), + FALSE); assert(kr == KERN_SUCCESS); - kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)table_addr, - (vm_map_size_t)rsize_used, TRUE, ©); + (vm_map_size_t)used_table_size, TRUE, ©); assert(kr == KERN_SUCCESS); - - *tablep = (ipc_info_name_t *) copy; - *tableCntp = table_actual; - } - - if (tree_info == *treep) { - /* data fit in-line; nothing to deallocate */ - - *treeCntp = tree_actual; - } else if (tree_actual == 0) { - kmem_free(ipc_kernel_map, tree_addr, tree_size); - - *treeCntp = 0; + *tablep = (ipc_info_name_t *)copy; + *tableCntp = infop->iis_table_size; } else { - vm_size_t size_used, rsize_used; - vm_map_copy_t copy; + *tablep = (ipc_info_name_t *)0; + *tableCntp = 0; + } - /* kmem_alloc doesn't zero memory */ + /* splay tree is obsolete, no work to do... */ + *treep = (ipc_info_tree_name_t *)0; + *treeCntp = 0; + return KERN_SUCCESS; +} +#endif /* MACH_IPC_DEBUG */ - size_used = tree_actual * sizeof *tree_info; - rsize_used = round_page(size_used); +/* + * Routine: mach_port_space_basic_info + * Purpose: + * Returns basic information about an IPC space. + * Conditions: + * Nothing locked. + * Returns: + * KERN_SUCCESS Returned information. + * KERN_FAILURE The call is not supported. + * KERN_INVALID_TASK The space is dead. + */ - if (rsize_used != tree_size) - kmem_free(ipc_kernel_map, - tree_addr + rsize_used, - tree_size - rsize_used); +#if !MACH_IPC_DEBUG +kern_return_t +mach_port_space_basic_info( + __unused ipc_space_t space, + __unused ipc_info_space_basic_t *infop) +{ + return KERN_FAILURE; +} +#else +kern_return_t +mach_port_space_basic_info( + ipc_space_t space, + ipc_info_space_basic_t *infop) +{ + if (space == IS_NULL) + return KERN_INVALID_TASK; - if (size_used != rsize_used) - bzero((char *) (tree_addr + size_used), - rsize_used - size_used); - kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(tree_addr), - vm_map_round_page(tree_addr + rsize_used), FALSE); - assert(kr == KERN_SUCCESS); + is_read_lock(space); + if (!is_active(space)) { + is_read_unlock(space); + return KERN_INVALID_TASK; + } - kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)tree_addr, - (vm_map_size_t)rsize_used, TRUE, ©); - assert(kr == KERN_SUCCESS); + /* get the basic space info */ + infop->iisb_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD); + infop->iisb_table_size = space->is_table_size; + infop->iisb_table_next = space->is_table_next->its_size; + infop->iisb_table_inuse = space->is_table_size - space->is_table_free - 1; + infop->iisb_reserved[0] = 0; + infop->iisb_reserved[1] = 0; - *treep = (ipc_info_tree_name_t *) copy; - *treeCntp = tree_actual; - } + is_read_unlock(space); return KERN_SUCCESS; } @@ -538,18 +396,18 @@ mach_port_dnrequest_info( return kr; /* port is locked and active */ - if (port->ip_dnrequests == IPR_NULL) { + if (port->ip_requests == IPR_NULL) { total = 0; used = 0; } else { - ipc_port_request_t dnrequests = port->ip_dnrequests; + ipc_port_request_t requests = port->ip_requests; ipc_port_request_index_t index; - total = dnrequests->ipr_size->its_size; + total = requests->ipr_size->its_size; for (index = 1, used = 0; index < total; index++) { - ipc_port_request_t ipr = &dnrequests[index]; + ipc_port_request_t ipr = &requests[index]; if (ipr->ipr_name != MACH_PORT_NULL) used++; @@ -564,10 +422,13 @@ mach_port_dnrequest_info( #endif /* MACH_IPC_DEBUG */ /* - * Routine: mach_port_kernel_object [kernel call] + * Routine: mach_port_kobject [kernel call] * Purpose: * Retrieve the type and address of the kernel object - * represented by a send or receive right. + * represented by a send or receive right. Returns + * the kernel address in a mach_vm_address_t to + * mask potential differences in kernel address space + * size. * Conditions: * Nothing locked. * Returns: @@ -581,25 +442,29 @@ mach_port_dnrequest_info( #if !MACH_IPC_DEBUG kern_return_t -mach_port_kernel_object( +mach_port_kobject( __unused ipc_space_t space, __unused mach_port_name_t name, - __unused unsigned int *typep, - __unused vm_offset_t *addrp) + __unused natural_t *typep, + __unused mach_vm_address_t *addrp) { return KERN_FAILURE; } #else kern_return_t -mach_port_kernel_object( +mach_port_kobject( ipc_space_t space, mach_port_name_t name, - unsigned int *typep, - vm_offset_t *addrp) + natural_t *typep, + mach_vm_address_t *addrp) { ipc_entry_t entry; ipc_port_t port; kern_return_t kr; + mach_vm_address_t kaddr; + + if (space == IS_NULL) + return KERN_INVALID_TASK; kr = ipc_right_lookup_read(space, name, &entry); if (kr != KERN_SUCCESS) @@ -611,7 +476,7 @@ mach_port_kernel_object( return KERN_INVALID_RIGHT; } - port = (ipc_port_t) entry->ie_object; + __IGNORE_WCASTALIGN(port = (ipc_port_t) entry->ie_object); assert(port != IP_NULL); ip_lock(port); @@ -623,9 +488,60 @@ mach_port_kernel_object( } *typep = (unsigned int) ip_kotype(port); - *addrp = (vm_offset_t) port->ip_kobject; + kaddr = (mach_vm_address_t)port->ip_kobject; ip_unlock(port); + +#if (DEVELOPMENT || DEBUG) + if (0 != kaddr && is_ipc_kobject(*typep)) + *addrp = VM_KERNEL_UNSLIDE_OR_PERM(kaddr); + else +#endif + *addrp = 0; + return KERN_SUCCESS; +} +#endif /* MACH_IPC_DEBUG */ +/* + * Routine: mach_port_kernel_object [Legacy kernel call] + * Purpose: + * Retrieve the type and address of the kernel object + * represented by a send or receive right. Hard-coded + * to return only the low-order 32-bits of the kernel + * object. + * Conditions: + * Nothing locked. + * Returns: + * KERN_SUCCESS Retrieved kernel object info. + * KERN_INVALID_TASK The space is null. + * KERN_INVALID_TASK The space is dead. + * KERN_INVALID_NAME The name doesn't denote a right. + * KERN_INVALID_RIGHT Name doesn't denote + * send or receive rights. + */ + +#if !MACH_IPC_DEBUG +kern_return_t +mach_port_kernel_object( + __unused ipc_space_t space, + __unused mach_port_name_t name, + __unused unsigned int *typep, + __unused unsigned int *addrp) +{ + return KERN_FAILURE; +} +#else +kern_return_t +mach_port_kernel_object( + ipc_space_t space, + mach_port_name_t name, + unsigned int *typep, + unsigned int *addrp) +{ + mach_vm_address_t addr = 0; + kern_return_t kr; + kr = mach_port_kobject(space, name, typep, &addr); + *addrp = (unsigned int) addr; + return kr; } #endif /* MACH_IPC_DEBUG */