|
|
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.