1 2 #include "inc.h" 3 4 #include <minix/com.h> 5 #include <minix/callnr.h> 6 #include <minix/endpoint.h> 7 8 static const struct calls *call_table[] = { 9 &pm_calls, 10 &vfs_calls, 11 &rs_calls, 12 &vm_calls, 13 &ipc_calls, 14 }; 15 16 /* 17 * Find a call handler for the given endpoint, call number pair. Return NULL 18 * if no call handler for this call exists. 19 */ 20 static const struct call_handler * 21 find_handler(endpoint_t endpt, int call_nr) 22 { 23 int i, index; 24 25 for (i = 0; i < COUNT(call_table); i++) { 26 if (call_table[i]->endpt != ANY && 27 call_table[i]->endpt != endpt) 28 continue; 29 30 if (call_nr < call_table[i]->base) 31 continue; 32 33 index = call_nr - call_table[i]->base; 34 35 if (index >= call_table[i]->count) 36 continue; 37 38 if (call_table[i]->map[index].outfunc == NULL) 39 continue; 40 41 return &call_table[i]->map[index]; 42 } 43 44 return NULL; 45 } 46 47 /* 48 * Print an endpoint. 49 */ 50 void 51 put_endpoint(struct trace_proc * proc, const char * name, endpoint_t endpt) 52 { 53 const char *text = NULL; 54 55 if (!valuesonly) { 56 switch (endpt) { 57 TEXT(ASYNCM); 58 TEXT(IDLE); 59 TEXT(CLOCK); 60 TEXT(SYSTEM); 61 TEXT(KERNEL); 62 TEXT(PM_PROC_NR); 63 TEXT(VFS_PROC_NR); 64 TEXT(RS_PROC_NR); 65 TEXT(MEM_PROC_NR); 66 TEXT(SCHED_PROC_NR); 67 TEXT(TTY_PROC_NR); 68 TEXT(DS_PROC_NR); 69 TEXT(VM_PROC_NR); 70 TEXT(PFS_PROC_NR); 71 TEXT(ANY); 72 TEXT(NONE); 73 TEXT(SELF); 74 } 75 } 76 77 if (text != NULL) 78 put_field(proc, name, text); 79 else 80 put_value(proc, name, "%d", endpt); 81 } 82 83 /* 84 * Print a message structure. The source field will be printed only if the 85 * PF_ALT flag is given. 86 */ 87 static void 88 put_message(struct trace_proc * proc, const char * name, int flags, 89 vir_bytes addr) 90 { 91 message m; 92 93 if (!put_open_struct(proc, name, flags, addr, &m, sizeof(m))) 94 return; 95 96 if (flags & PF_ALT) 97 put_endpoint(proc, "m_source", m.m_source); 98 99 put_value(proc, "m_type", "%x", m.m_type); 100 101 put_close_struct(proc, FALSE /*all*/); 102 } 103 104 /* 105 * Print the call's equals sign, which also implies that the parameters part of 106 * the call has been fully printed and the corresponding closing parenthesis 107 * may have to be printed, if it has not been printed already. 108 */ 109 void 110 put_equals(struct trace_proc * proc) 111 { 112 113 /* 114 * Do not allow multiple equals signs on a single line. This check is 115 * protection against badly written handlers. It does not work for the 116 * no-return type, but such calls are rare and less error prone anyway. 117 */ 118 assert((proc->call_flags & (CF_DONE | CF_NORETURN)) != CF_DONE); 119 120 /* 121 * We allow (and in fact force) handlers to call put_equals in order to 122 * indicate that the call's parameters block has ended, so we must end 123 * the block here, if we hadn't done so before. 124 */ 125 if (!(proc->call_flags & CF_DONE)) { 126 put_close(proc, ") "); 127 128 proc->call_flags |= CF_DONE; 129 } 130 131 put_align(proc); 132 put_text(proc, "= "); 133 134 format_set_sep(proc, NULL); 135 } 136 137 /* 138 * Print the primary result of a call, after the equals sign. It is always 139 * possible that this is an IPC-level or other low-level error, in which case 140 * this takes precedence, which is why this function must be called to print 141 * the result if the call failed in any way at all; it may or may not be used 142 * if the call succeeded. For regular call results, default MINIX3/POSIX 143 * semantics are used: if the return value is negative, the actual call failed 144 * with -1 and the negative return value is the call's error code. The caller 145 * may consider other cases a failure (e.g., waitpid() returning 0), but 146 * negative return values *not* signifying an error are currently not supported 147 * since they are not present in MINIX3. 148 */ 149 void 150 put_result(struct trace_proc * proc) 151 { 152 const char *errname; 153 int value; 154 155 /* This call should always be preceded by a put_equals call. */ 156 assert(proc->call_flags & CF_DONE); 157 158 /* 159 * If we failed to copy in the result register or message, print a 160 * basic error and nothing else. 161 */ 162 if (proc->call_flags & (CF_REG_ERR | CF_MSG_ERR)) { 163 put_text(proc, "<fault>"); 164 165 return; 166 } 167 168 /* 169 * If we are printing a system call rather than an IPC call, and an 170 * error occurred at the IPC level, prefix the output with "<ipc>" to 171 * indicate the IPC failure. If we are printing an IPC call, an IPC- 172 * level result is implied, so we do not print this. 173 */ 174 if (proc->call_handler != NULL && (proc->call_flags & CF_IPC_ERR)) 175 put_text(proc, "<ipc> "); 176 177 value = proc->call_result; 178 179 if (value >= 0) 180 put_fmt(proc, "%d", value); 181 else if (!valuesonly && (errname = get_error_name(-value)) != NULL) 182 put_fmt(proc, "-1 [%s]", errname); 183 else 184 put_fmt(proc, "-1 [%d]", -value); 185 186 format_set_sep(proc, " "); 187 } 188 189 /* 190 * The default enter-call (out) printer, which prints no parameters and is thus 191 * immediately done with printing parameters. 192 */ 193 int 194 default_out(struct trace_proc * __unused proc, const message * __unused m_out) 195 { 196 197 return CT_DONE; 198 } 199 200 /* 201 * The default leave-call (in) printer, which simply prints the call result, 202 * possibly preceded by an equals sign if none was printed yet. For obvious 203 * reasons, if the handler's out printer returned CT_NOTDONE, this default 204 * printer must not be used. 205 */ 206 void 207 default_in(struct trace_proc * proc, const message * __unused m_out, 208 const message * __unused m_in, int __unused failed) 209 { 210 211 if ((proc->call_flags & (CF_DONE | CF_NORETURN)) != CF_DONE) 212 put_equals(proc); 213 put_result(proc); 214 } 215 216 /* 217 * Prepare a sendrec call, by copying in the request message, determining 218 * whether it is one of the calls that the tracing engine should know about, 219 * searching for a handler for the call, and returning a name for the call. 220 */ 221 static const char * 222 sendrec_prepare(struct trace_proc * proc, endpoint_t endpt, vir_bytes addr, 223 int * trace_class) 224 { 225 const char *name; 226 int r; 227 228 r = mem_get_data(proc->pid, addr, &proc->m_out, sizeof(proc->m_out)); 229 230 if (r == 0) { 231 if (endpt == PM_PROC_NR) { 232 if (proc->m_out.m_type == PM_EXEC) 233 *trace_class = TC_EXEC; 234 else if (proc->m_out.m_type == PM_SIGRETURN) 235 *trace_class = TC_SIGRET; 236 } 237 238 proc->call_handler = find_handler(endpt, proc->m_out.m_type); 239 } else 240 proc->call_handler = NULL; 241 242 if (proc->call_handler != NULL) { 243 if (proc->call_handler->namefunc != NULL) 244 name = proc->call_handler->namefunc(&proc->m_out); 245 else 246 name = proc->call_handler->name; 247 248 assert(name != NULL); 249 } else 250 name = "ipc_sendrec"; 251 252 return name; 253 } 254 255 /* 256 * Print the outgoing (request) part of a sendrec call. If we found a call 257 * handler for the call, let the handler generate output. Otherwise, print the 258 * sendrec call at the kernel IPC level. Return the resulting call flags. 259 */ 260 static unsigned int 261 sendrec_out(struct trace_proc * proc, endpoint_t endpt, vir_bytes addr) 262 { 263 264 if (proc->call_handler != NULL) { 265 return proc->call_handler->outfunc(proc, &proc->m_out); 266 } else { 267 put_endpoint(proc, "src_dest", endpt); 268 /* 269 * We have already copied in the message, but if we used m_out 270 * and PF_LOCADDR here, a copy failure would cause "&.." to be 271 * printed rather than the actual message address. 272 */ 273 put_message(proc, "m_ptr", 0, addr); 274 275 return CT_DONE; 276 } 277 } 278 279 /* 280 * Print the incoming (reply) part of a sendrec call. Copy in the reply 281 * message, determine whether the call is considered to have failed, and let 282 * the call handler do the rest. If no call handler was found, print an 283 * IPC-level result. 284 */ 285 static void 286 sendrec_in(struct trace_proc * proc, int failed) 287 { 288 message m_in; 289 290 if (failed) { 291 /* The call failed at the IPC level. */ 292 memset(&m_in, 0, sizeof(m_in)); /* not supposed to be used */ 293 assert(proc->call_flags & CF_IPC_ERR); 294 } else if (mem_get_data(proc->pid, proc->m_addr, &m_in, 295 sizeof(m_in)) != 0) { 296 /* The reply message is somehow unavailable to us. */ 297 memset(&m_in, 0, sizeof(m_in)); /* not supposed to be used */ 298 proc->call_result = EGENERIC; /* not supposed to be used */ 299 proc->call_flags |= CF_MSG_ERR; 300 failed = PF_FAILED; 301 } else { 302 /* The result is for the actual call. */ 303 proc->call_result = m_in.m_type; 304 failed = (proc->call_result < 0) ? PF_FAILED : 0; 305 } 306 307 if (proc->call_handler != NULL) 308 proc->call_handler->infunc(proc, &proc->m_out, &m_in, failed); 309 else 310 put_result(proc); 311 } 312 313 /* 314 * Perform preparations for printing a system call. Return two things: the 315 * name to use for the call, and the trace class of the call. 316 * special treatment). 317 */ 318 static const char * 319 call_prepare(struct trace_proc * proc, reg_t reg[3], int * trace_class) 320 { 321 322 switch (proc->call_type) { 323 case SENDREC: 324 return sendrec_prepare(proc, (endpoint_t)reg[1], 325 (vir_bytes)reg[2], trace_class); 326 327 case SEND: 328 return "ipc_send"; 329 330 case SENDNB: 331 return "ipc_sendnb"; 332 333 case RECEIVE: 334 return "ipc_receive"; 335 336 case NOTIFY: 337 return "ipc_notify"; 338 339 case SENDA: 340 return "ipc_senda"; 341 342 case MINIX_KERNINFO: 343 return "minix_kerninfo"; 344 345 default: 346 /* 347 * It would be nice to include the call number here, but we 348 * must return a string that will last until the entire call is 349 * finished. Adding another buffer to the trace_proc structure 350 * is an option, but it seems overkill.. 351 */ 352 return "ipc_unknown"; 353 } 354 } 355 356 /* 357 * Print the outgoing (request) part of a system call. Return the resulting 358 * call flags. 359 */ 360 static unsigned int 361 call_out(struct trace_proc * proc, reg_t reg[3]) 362 { 363 364 switch (proc->call_type) { 365 case SENDREC: 366 proc->m_addr = (vir_bytes)reg[2]; 367 368 return sendrec_out(proc, (endpoint_t)reg[1], 369 (vir_bytes)reg[2]); 370 371 case SEND: 372 case SENDNB: 373 put_endpoint(proc, "dest", (endpoint_t)reg[1]); 374 put_message(proc, "m_ptr", 0, (vir_bytes)reg[2]); 375 376 return CT_DONE; 377 378 case RECEIVE: 379 proc->m_addr = (vir_bytes)reg[2]; 380 381 put_endpoint(proc, "src", (endpoint_t)reg[1]); 382 383 return CT_NOTDONE; 384 385 case NOTIFY: 386 put_endpoint(proc, "dest", (endpoint_t)reg[1]); 387 388 return CT_DONE; 389 390 case SENDA: 391 put_ptr(proc, "table", (vir_bytes)reg[2]); 392 put_value(proc, "count", "%zu", (size_t)reg[1]); 393 394 return CT_DONE; 395 396 case MINIX_KERNINFO: 397 default: 398 return CT_DONE; 399 } 400 } 401 402 /* 403 * Print the incoming (reply) part of a call. 404 */ 405 static void 406 call_in(struct trace_proc * proc, int failed) 407 { 408 409 switch (proc->call_type) { 410 case SENDREC: 411 sendrec_in(proc, failed); 412 413 break; 414 415 case RECEIVE: 416 /* Print the source as well. */ 417 put_message(proc, "m_ptr", failed | PF_ALT, proc->m_addr); 418 put_equals(proc); 419 put_result(proc); 420 421 break; 422 423 case MINIX_KERNINFO: 424 /* 425 * We do not have a platform-independent means to access the 426 * secondary IPC return value, so we cannot print the receive 427 * status or minix_kerninfo address. 428 */ 429 /* FALLTHROUGH */ 430 default: 431 put_result(proc); 432 433 break; 434 } 435 } 436 437 /* 438 * Determine whether to skip printing the given call, based on its name. 439 */ 440 static int 441 call_hide(const char * __unused name) 442 { 443 444 /* 445 * TODO: add support for such filtering, with an strace-like -e command 446 * line option. For now, we filter nothing, although calls may still 447 * be hidden as the result of a register retrieval error. 448 */ 449 return FALSE; 450 } 451 452 /* 453 * The given process entered a system call. Return the trace class of the 454 * call: TC_EXEC for an execve() call, TC_SIGRET for a sigreturn() call, or 455 * TC_NORMAL for a call that requires no exceptions in the trace engine. 456 */ 457 int 458 call_enter(struct trace_proc * proc, int show_stack) 459 { 460 const char *name; 461 reg_t reg[3]; 462 int trace_class, type; 463 464 /* Get the IPC-level type and parameters of the system call. */ 465 if (kernel_get_syscall(proc->pid, reg) < 0) { 466 /* 467 * If obtaining the details of the system call failed, even 468 * though we know the process is stopped on a system call, we 469 * are going to assume that the process got killed somehow. 470 * Thus, the best we can do is ignore the system call entirely, 471 * and hope that the next thing we hear about this process is 472 * its termination. At worst, we ignore a serious error.. 473 */ 474 proc->call_flags = CF_HIDE; 475 476 return FALSE; 477 } 478 479 /* 480 * Obtain the call name that is to be used for this call, and decide 481 * whether we want to print this call at all. 482 */ 483 proc->call_type = (int)reg[0]; 484 trace_class = TC_NORMAL; 485 486 name = call_prepare(proc, reg, &trace_class); 487 488 proc->call_name = name; 489 490 if (call_hide(name)) { 491 proc->call_flags = CF_HIDE; 492 493 return trace_class; 494 } 495 496 /* Only print a stack trace if we are printing the call itself. */ 497 if (show_stack) 498 kernel_put_stacktrace(proc); 499 500 /* 501 * Start a new line, start recording, and print the call name and 502 * opening parenthesis. 503 */ 504 put_newline(); 505 506 format_reset(proc); 507 508 record_start(proc); 509 510 put_text(proc, name); 511 put_open(proc, NULL, PF_NONAME, "(", ", "); 512 513 /* 514 * Print the outgoing part of the call, that is, some or all of its 515 * parameters. This call returns flags indicating how far printing 516 * got, and may be one of the following combinations: 517 * - CT_NOTDONE (0) if printing parameters is not yet complete; after 518 * the call split, the in handler must print the rest itself; 519 * - CT_DONE (CF_DONE) if printing parameters is complete, and we 520 * should now print the closing parenthesis and equals sign; 521 * - CT_NORETURN (CF_DONE|CF_NORETURN) if printing parameters is 522 * complete, but we should not print the equals sign, because the 523 * call is expected not to return (the no-return call type). 524 */ 525 type = call_out(proc, reg); 526 assert(type == CT_NOTDONE || type == CT_DONE || type == CT_NORETURN); 527 528 /* 529 * Print whatever the handler told us to print for now. 530 */ 531 if (type & CF_DONE) { 532 if (type & CF_NORETURN) { 533 put_close(proc, ")"); 534 535 put_space(proc); 536 537 proc->call_flags |= type; 538 } else { 539 /* 540 * The equals sign is printed implicitly for the 541 * CT_DONE type only. For CT_NORETURN and CT_NOTDONE, 542 * the "in" handler has to do it explicitly. 543 */ 544 put_equals(proc); 545 } 546 } else { 547 /* 548 * If at least one parameter was printed, print the separator 549 * now. We know that another parameter will follow (otherwise 550 * the caller would have returned CT_DONE), and this way the 551 * output looks better. 552 */ 553 format_push_sep(proc); 554 } 555 556 /* 557 * We are now at the call split; further printing will be done once the 558 * call returns, through call_leave. Stop recording; if the call gets 559 * suspended and later resumed, we should replay everything up to here. 560 */ 561 #if DEBUG 562 put_text(proc, "|"); /* warning, this may push a space */ 563 #endif 564 565 record_stop(proc); 566 567 output_flush(); 568 569 return trace_class; 570 } 571 572 /* 573 * The given process left a system call, or if skip is set, the leave phase of 574 * the current system call should be ended. 575 */ 576 void 577 call_leave(struct trace_proc * proc, int skip) 578 { 579 reg_t retreg; 580 int hide, failed; 581 582 /* If the call is skipped, it must be a no-return type call. */ 583 assert(!skip || (proc->call_flags & (CF_NORETURN | CF_HIDE))); 584 585 /* 586 * Start by replaying the current call, if necessary. If the call was 587 * suspended and we are about to print the "in" part, this is obviously 588 * needed. If the call is hidden, replaying will be a no-op, since 589 * nothing was recorded for this call. The special case is a skipped 590 * call (which, as established above, must be a no-return call, e.g. 591 * exec), for which replaying has the effect that if the call was 592 * previously suspended, it will now be replayed, without suspension: 593 * 594 * 2| execve("./test", ["./test"], [..(12)]) <..> 595 * 3| sigsuspend([]) = <..> 596 * [A] 2| execve("./test", ["./test"], [..(12)]) 597 * 2| --- 598 * 2| Tracing test (pid 2) 599 * 600 * The [A] line is the result of replaying the skipped call. 601 */ 602 call_replay(proc); 603 604 hide = (proc->call_flags & CF_HIDE); 605 606 if (!hide && !skip) { 607 /* Get the IPC-level result of the call. */ 608 if (kernel_get_retreg(proc->pid, &retreg) < 0) { 609 /* This should never happen. Deal with it anyway. */ 610 proc->call_flags |= CF_REG_ERR; 611 failed = PF_FAILED; 612 } else if ((proc->call_result = (int)retreg) < 0) { 613 proc->call_flags |= CF_IPC_ERR; 614 failed = PF_FAILED; 615 } else 616 failed = 0; 617 618 /* 619 * Print the incoming part of the call, that is, possibly some 620 * or all of its parameters and the call's closing parenthesis 621 * (if CT_NOTDONE), and the equals sign (if not CT_DONE), then 622 * the call result. 623 */ 624 call_in(proc, failed); 625 } 626 627 if (!hide) { 628 /* 629 * The call is complete now, so clear the recording. This also 630 * implies that no suspension marker will be printed anymore. 631 */ 632 record_clear(proc); 633 634 put_newline(); 635 } 636 637 /* 638 * For calls not of the no-return type, an equals sign must have been 639 * printed by now. This is protection against badly written handlers. 640 */ 641 assert(proc->call_flags & CF_DONE); 642 643 proc->call_name = NULL; 644 proc->call_flags = 0; 645 } 646 647 /* 648 * Replay the recorded text, if any, for the enter phase of the given process. 649 * If there is no recorded text, start a new line anyway. 650 */ 651 void 652 call_replay(struct trace_proc * proc) 653 { 654 655 /* 656 * We get TRUE if the recorded call should be replayed, but the 657 * recorded text for the call did not fit in the recording buffer. 658 * In that case, we have to come up with a replacement text for the 659 * call up to the call split. 660 */ 661 if (record_replay(proc) == TRUE) { 662 /* 663 * We basically place a "<..>" suspension marker in the 664 * parameters part of the call, and use its call name and flags 665 * for the rest. There is a trailing space in all cases. 666 */ 667 put_fmt(proc, "%s(<..>%s", proc->call_name, 668 !(proc->call_flags & CF_DONE) ? "," : 669 ((proc->call_flags & CF_NORETURN) ? ")" : ") =")); 670 put_space(proc); 671 } 672 } 673 674 /* 675 * Return the human-readable name of the call currently being made by the given 676 * process. The process is guaranteed to be in a call, although the call may 677 * be hidden. Under no circumstances may this function return a NULL pointer. 678 */ 679 const char * 680 call_name(struct trace_proc * proc) 681 { 682 683 assert(proc->call_name != NULL); 684 685 return proc->call_name; 686 } 687