]> git.saurik.com Git - apple/system_cmds.git/blame - lsmp.tproj/task_details.c
system_cmds-880.100.5.tar.gz
[apple/system_cmds.git] / lsmp.tproj / task_details.c
CommitLineData
1a7e3f61 1/*
cf37c299 2 * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
1a7e3f61
A
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#include <unistd.h>
24#include <mach/mach.h>
25#include <mach/mach_error.h>
26#include <mach_debug/ipc_info.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <libproc.h>
cf37c299 30#include <assert.h>
1a7e3f61
A
31
32#include "common.h"
33
cf37c299
A
34#pragma mark kobject to name hash table implementation
35
36#if (K2N_TABLE_SIZE & (K2N_TABLE_SIZE - 1) != 0)
37#error K2N_TABLE_SIZE must be a power of two
38#endif
39
40#define K2N_TABLE_MASK (K2N_TABLE_SIZE - 1)
41
42static uint32_t k2n_hash(natural_t kobject) {
43 return (uint64_t)kobject * 2654435761 >> 32;
44}
45
530d02b6 46static struct k2n_table_node *k2n_table_lookup_next_internal(struct k2n_table_node *node, natural_t kobject) {
cf37c299
A
47 while (node) {
48 if (kobject == node->kobject)
49 return node;
50
51 node = node->next;
52 }
53
54 return NULL;
55}
56
530d02b6
A
57struct k2n_table_node *k2n_table_lookup_next(struct k2n_table_node *node, natural_t kobject) {
58 if (!node) {
59 return NULL;
60 }
61 return k2n_table_lookup_next_internal(node->next, kobject);
62}
63
cf37c299
A
64struct k2n_table_node *k2n_table_lookup(struct k2n_table_node **table, natural_t kobject) {
65 uint32_t hv;
66 struct k2n_table_node *node;
67
68 hv = k2n_hash(kobject);
69
70 node = table[hv & K2N_TABLE_MASK];
71
530d02b6 72 return k2n_table_lookup_next_internal(node, kobject);
cf37c299
A
73}
74
75static void k2n_table_enter(struct k2n_table_node **table, natural_t kobject, ipc_info_name_t *info_name) {
76 uint32_t hv;
77 struct k2n_table_node *node;
78
79 hv = k2n_hash(kobject);
80
81 node = malloc(sizeof (struct k2n_table_node));
82 assert(node);
83
84 node->kobject = kobject;
85 node->info_name = info_name;
530d02b6 86 assert(kobject == info_name->iin_object);
cf37c299
A
87
88 node->next = table[hv & K2N_TABLE_MASK];
89 table[hv & K2N_TABLE_MASK] = node;
90}
91
92#pragma mark -
93
1a7e3f61
A
94static my_per_task_info_t NOT_FOUND_TASK_INFO = {
95 .task = NULL,
96 .task_kobject = NULL,
97 .pid = -1,
98 .info = {0,0,0,0,0,0},
99 .table = NULL,
100 .tableCount = 0,
101 .tree = NULL,
102 .treeCount = 0,
103 .valid = FALSE,
cf37c299 104 .k2ntable = {0},
1a7e3f61 105 .processName = "Unknown",
ac27e6b4
A
106 .exceptionInfo = {0},
107 .threadInfos = NULL,
108 .threadCount = 0,
109 .threadExceptionInfos = NULL
1a7e3f61
A
110};
111
112char * get_task_name_by_pid(pid_t pid);
113
114static void proc_pid_to_name(int pid, char *pname){
115 if (0 == proc_name(pid, pname, PROC_NAME_LEN)) {
116 strcpy(pname, "Unknown Process");
117 }
118}
119
120static my_per_task_info_t *global_taskinfo = NULL;
121static uint32_t global_taskcount = 0;
122
123my_per_task_info_t * allocate_taskinfo_memory(uint32_t taskCount)
124{
125 my_per_task_info_t * retval = malloc(taskCount * sizeof(my_per_task_info_t));
126 if (retval) {
127 bzero((void *)retval, taskCount * sizeof(my_per_task_info_t));
128 }
129 global_taskcount = taskCount;
130 global_taskinfo = retval;
131 return retval;
132}
133
134void deallocate_taskinfo_memory(my_per_task_info_t *data){
135 if (data) {
136 free(data);
137 global_taskinfo = NULL;
138 global_taskcount = 0;
139 }
140}
141
00bf83c0 142kern_return_t collect_per_task_info(my_per_task_info_t *taskinfo, task_read_t target_task)
1a7e3f61 143{
cf37c299 144 int i;
1a7e3f61
A
145 kern_return_t ret = KERN_SUCCESS;
146 unsigned int kotype = 0;
147 vm_offset_t kobject = (vm_offset_t)0;
cf37c299 148
1a7e3f61
A
149 taskinfo->task = target_task;
150 pid_for_task(target_task, &taskinfo->pid);
ac27e6b4 151
00bf83c0 152 ret = task_get_exception_ports_info(taskinfo->task, EXC_MASK_ALL, taskinfo->exceptionInfo.masks, &taskinfo->exceptionInfo.count, taskinfo->exceptionInfo.ports_info, taskinfo->exceptionInfo.behaviors, taskinfo->exceptionInfo.flavors);
ac27e6b4
A
153
154 if (ret != KERN_SUCCESS) {
00bf83c0 155 fprintf(stderr, "task_get_exception_ports_info() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret));
ac27e6b4
A
156 taskinfo->pid = 0;
157 }
158
159 /* collect threads port as well */
160 taskinfo->threadCount = 0;
161 thread_act_array_t threadPorts;
162 ret = task_threads(taskinfo->task, &threadPorts, &taskinfo->threadCount);
163
164 if (ret != KERN_SUCCESS) {
165 fprintf(stderr, "task_threads() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret));
166 taskinfo->threadCount = 0;
167 } else {
168 /* collect the thread information */
169 taskinfo->threadInfos = (struct my_per_thread_info *)malloc(sizeof(struct my_per_thread_info) * taskinfo->threadCount);
170 bzero(taskinfo->threadInfos, sizeof(struct my_per_thread_info) * taskinfo->threadCount);
171
172 /* now collect exception ports for each of those threads as well */
173 taskinfo->threadExceptionInfos = (struct exc_port_info *) malloc(sizeof(struct exc_port_info) * taskinfo->threadCount);
174 boolean_t found_exception = false;
175 for (int i = 0; i < taskinfo->threadCount; i++) {
176 unsigned th_kobject = 0;
177 unsigned th_kotype = 0;
178 ipc_voucher_t th_voucher = IPC_VOUCHER_NULL;
179 thread_identifier_info_data_t th_info;
180 mach_msg_type_number_t th_info_count = THREAD_IDENTIFIER_INFO_COUNT;
181 struct exc_port_info *excinfo = &(taskinfo->threadExceptionInfos[i]);
182
00bf83c0 183 ret = thread_get_exception_ports_info(threadPorts[i], EXC_MASK_ALL, excinfo->masks, &excinfo->count, excinfo->ports_info, excinfo->behaviors, excinfo->flavors);
ac27e6b4 184 if (ret != KERN_SUCCESS){
00bf83c0 185 fprintf(stderr, "thread_get_exception_ports_info() failed: pid: %d thread: %d error %s\n", taskinfo->pid, threadPorts[i], mach_error_string(ret));
ac27e6b4
A
186 }
187
188 if (excinfo->count != 0) {
189 found_exception = true;
190 }
191
192 taskinfo->threadInfos[i].thread = threadPorts[i];
193
194 if (KERN_SUCCESS == mach_port_kernel_object(mach_task_self(), threadPorts[i], &th_kotype, &th_kobject)) {
195 taskinfo->threadInfos[i].th_kobject = th_kobject;
196 if (KERN_SUCCESS == thread_info(threadPorts[i], THREAD_IDENTIFIER_INFO, (thread_info_t)&th_info, &th_info_count)) {
197 taskinfo->threadInfos[i].th_id = th_info.thread_id;
198 }
199 }
200
201 if (KERN_SUCCESS == thread_get_mach_voucher(threadPorts[i], 0, &th_voucher) && th_voucher != IPC_VOUCHER_NULL) {
887d5eed 202 char *detail = copy_voucher_detail(mach_task_self(), th_voucher, NULL);
ac27e6b4
A
203 taskinfo->threadInfos[i].voucher_detail = strndup(detail, VOUCHER_DETAIL_MAXLEN);
204 free(detail);
205
206 mach_port_deallocate(mach_task_self(), th_voucher);
207 }
208
209 mach_port_deallocate(mach_task_self(), threadPorts[i]);
210 threadPorts[i] = MACH_PORT_NULL;
211 }
212
213 if (found_exception == false) {
214 free(taskinfo->threadExceptionInfos);
215 taskinfo->threadExceptionInfos = NULL;
216 }
217
218 }
219
220 vm_deallocate(mach_task_self(), threadPorts, taskinfo->threadCount * sizeof(thread_act_t));
221 threadPorts = NULL;
cf37c299 222
ac27e6b4 223 ret = mach_port_space_info(target_task, &taskinfo->info, &taskinfo->table, &taskinfo->tableCount, &taskinfo->tree, &taskinfo->treeCount);
cf37c299 224
1a7e3f61
A
225 if (ret != KERN_SUCCESS) {
226 fprintf(stderr, "mach_port_space_info() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret));
227 taskinfo->pid = 0;
228 return ret;
229 }
cf37c299
A
230
231 bzero(taskinfo->k2ntable, K2N_TABLE_SIZE * sizeof (struct k2n_table_node *));
232 for (i = 0; i < taskinfo->tableCount; i++) {
233 k2n_table_enter(taskinfo->k2ntable, taskinfo->table[i].iin_object, &taskinfo->table[i]);
234 }
235
1a7e3f61 236 proc_pid_to_name(taskinfo->pid, taskinfo->processName);
ac27e6b4 237
1a7e3f61 238 ret = mach_port_kernel_object(mach_task_self(), taskinfo->task, &kotype, (unsigned *)&kobject);
00bf83c0
A
239
240 /* Now that we are using read ports, kotype should be checked against IKOT_TASK_READ */
241 if (ret == KERN_SUCCESS && kotype == IKOT_TASK_READ) {
1a7e3f61
A
242 taskinfo->task_kobject = kobject;
243 taskinfo->valid = TRUE;
244 }
cf37c299 245
1a7e3f61
A
246 return ret;
247}
248
1a7e3f61
A
249void get_exc_behavior_string(exception_behavior_t b, char *out_string, size_t len)
250{
251 out_string[0]='\0';
cf37c299 252
1a7e3f61 253 if (b & MACH_EXCEPTION_CODES)
530d02b6 254 strlcat(out_string, "MACH +", len);
1a7e3f61
A
255 switch (b & ~MACH_EXCEPTION_CODES) {
256 case EXCEPTION_DEFAULT:
530d02b6 257 strlcat(out_string, " DEFAULT", len);
1a7e3f61
A
258 break;
259 case EXCEPTION_STATE:
530d02b6 260 strlcat(out_string, " STATE", len);
1a7e3f61
A
261 break;
262 case EXCEPTION_STATE_IDENTITY:
530d02b6 263 strlcat(out_string, " IDENTITY", len);
1a7e3f61
A
264 break;
265 default:
530d02b6 266 strlcat(out_string, " UNKNOWN", len);
1a7e3f61
A
267 }
268}
269
270void get_exc_mask_string(exception_mask_t m, char *out_string, size_t len)
271{
272 out_string[0]='\0';
cf37c299 273
1a7e3f61 274 if (m & (1<<EXC_BAD_ACCESS))
530d02b6 275 strlcat(out_string, " BAD_ACCESS", len);
1a7e3f61 276 if (m & (1<<EXC_BAD_INSTRUCTION))
530d02b6 277 strlcat(out_string," BAD_INSTRUCTION", len);
1a7e3f61 278 if (m & (1<<EXC_ARITHMETIC))
530d02b6 279 strlcat(out_string," ARITHMETIC", len);
1a7e3f61 280 if (m & (1<<EXC_EMULATION))
530d02b6 281 strlcat(out_string," EMULATION", len);
1a7e3f61 282 if (m & (1<<EXC_SOFTWARE))
530d02b6 283 strlcat(out_string," SOFTWARE", len);
1a7e3f61 284 if (m & (1<<EXC_BREAKPOINT))
530d02b6 285 strlcat(out_string," BREAKPOINT", len);
1a7e3f61 286 if (m & (1<<EXC_SYSCALL))
530d02b6 287 strlcat(out_string," SYSCALL", len);
1a7e3f61 288 if (m & (1<<EXC_MACH_SYSCALL))
530d02b6 289 strlcat(out_string," MACH_SYSCALL", len);
1a7e3f61 290 if (m & (1<<EXC_RPC_ALERT))
530d02b6 291 strlcat(out_string," RPC_ALERT", len);
1a7e3f61 292 if (m & (1<<EXC_CRASH))
530d02b6 293 strlcat(out_string," CRASH", len);
1a7e3f61 294 if (m & (1<<EXC_RESOURCE))
530d02b6 295 strlcat(out_string," RESOURCE", len);
1a7e3f61 296 if (m & (1<<EXC_GUARD))
530d02b6 297 strlcat(out_string," GUARD", len);
1a7e3f61
A
298}
299
887d5eed 300kern_return_t print_task_exception_info(my_per_task_info_t *taskinfo, JSON_t json)
1a7e3f61 301{
ac27e6b4 302
1a7e3f61
A
303 char behavior_string[30];
304 char mask_string[200];
ac27e6b4 305
887d5eed
A
306 JSON_KEY(json, exception_ports);
307 JSON_ARRAY_BEGIN(json);
308
1a7e3f61 309 boolean_t header_required = TRUE;
ac27e6b4 310 for (int i = 0; i < taskinfo->exceptionInfo.count; i++) {
00bf83c0
A
311 if (taskinfo->exceptionInfo.ports_info[i].iip_port_object != 0) {
312 my_per_task_info_t * _found_task;
313
1a7e3f61 314 if (header_required) {
ac27e6b4 315
00bf83c0 316 printf(" exc_port_object receiver_task flavor <behaviors> mask \n");
1a7e3f61
A
317 header_required = FALSE;
318 }
ac27e6b4 319 get_exc_behavior_string(taskinfo->exceptionInfo.behaviors[i], behavior_string, sizeof(behavior_string));
530d02b6 320 get_exc_mask_string(taskinfo->exceptionInfo.masks[i], mask_string, sizeof(mask_string));
887d5eed
A
321
322 JSON_OBJECT_BEGIN(json);
00bf83c0
A
323 JSON_OBJECT_SET(json, port_object, "0x%08x", taskinfo->exceptionInfo.ports_info[i].iip_port_object);
324 JSON_OBJECT_SET(json, receiver_object, "0x%08x", taskinfo->exceptionInfo.ports_info[i].iip_receiver_object);
887d5eed
A
325 JSON_OBJECT_SET(json, flavor, "0x%03x", taskinfo->exceptionInfo.flavors[i]);
326 JSON_OBJECT_SET(json, behavior, "%s", behavior_string);
327 JSON_OBJECT_SET(json, mask, "%s", mask_string);
328 JSON_OBJECT_END(json); // exception port
00bf83c0
A
329
330 _found_task = get_taskinfo_by_kobject((natural_t)taskinfo->exceptionInfo.ports_info[i].iip_receiver_object);
331
332 printf(" 0x%08x (%d) %s 0x%03x <%s> %s \n",
333 taskinfo->exceptionInfo.ports_info[i].iip_port_object,
334 _found_task->pid,
335 _found_task->processName,
336 taskinfo->exceptionInfo.flavors[i], behavior_string, mask_string);
1a7e3f61 337 }
cf37c299 338
1a7e3f61 339 }
cf37c299 340
887d5eed
A
341 JSON_ARRAY_END(json); // exception ports
342
ac27e6b4 343 return KERN_SUCCESS;
1a7e3f61
A
344}
345
346
887d5eed 347kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo, JSON_t json)
1a7e3f61
A
348{
349 kern_return_t kret = KERN_SUCCESS;
ac27e6b4 350 mach_msg_type_number_t threadcount = taskinfo->threadCount;
1a7e3f61
A
351 boolean_t header_required = TRUE;
352 boolean_t newline_required = TRUE;
ac27e6b4 353 struct my_per_thread_info * info = NULL;
cf37c299 354
887d5eed
A
355 JSON_KEY(json, threads);
356 JSON_ARRAY_BEGIN(json);
357
1a7e3f61 358 for (int i = 0; i < threadcount; i++) {
887d5eed
A
359 JSON_OBJECT_BEGIN(json);
360
ac27e6b4 361 info = &taskinfo->threadInfos[i];
1a7e3f61 362 if (header_required) {
ac27e6b4 363 printf("Thread_KObject Thread-ID Port Description.");
1a7e3f61
A
364 header_required = FALSE;
365 }
cf37c299 366
1a7e3f61
A
367 if (newline_required) {
368 printf("\n");
369 }
370 newline_required = TRUE;
cf37c299 371
ac27e6b4 372 if (info->th_kobject != 0) {
1a7e3f61 373 /* TODO: Should print tid and stuff */
ac27e6b4
A
374 printf("0x%08x ", info->th_kobject);
375 printf("0x%llx ", info->th_id);
887d5eed
A
376
377 JSON_OBJECT_SET(json, kobject, "0x%08x", info->th_kobject);
378 JSON_OBJECT_SET(json, tid, "0x%llx", info->th_id);
1a7e3f61
A
379 }
380
ac27e6b4 381 if (info->voucher_detail != NULL) {
887d5eed 382 /* TODO: include voucher detail in JSON */
ac27e6b4
A
383 printf("%s\n", info->voucher_detail);
384 }
385
887d5eed
A
386 JSON_KEY(json, exception_ports);
387 JSON_ARRAY_BEGIN(json);
388
ac27e6b4
A
389 /* print the thread exception ports also */
390 if (taskinfo->threadExceptionInfos != NULL)
391 {
392
393 struct exc_port_info *excinfo = &taskinfo->threadExceptionInfos[i];
394 char behavior_string[30];
395 char mask_string[200];
396
397 if (excinfo->count > 0) {
398 boolean_t header_required = TRUE;
399 for (int i = 0; i < excinfo->count; i++) {
887d5eed
A
400 JSON_OBJECT_BEGIN(json);
401
00bf83c0 402 if (excinfo->ports_info[i].iip_port_object != 0) {
ac27e6b4 403 if (header_required) {
00bf83c0 404 printf("\n exc_port_object exc_port_receiver flavor <behaviors> mask -> name owner\n");
ac27e6b4
A
405 header_required = FALSE;
406 }
407 get_exc_behavior_string(excinfo->behaviors[i], behavior_string, sizeof(behavior_string));
408 get_exc_mask_string(excinfo->masks[i], mask_string, sizeof(mask_string));
887d5eed 409
00bf83c0
A
410 JSON_OBJECT_SET(json, port_object, "0x%08x", excinfo->ports_info[i].iip_port_object);
411 JSON_OBJECT_SET(json, receiver_object, "0x%08x", excinfo->ports_info[i].iip_receiver_object);
887d5eed
A
412 JSON_OBJECT_SET(json, flavor, "0x%03x", excinfo->flavors[i]);
413 JSON_OBJECT_SET(json, behavior, "%s", behavior_string);
414 JSON_OBJECT_SET(json, mask, "%s", mask_string);
415
00bf83c0
A
416 printf(" 0x%08x 0x%08x 0x%03x <%s> %s " , excinfo->ports_info[i].iip_port_object, excinfo->ports_info[i].iip_receiver_object, excinfo->flavors[i], behavior_string, mask_string);
417
418 my_per_task_info_t *recv_holder_taskinfo;
419 mach_port_name_t recv_name = MACH_PORT_NULL;
420 if (KERN_SUCCESS == get_taskinfo_of_receiver_by_send_right_info(excinfo->ports_info[i], &recv_holder_taskinfo, &recv_name)) {
421 JSON_OBJECT_SET(json, name, "0x%08x", recv_name);
422 JSON_OBJECT_SET(json, ipc-object, "0x%08x", excinfo->ports_info[i].iip_port_object);
423 JSON_OBJECT_SET(json, pid, %d, recv_holder_taskinfo->pid);
424 JSON_OBJECT_SET(json, process, "%s", recv_holder_taskinfo->processName);
425
426 printf(" -> 0x%08x 0x%08x (%d) %s\n",
427 recv_name,
428 excinfo->ports_info[i].iip_port_object,
429 recv_holder_taskinfo->pid,
430 recv_holder_taskinfo->processName);
ac27e6b4
A
431 } else {
432 fprintf(stderr, "failed to find");
433 }
434
435 printf("\n");
436
437 }
887d5eed 438 JSON_OBJECT_END(json); // exception port
ac27e6b4
A
439 }
440 }
1a7e3f61 441 }
887d5eed
A
442 JSON_ARRAY_END(json); // exception ports
443 JSON_OBJECT_END(json); // thread
1a7e3f61 444 }
887d5eed
A
445
446 JSON_ARRAY_END(json); // threads
9726c137 447 printf("\n");
1a7e3f61
A
448 return kret;
449}
450
451char * get_task_name_by_pid(pid_t pid) {
452 char * retval = "Unknown";
453 for (int i = 0; i < global_taskcount; i++) {
454 if (pid == global_taskinfo[i].pid) {
455 return global_taskinfo[i].processName;
456 }
457 }
458 return retval;
459}
460
461my_per_task_info_t * get_taskinfo_by_kobject(natural_t kobj) {
462 my_per_task_info_t *retval = &NOT_FOUND_TASK_INFO;
463 for (int j = 0; j < global_taskcount; j++) {
464 if (global_taskinfo[j].task_kobject == kobj) {
465 retval = &global_taskinfo[j];
466 break;
467 }
468 }
469 return retval;
470}
471
00bf83c0 472static kern_return_t _get_taskinfo_of_receiver_by_send_right(natural_t kobject, my_per_task_info_t **out_taskinfo, mach_port_name_t *out_recv_info)
1a7e3f61 473{
1a7e3f61 474 *out_taskinfo = &NOT_FOUND_TASK_INFO;
cf37c299
A
475 struct k2n_table_node *k2nnode;
476
00bf83c0
A
477 for (unsigned int j = 0; j < global_taskcount; j++) {
478 if ((k2nnode = k2n_table_lookup(global_taskinfo[j].k2ntable, kobject))) {
479 assert(k2nnode->info_name->iin_object == kobject);
cf37c299
A
480
481 if (k2nnode->info_name->iin_type & MACH_PORT_TYPE_RECEIVE) {
1a7e3f61 482 *out_taskinfo = &global_taskinfo[j];
cf37c299
A
483 *out_recv_info = k2nnode->info_name->iin_name;
484 return KERN_SUCCESS;
1a7e3f61
A
485 }
486 }
487 }
cf37c299
A
488
489 return KERN_FAILURE;
1a7e3f61
A
490}
491
00bf83c0
A
492kern_return_t get_taskinfo_of_receiver_by_send_right(ipc_info_name_t sendright, my_per_task_info_t **out_taskinfo, mach_port_name_t *out_recv_info)
493{
494 return _get_taskinfo_of_receiver_by_send_right(sendright.iin_object, out_taskinfo, out_recv_info);
495}
ac27e6b4 496
00bf83c0
A
497kern_return_t get_taskinfo_of_receiver_by_send_right_info(ipc_info_port_t sendright_info, my_per_task_info_t **out_taskinfo, mach_port_name_t *out_recv_info)
498{
499 return _get_taskinfo_of_receiver_by_send_right(sendright_info.iip_port_object, out_taskinfo, out_recv_info);
ac27e6b4 500}