1 /* 2 * Copyright 2005-2006, Ingo Weinhold, bonefish@users.sf.net. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <signal.h> 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <debugger.h> 12 #include <kernel.h> 13 #include <KernelExport.h> 14 #include <kscheduler.h> 15 #include <ksignal.h> 16 #include <ksyscalls.h> 17 #include <sem.h> 18 #include <team.h> 19 #include <thread.h> 20 #include <thread_types.h> 21 #include <user_debugger.h> 22 #include <vm.h> 23 #include <vm_types.h> 24 #include <arch/user_debugger.h> 25 26 #include <util/AutoLock.h> 27 28 //#define TRACE_USER_DEBUGGER 29 #ifdef TRACE_USER_DEBUGGER 30 # define TRACE(x) dprintf x 31 #else 32 # define TRACE(x) ; 33 #endif 34 35 36 static port_id sDefaultDebuggerPort = -1; 37 // accessed atomically 38 39 40 static status_t ensure_debugger_installed(team_id teamID, port_id *port = NULL); 41 static void get_team_debug_info(team_debug_info &teamDebugInfo); 42 43 44 static ssize_t 45 kill_interruptable_read_port(port_id port, int32 *code, void *buffer, 46 size_t bufferSize) 47 { 48 return read_port_etc(port, code, buffer, bufferSize, 49 B_KILL_CAN_INTERRUPT, 0); 50 } 51 52 53 static status_t 54 kill_interruptable_write_port(port_id port, int32 code, const void *buffer, 55 size_t bufferSize) 56 { 57 return write_port_etc(port, code, buffer, bufferSize, 58 B_KILL_CAN_INTERRUPT, 0); 59 } 60 61 62 static status_t 63 debugger_write(port_id port, int32 code, const void *buffer, size_t bufferSize, 64 bool dontWait) 65 { 66 TRACE(("debugger_write(): thread: %ld, team %ld, port: %ld, code: %lx, message: %p, " 67 "size: %lu, dontWait: %d\n", thread_get_current_thread()->id, 68 thread_get_current_thread()->team->id, port, code, buffer, bufferSize, 69 dontWait)); 70 71 status_t error = B_OK; 72 73 // get the team debug info 74 team_debug_info teamDebugInfo; 75 get_team_debug_info(teamDebugInfo); 76 sem_id writeLock = teamDebugInfo.debugger_write_lock; 77 78 // get the write lock 79 TRACE(("debugger_write(): acquiring write lock...\n")); 80 error = acquire_sem_etc(writeLock, 1, 81 dontWait ? (uint32)B_RELATIVE_TIMEOUT : (uint32)B_KILL_CAN_INTERRUPT, 0); 82 if (error != B_OK) { 83 TRACE(("debugger_write() done1: %lx\n", error)); 84 return error; 85 } 86 87 // re-get the team debug info 88 get_team_debug_info(teamDebugInfo); 89 90 if (teamDebugInfo.debugger_port != port 91 || (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_HANDOVER)) { 92 // The debugger has changed in the meantime or we are about to be 93 // handed over to a new debugger. In either case we don't send the 94 // message. 95 TRACE(("debugger_write(): %s\n", 96 (teamDebugInfo.debugger_port != port ? "debugger port changed" 97 : "handover flag set"))); 98 } else { 99 TRACE(("debugger_write(): writing to port...\n")); 100 101 error = write_port_etc(port, code, buffer, bufferSize, 102 dontWait ? (uint32)B_RELATIVE_TIMEOUT : (uint32)B_KILL_CAN_INTERRUPT, 0); 103 } 104 105 // release the write lock 106 release_sem(writeLock); 107 108 TRACE(("debugger_write() done: %lx\n", error)); 109 110 return error; 111 } 112 113 114 /*! Updates the thread::flags field according to what user debugger flags are 115 set for the thread. 116 Interrupts must be disabled and the thread lock must be held. 117 */ 118 static void 119 update_thread_user_debug_flag(struct thread* thread) 120 { 121 if (atomic_get(&thread->debug_info.flags) 122 & (B_THREAD_DEBUG_STOP | B_THREAD_DEBUG_SINGLE_STEP)) { 123 atomic_or(&thread->flags, THREAD_FLAGS_DEBUG_THREAD); 124 } else 125 atomic_and(&thread->flags, ~THREAD_FLAGS_DEBUG_THREAD); 126 } 127 128 129 /*! Updates the thread::flags THREAD_FLAGS_BREAKPOINTS_DEFINED bit of the 130 current thread. 131 Interrupts must be disabled and the team lock must be held. 132 */ 133 static void 134 update_thread_breakpoints_flag() 135 { 136 struct thread* thread = thread_get_current_thread(); 137 struct team* team = thread->team; 138 139 if (arch_has_breakpoints(&team->debug_info.arch_info)) 140 atomic_or(&thread->flags, THREAD_FLAGS_BREAKPOINTS_DEFINED); 141 else 142 atomic_and(&thread->flags, ~THREAD_FLAGS_BREAKPOINTS_DEFINED); 143 } 144 145 146 /*! Updates the thread::flags THREAD_FLAGS_BREAKPOINTS_DEFINED bit of all 147 threads of the current team. 148 Interrupts must be disabled and the team lock must be held. 149 */ 150 static void 151 update_threads_breakpoints_flag() 152 { 153 InterruptsSpinLocker _(team_spinlock); 154 155 struct team* team = thread_get_current_thread()->team; 156 struct thread* thread = team->thread_list; 157 158 if (arch_has_breakpoints(&team->debug_info.arch_info)) { 159 for (; thread != NULL; thread = thread->team_next) 160 atomic_or(&thread->flags, THREAD_FLAGS_BREAKPOINTS_DEFINED); 161 } else { 162 for (; thread != NULL; thread = thread->team_next) 163 atomic_and(&thread->flags, ~THREAD_FLAGS_BREAKPOINTS_DEFINED); 164 } 165 } 166 167 168 /*! Updates the thread::flags B_TEAM_DEBUG_DEBUGGER_INSTALLED bit of the 169 current thread. 170 Interrupts must be disabled and the team lock must be held. 171 */ 172 static void 173 update_thread_debugger_installed_flag() 174 { 175 struct thread* thread = thread_get_current_thread(); 176 struct team* team = thread->team; 177 178 if (atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_DEBUGGER_INSTALLED) 179 atomic_or(&thread->flags, THREAD_FLAGS_DEBUGGER_INSTALLED); 180 else 181 atomic_and(&thread->flags, ~THREAD_FLAGS_DEBUGGER_INSTALLED); 182 } 183 184 185 /*! Updates the thread::flags THREAD_FLAGS_DEBUGGER_INSTALLED bit of all 186 threads of the given team. 187 Interrupts must be disabled and the team lock must be held. 188 */ 189 static void 190 update_threads_debugger_installed_flag(struct team* team) 191 { 192 struct thread* thread = team->thread_list; 193 194 if (atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 195 for (; thread != NULL; thread = thread->team_next) 196 atomic_or(&thread->flags, THREAD_FLAGS_DEBUGGER_INSTALLED); 197 } else { 198 for (; thread != NULL; thread = thread->team_next) 199 atomic_and(&thread->flags, ~THREAD_FLAGS_DEBUGGER_INSTALLED); 200 } 201 } 202 203 204 /** 205 * For the first initialization the function must be called with \a initLock 206 * set to \c true. If it would be possible that another thread accesses the 207 * structure at the same time, `lock' must be held when calling the function. 208 */ 209 void 210 clear_team_debug_info(struct team_debug_info *info, bool initLock) 211 { 212 if (info) { 213 arch_clear_team_debug_info(&info->arch_info); 214 atomic_set(&info->flags, B_TEAM_DEBUG_DEFAULT_FLAGS); 215 info->debugger_team = -1; 216 info->debugger_port = -1; 217 info->nub_thread = -1; 218 info->nub_port = -1; 219 info->debugger_write_lock = -1; 220 221 if (initLock) 222 info->lock = 0; 223 } 224 } 225 226 /** 227 * `lock' must not be held nor may interrupts be disabled. 228 * \a info must not be a member of a team struct (or the team struct must no 229 * longer be accessible, i.e. the team should already be removed). 230 * 231 * In case the team is still accessible, the procedure is: 232 * 1. get `lock' 233 * 2. copy the team debug info on stack 234 * 3. call clear_team_debug_info() on the team debug info 235 * 4. release `lock' 236 * 5. call destroy_team_debug_info() on the copied team debug info 237 */ 238 void 239 destroy_team_debug_info(struct team_debug_info *info) 240 { 241 if (info) { 242 arch_destroy_team_debug_info(&info->arch_info); 243 244 // delete the debugger port write lock 245 if (info->debugger_write_lock >= 0) { 246 delete_sem(info->debugger_write_lock); 247 info->debugger_write_lock = -1; 248 } 249 250 // delete the nub port 251 if (info->nub_port >= 0) { 252 set_port_owner(info->nub_port, B_CURRENT_TEAM); 253 delete_port(info->nub_port); 254 info->nub_port = -1; 255 } 256 257 // wait for the nub thread 258 if (info->nub_thread >= 0) { 259 if (info->nub_thread != thread_get_current_thread()->id) { 260 int32 result; 261 wait_for_thread(info->nub_thread, &result); 262 } 263 264 info->nub_thread = -1; 265 } 266 267 atomic_set(&info->flags, 0); 268 info->debugger_team = -1; 269 info->debugger_port = -1; 270 } 271 } 272 273 274 void 275 clear_thread_debug_info(struct thread_debug_info *info, bool dying) 276 { 277 if (info) { 278 arch_clear_thread_debug_info(&info->arch_info); 279 atomic_set(&info->flags, 280 B_THREAD_DEBUG_DEFAULT_FLAGS | (dying ? B_THREAD_DEBUG_DYING : 0)); 281 info->debug_port = -1; 282 info->ignore_signals = 0; 283 info->ignore_signals_once = 0; 284 } 285 } 286 287 288 void 289 destroy_thread_debug_info(struct thread_debug_info *info) 290 { 291 if (info) { 292 arch_destroy_thread_debug_info(&info->arch_info); 293 294 if (info->debug_port >= 0) { 295 delete_port(info->debug_port); 296 info->debug_port = -1; 297 } 298 299 info->ignore_signals = 0; 300 info->ignore_signals_once = 0; 301 302 atomic_set(&info->flags, 0); 303 } 304 } 305 306 307 void 308 user_debug_prepare_for_exec() 309 { 310 struct thread *thread = thread_get_current_thread(); 311 struct team *team = thread->team; 312 313 // If a debugger is installed for the team and the thread debug stuff 314 // initialized, changed the ownership of the debug port for the thread 315 // to the kernel team, since exec_team() deletes all ports owned by this 316 // team. We change the ownership back later. 317 if (atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 318 // get the port 319 port_id debugPort = -1; 320 321 cpu_status state = disable_interrupts(); 322 GRAB_THREAD_LOCK(); 323 324 if (thread->debug_info.flags & B_THREAD_DEBUG_INITIALIZED) 325 debugPort = thread->debug_info.debug_port; 326 327 RELEASE_THREAD_LOCK(); 328 restore_interrupts(state); 329 330 // set the new port ownership 331 if (debugPort >= 0) 332 set_port_owner(debugPort, team_get_kernel_team_id()); 333 } 334 } 335 336 337 void 338 user_debug_finish_after_exec() 339 { 340 struct thread *thread = thread_get_current_thread(); 341 struct team *team = thread->team; 342 343 // If a debugger is installed for the team and the thread debug stuff 344 // initialized for this thread, change the ownership of its debug port 345 // back to this team. 346 if (atomic_get(&team->debug_info.flags) & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 347 // get the port 348 port_id debugPort = -1; 349 350 cpu_status state = disable_interrupts(); 351 GRAB_THREAD_LOCK(); 352 353 if (thread->debug_info.flags & B_THREAD_DEBUG_INITIALIZED) 354 debugPort = thread->debug_info.debug_port; 355 356 RELEASE_THREAD_LOCK(); 357 restore_interrupts(state); 358 359 // set the new port ownership 360 if (debugPort >= 0) 361 set_port_owner(debugPort, team->id); 362 } 363 } 364 365 366 void 367 init_user_debug() 368 { 369 #ifdef ARCH_INIT_USER_DEBUG 370 ARCH_INIT_USER_DEBUG(); 371 #endif 372 } 373 374 375 static void 376 get_team_debug_info(team_debug_info &teamDebugInfo) 377 { 378 struct thread *thread = thread_get_current_thread(); 379 380 cpu_status state = disable_interrupts(); 381 GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 382 383 memcpy(&teamDebugInfo, &thread->team->debug_info, sizeof(team_debug_info)); 384 385 RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 386 restore_interrupts(state); 387 } 388 389 390 static status_t 391 thread_hit_debug_event_internal(debug_debugger_message event, 392 const void *message, int32 size, bool requireDebugger, bool &restart) 393 { 394 restart = false; 395 struct thread *thread = thread_get_current_thread(); 396 397 TRACE(("thread_hit_debug_event(): thread: %ld, event: %lu, message: %p, " 398 "size: %ld\n", thread->id, (uint32)event, message, size)); 399 400 // check, if there's a debug port already 401 bool setPort = !(atomic_get(&thread->debug_info.flags) 402 & B_THREAD_DEBUG_INITIALIZED); 403 404 // create a port, if there is none yet 405 port_id port = -1; 406 if (setPort) { 407 char nameBuffer[128]; 408 snprintf(nameBuffer, sizeof(nameBuffer), "nub to thread %ld", 409 thread->id); 410 411 port = create_port(1, nameBuffer); 412 if (port < 0) { 413 dprintf("thread_hit_debug_event(): Failed to create debug port: " 414 "%s\n", strerror(port)); 415 return port; 416 } 417 418 setPort = true; 419 } 420 421 // check the debug info structures once more: get the debugger port, set 422 // the thread's debug port, and update the thread's debug flags 423 port_id deletePort = port; 424 port_id debuggerPort = -1; 425 port_id nubPort = -1; 426 status_t error = B_OK; 427 cpu_status state = disable_interrupts(); 428 GRAB_THREAD_LOCK(); 429 GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 430 431 uint32 threadFlags = thread->debug_info.flags; 432 threadFlags &= ~B_THREAD_DEBUG_STOP; 433 bool debuggerInstalled 434 = (thread->team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED); 435 if (thread->id == thread->team->debug_info.nub_thread) { 436 // Ugh, we're the nub thread. We shouldn't be here. 437 TRACE(("thread_hit_debug_event(): Misdirected nub thread: %ld\n", 438 thread->id)); 439 440 error = B_ERROR; 441 442 } else if (debuggerInstalled || !requireDebugger) { 443 if (debuggerInstalled) { 444 debuggerPort = thread->team->debug_info.debugger_port; 445 nubPort = thread->team->debug_info.nub_port; 446 } 447 448 if (setPort) { 449 if (threadFlags & B_THREAD_DEBUG_INITIALIZED) { 450 // someone created a port for us (the port we've created will 451 // be deleted below) 452 port = thread->debug_info.debug_port; 453 } else { 454 thread->debug_info.debug_port = port; 455 deletePort = -1; // keep the port 456 threadFlags |= B_THREAD_DEBUG_INITIALIZED; 457 } 458 } else { 459 if (threadFlags & B_THREAD_DEBUG_INITIALIZED) { 460 port = thread->debug_info.debug_port; 461 } else { 462 // someone deleted our port 463 error = B_ERROR; 464 } 465 } 466 } else 467 error = B_ERROR; 468 469 // update the flags 470 if (error == B_OK) 471 threadFlags |= B_THREAD_DEBUG_STOPPED; 472 atomic_set(&thread->debug_info.flags, threadFlags); 473 474 update_thread_user_debug_flag(thread); 475 476 RELEASE_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info); 477 RELEASE_THREAD_LOCK(); 478 restore_interrupts(state); 479 480 // delete the superfluous port 481 if (deletePort >= 0) 482 delete_port(deletePort); 483 484 if (error != B_OK) { 485 TRACE(("thread_hit_debug_event() error: thread: %ld, error: %lx\n", 486 thread->id, error)); 487 return error; 488 } 489 490 // send a message to the debugger port 491 if (debuggerInstalled) { 492 // update the message's origin info first 493 debug_origin *origin = (debug_origin *)message; 494 origin->thread = thread->id; 495 origin->team = thread->team->id; 496 origin->nub_port = nubPort; 497 498 TRACE(("thread_hit_debug_event(): thread: %ld, sending message to " 499 "debugger port %ld\n", thread->id, debuggerPort)); 500 501 error = debugger_write(debuggerPort, event, message, size, false); 502 } 503 504 status_t result = B_THREAD_DEBUG_HANDLE_EVENT; 505 bool singleStep = false; 506 507 if (error == B_OK) { 508 bool done = false; 509 while (!done) { 510 // read a command from the debug port 511 int32 command; 512 debugged_thread_message_data commandMessage; 513 ssize_t commandMessageSize = kill_interruptable_read_port(port, 514 &command, &commandMessage, sizeof(commandMessage)); 515 if (commandMessageSize < 0) { 516 error = commandMessageSize; 517 TRACE(("thread_hit_debug_event(): thread: %ld, failed " 518 "to receive message from port %ld: %lx\n", 519 thread->id, port, error)); 520 break; 521 } 522 523 switch (command) { 524 case B_DEBUGGED_THREAD_MESSAGE_CONTINUE: 525 TRACE(("thread_hit_debug_event(): thread: %ld: " 526 "B_DEBUGGED_THREAD_MESSAGE_CONTINUE\n", 527 thread->id)); 528 result = commandMessage.continue_thread.handle_event; 529 530 singleStep = commandMessage.continue_thread.single_step; 531 done = true; 532 break; 533 534 case B_DEBUGGED_THREAD_SET_CPU_STATE: 535 { 536 TRACE(("thread_hit_debug_event(): thread: %ld: " 537 "B_DEBUGGED_THREAD_SET_CPU_STATE\n", 538 thread->id)); 539 arch_set_debug_cpu_state( 540 &commandMessage.set_cpu_state.cpu_state); 541 542 break; 543 } 544 545 case B_DEBUGGED_THREAD_GET_CPU_STATE: 546 { 547 port_id replyPort = commandMessage.get_cpu_state.reply_port; 548 549 // prepare the message 550 debug_nub_get_cpu_state_reply replyMessage; 551 replyMessage.error = B_OK; 552 replyMessage.message = event; 553 arch_get_debug_cpu_state(&replyMessage.cpu_state); 554 555 // send it 556 error = kill_interruptable_write_port(replyPort, event, 557 &replyMessage, sizeof(replyMessage)); 558 559 break; 560 } 561 562 case B_DEBUGGED_THREAD_DEBUGGER_CHANGED: 563 { 564 // Check, if the debugger really changed, i.e. is different 565 // than the one we know. 566 team_debug_info teamDebugInfo; 567 get_team_debug_info(teamDebugInfo); 568 569 if (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 570 if (!debuggerInstalled 571 || teamDebugInfo.debugger_port != debuggerPort) { 572 // debugger was installed or has changed: restart 573 // this function 574 restart = true; 575 done = true; 576 } 577 } else { 578 if (debuggerInstalled) { 579 // debugger is gone: continue the thread normally 580 done = true; 581 } 582 } 583 584 break; 585 } 586 } 587 } 588 } else { 589 TRACE(("thread_hit_debug_event(): thread: %ld, failed to send " 590 "message to debugger port %ld: %lx\n", thread->id, 591 debuggerPort, error)); 592 } 593 594 // update the thread debug info 595 bool destroyThreadInfo = false; 596 thread_debug_info threadDebugInfo; 597 598 state = disable_interrupts(); 599 GRAB_THREAD_LOCK(); 600 601 // check, if the team is still being debugged 602 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 603 if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 604 // update the single-step flag 605 if (singleStep) { 606 atomic_or(&thread->debug_info.flags, 607 B_THREAD_DEBUG_SINGLE_STEP); 608 } else { 609 atomic_and(&thread->debug_info.flags, 610 ~B_THREAD_DEBUG_SINGLE_STEP); 611 } 612 613 // unset the "stopped" state 614 atomic_and(&thread->debug_info.flags, ~B_THREAD_DEBUG_STOPPED); 615 616 update_thread_user_debug_flag(thread); 617 618 } else { 619 // the debugger is gone: cleanup our info completely 620 threadDebugInfo = thread->debug_info; 621 clear_thread_debug_info(&thread->debug_info, false); 622 destroyThreadInfo = true; 623 } 624 625 RELEASE_THREAD_LOCK(); 626 restore_interrupts(state); 627 628 // enable/disable single stepping 629 arch_update_thread_single_step(); 630 631 if (destroyThreadInfo) 632 destroy_thread_debug_info(&threadDebugInfo); 633 634 return (error == B_OK ? result : error); 635 } 636 637 638 static status_t 639 thread_hit_debug_event(debug_debugger_message event, const void *message, 640 int32 size, bool requireDebugger) 641 { 642 status_t result; 643 bool restart; 644 do { 645 restart = false; 646 result = thread_hit_debug_event_internal(event, message, size, 647 requireDebugger, restart); 648 } while (result >= 0 && restart); 649 650 return result; 651 } 652 653 654 void 655 user_debug_pre_syscall(uint32 syscall, void *args) 656 { 657 // check whether a debugger is installed 658 struct thread *thread = thread_get_current_thread(); 659 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 660 if (!(teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED)) 661 return; 662 663 // check whether pre-syscall tracing is enabled for team or thread 664 int32 threadDebugFlags = atomic_get(&thread->debug_info.flags); 665 if (!(teamDebugFlags & B_TEAM_DEBUG_PRE_SYSCALL) 666 && !(threadDebugFlags & B_THREAD_DEBUG_PRE_SYSCALL)) { 667 return; 668 } 669 670 // prepare the message 671 debug_pre_syscall message; 672 message.syscall = syscall; 673 674 // copy the syscall args 675 if (syscall < (uint32)kSyscallCount) { 676 if (kSyscallInfos[syscall].parameter_size > 0) 677 memcpy(message.args, args, kSyscallInfos[syscall].parameter_size); 678 } 679 680 thread_hit_debug_event(B_DEBUGGER_MESSAGE_PRE_SYSCALL, &message, 681 sizeof(message), true); 682 } 683 684 685 void 686 user_debug_post_syscall(uint32 syscall, void *args, uint64 returnValue, 687 bigtime_t startTime) 688 { 689 // check whether a debugger is installed 690 struct thread *thread = thread_get_current_thread(); 691 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 692 if (!(teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED)) 693 return; 694 695 // check whether post-syscall tracing is enabled for team or thread 696 int32 threadDebugFlags = atomic_get(&thread->debug_info.flags); 697 if (!(teamDebugFlags & B_TEAM_DEBUG_POST_SYSCALL) 698 && !(threadDebugFlags & B_THREAD_DEBUG_POST_SYSCALL)) { 699 return; 700 } 701 702 // prepare the message 703 debug_post_syscall message; 704 message.start_time = startTime; 705 message.end_time = system_time(); 706 message.return_value = returnValue; 707 message.syscall = syscall; 708 709 // copy the syscall args 710 if (syscall < (uint32)kSyscallCount) { 711 if (kSyscallInfos[syscall].parameter_size > 0) 712 memcpy(message.args, args, kSyscallInfos[syscall].parameter_size); 713 } 714 715 thread_hit_debug_event(B_DEBUGGER_MESSAGE_POST_SYSCALL, &message, 716 sizeof(message), true); 717 } 718 719 720 /** \brief To be called when an unhandled processor exception (error/fault) 721 * occurred. 722 * \param exception The debug_why_stopped value identifying the kind of fault. 723 * \param singal The signal corresponding to the exception. 724 * \return \c true, if the caller shall continue normally, i.e. usually send 725 * a deadly signal. \c false, if the debugger insists to continue the 726 * program (e.g. because it has solved the removed the cause of the 727 * problem). 728 */ 729 bool 730 user_debug_exception_occurred(debug_exception_type exception, int signal) 731 { 732 // First check whether there's a signal handler installed for the signal. 733 // If so, we don't want to install a debugger for the team. We always send 734 // the signal instead. An already installed debugger will be notified, if 735 // it has requested notifications of signal. 736 struct sigaction signalAction; 737 if (sigaction(signal, NULL, &signalAction) == B_OK 738 && signalAction.sa_handler != SIG_DFL) { 739 return true; 740 } 741 742 // ensure that a debugger is installed for this team 743 struct thread *thread = thread_get_current_thread(); 744 port_id nubPort; 745 status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort); 746 if (error != B_OK) { 747 dprintf("user_debug_exception_occurred(): Failed to install debugger: " 748 "thread: %ld: %s\n", thread->id, strerror(error)); 749 return true; 750 } 751 752 // prepare the message 753 debug_exception_occurred message; 754 message.exception = exception; 755 message.signal = signal; 756 757 status_t result = thread_hit_debug_event( 758 B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED, &message, sizeof(message), true); 759 return (result != B_THREAD_DEBUG_IGNORE_EVENT); 760 } 761 762 763 bool 764 user_debug_handle_signal(int signal, struct sigaction *handler, bool deadly) 765 { 766 // check, if a debugger is installed and is interested in signals 767 struct thread *thread = thread_get_current_thread(); 768 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 769 if (~teamDebugFlags 770 & (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_SIGNALS)) { 771 return true; 772 } 773 774 // prepare the message 775 debug_signal_received message; 776 message.signal = signal; 777 message.handler = *handler; 778 message.deadly = deadly; 779 780 status_t result = thread_hit_debug_event(B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED, 781 &message, sizeof(message), true); 782 return (result != B_THREAD_DEBUG_IGNORE_EVENT); 783 } 784 785 786 void 787 user_debug_stop_thread() 788 { 789 // ensure that a debugger is installed for this team 790 struct thread *thread = thread_get_current_thread(); 791 port_id nubPort; 792 status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort); 793 if (error != B_OK) { 794 dprintf("user_debug_stop_thread(): Failed to install debugger: " 795 "thread: %ld: %s\n", thread->id, strerror(error)); 796 return; 797 } 798 799 // prepare the message 800 debug_thread_debugged message; 801 802 thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, &message, 803 sizeof(message), true); 804 } 805 806 807 void 808 user_debug_team_created(team_id teamID) 809 { 810 // check, if a debugger is installed and is interested in team creation 811 // events 812 struct thread *thread = thread_get_current_thread(); 813 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 814 if (~teamDebugFlags 815 & (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_TEAM_CREATION)) { 816 return; 817 } 818 819 // prepare the message 820 debug_team_created message; 821 message.new_team = teamID; 822 823 thread_hit_debug_event(B_DEBUGGER_MESSAGE_TEAM_CREATED, &message, 824 sizeof(message), true); 825 } 826 827 828 void 829 user_debug_team_deleted(team_id teamID, port_id debuggerPort) 830 { 831 if (debuggerPort >= 0) { 832 TRACE(("user_debug_team_deleted(team: %ld, debugger port: %ld)\n", 833 teamID, debuggerPort)); 834 835 debug_team_deleted message; 836 message.origin.thread = -1; 837 message.origin.team = teamID; 838 message.origin.nub_port = -1; 839 write_port_etc(debuggerPort, B_DEBUGGER_MESSAGE_TEAM_DELETED, &message, 840 sizeof(message), B_RELATIVE_TIMEOUT, 0); 841 // TODO: Would it be OK to wait here? 842 } 843 } 844 845 846 void 847 user_debug_update_new_thread_flags(thread_id threadID) 848 { 849 // Update thread::flags of the thread. 850 851 InterruptsLocker interruptsLocker; 852 853 SpinLocker threadLocker(thread_spinlock); 854 855 struct thread *thread = thread_get_thread_struct_locked(threadID); 856 if (!thread) 857 return; 858 859 update_thread_user_debug_flag(thread); 860 861 threadLocker.Unlock(); 862 863 SpinLocker teamLocker(team_spinlock); 864 update_thread_breakpoints_flag(); 865 update_thread_debugger_installed_flag(); 866 } 867 868 869 void 870 user_debug_thread_created(thread_id threadID) 871 { 872 // check, if a debugger is installed and is interested in thread events 873 struct thread *thread = thread_get_current_thread(); 874 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 875 if (~teamDebugFlags 876 & (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_THREADS)) { 877 return; 878 } 879 880 // prepare the message 881 debug_thread_created message; 882 message.new_thread = threadID; 883 884 thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_CREATED, &message, 885 sizeof(message), true); 886 } 887 888 889 void 890 user_debug_thread_deleted(team_id teamID, thread_id threadID) 891 { 892 // get the team debug flags and debugger port 893 cpu_status state = disable_interrupts(); 894 GRAB_TEAM_LOCK(); 895 896 struct team *team = team_get_team_struct_locked(teamID); 897 898 int32 teamDebugFlags = 0; 899 port_id debuggerPort = -1; 900 if (team) { 901 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 902 903 teamDebugFlags = atomic_get(&team->debug_info.flags); 904 debuggerPort = team->debug_info.debugger_port; 905 906 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 907 } 908 909 RELEASE_TEAM_LOCK(); 910 restore_interrupts(state); 911 912 // check, if a debugger is installed and is interested in thread events 913 if (~teamDebugFlags 914 & (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_THREADS)) { 915 return; 916 } 917 918 // notify the debugger 919 if (debuggerPort >= 0) { 920 debug_thread_deleted message; 921 message.origin.thread = threadID; 922 message.origin.team = teamID; 923 message.origin.nub_port = -1; 924 debugger_write(debuggerPort, B_DEBUGGER_MESSAGE_THREAD_DELETED, 925 &message, sizeof(message), true); 926 // TODO: Would it be OK to wait here? 927 } 928 } 929 930 931 void 932 user_debug_image_created(const image_info *imageInfo) 933 { 934 // check, if a debugger is installed and is interested in image events 935 struct thread *thread = thread_get_current_thread(); 936 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 937 if (~teamDebugFlags 938 & (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_IMAGES)) { 939 return; 940 } 941 942 // prepare the message 943 debug_image_created message; 944 memcpy(&message.info, imageInfo, sizeof(image_info)); 945 946 thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message, 947 sizeof(message), true); 948 } 949 950 951 void 952 user_debug_image_deleted(const image_info *imageInfo) 953 { 954 // check, if a debugger is installed and is interested in image events 955 struct thread *thread = thread_get_current_thread(); 956 int32 teamDebugFlags = atomic_get(&thread->team->debug_info.flags); 957 if (~teamDebugFlags 958 & (B_TEAM_DEBUG_DEBUGGER_INSTALLED | B_TEAM_DEBUG_IMAGES)) { 959 return; 960 } 961 962 // prepare the message 963 debug_image_deleted message; 964 memcpy(&message.info, imageInfo, sizeof(image_info)); 965 966 thread_hit_debug_event(B_DEBUGGER_MESSAGE_IMAGE_CREATED, &message, 967 sizeof(message), true); 968 } 969 970 971 void 972 user_debug_breakpoint_hit(bool software) 973 { 974 // ensure that a debugger is installed for this team 975 struct thread *thread = thread_get_current_thread(); 976 port_id nubPort; 977 status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort); 978 if (error != B_OK) { 979 dprintf("user_debug_breakpoint_hit(): Failed to install debugger: " 980 "thread: %ld: %s\n", thread->id, strerror(error)); 981 return; 982 } 983 984 // prepare the message 985 debug_breakpoint_hit message; 986 message.software = software; 987 arch_get_debug_cpu_state(&message.cpu_state); 988 989 thread_hit_debug_event(B_DEBUGGER_MESSAGE_BREAKPOINT_HIT, &message, 990 sizeof(message), true); 991 } 992 993 994 void 995 user_debug_watchpoint_hit() 996 { 997 // ensure that a debugger is installed for this team 998 struct thread *thread = thread_get_current_thread(); 999 port_id nubPort; 1000 status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort); 1001 if (error != B_OK) { 1002 dprintf("user_debug_watchpoint_hit(): Failed to install debugger: " 1003 "thread: %ld: %s\n", thread->id, strerror(error)); 1004 return; 1005 } 1006 1007 // prepare the message 1008 debug_watchpoint_hit message; 1009 arch_get_debug_cpu_state(&message.cpu_state); 1010 1011 thread_hit_debug_event(B_DEBUGGER_MESSAGE_WATCHPOINT_HIT, &message, 1012 sizeof(message), true); 1013 } 1014 1015 1016 void 1017 user_debug_single_stepped() 1018 { 1019 // ensure that a debugger is installed for this team 1020 struct thread *thread = thread_get_current_thread(); 1021 port_id nubPort; 1022 status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort); 1023 if (error != B_OK) { 1024 dprintf("user_debug_watchpoint_hit(): Failed to install debugger: " 1025 "thread: %ld: %s\n", thread->id, strerror(error)); 1026 return; 1027 } 1028 1029 // prepare the message 1030 debug_single_step message; 1031 arch_get_debug_cpu_state(&message.cpu_state); 1032 1033 thread_hit_debug_event(B_DEBUGGER_MESSAGE_SINGLE_STEP, &message, 1034 sizeof(message), true); 1035 } 1036 1037 1038 /** \brief Called by the debug nub thread of a team to broadcast a message 1039 * that are initialized for debugging (and thus have a debug port). 1040 */ 1041 static void 1042 broadcast_debugged_thread_message(struct thread *nubThread, int32 code, 1043 const void *message, int32 size) 1044 { 1045 // iterate through the threads 1046 thread_info threadInfo; 1047 int32 cookie = 0; 1048 while (get_next_thread_info(nubThread->team->id, &cookie, &threadInfo) 1049 == B_OK) { 1050 // find the thread and get its debug port 1051 cpu_status state = disable_interrupts(); 1052 GRAB_THREAD_LOCK(); 1053 1054 port_id threadDebugPort = -1; 1055 thread_id threadID = -1; 1056 struct thread *thread 1057 = thread_get_thread_struct_locked(threadInfo.thread); 1058 if (thread && thread != nubThread && thread->team == nubThread->team 1059 && thread->debug_info.flags & B_THREAD_DEBUG_INITIALIZED) { 1060 threadDebugPort = thread->debug_info.debug_port; 1061 threadID = thread->id; 1062 } 1063 1064 RELEASE_THREAD_LOCK(); 1065 restore_interrupts(state); 1066 1067 // send the message to the thread 1068 if (threadDebugPort >= 0) { 1069 status_t error = kill_interruptable_write_port(threadDebugPort, 1070 code, message, size); 1071 if (error != B_OK) { 1072 TRACE(("broadcast_debugged_thread_message(): Failed to send " 1073 "message to thread %ld: %lx\n", threadID, error)); 1074 } 1075 } 1076 } 1077 } 1078 1079 1080 static void 1081 nub_thread_cleanup(struct thread *nubThread) 1082 { 1083 TRACE(("nub_thread_cleanup(%ld): debugger port: %ld\n", nubThread->id, 1084 nubThread->team->debug_info.debugger_port)); 1085 1086 team_debug_info teamDebugInfo; 1087 bool destroyDebugInfo = false; 1088 1089 cpu_status state = disable_interrupts(); 1090 GRAB_TEAM_LOCK(); 1091 GRAB_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info); 1092 1093 team_debug_info &info = nubThread->team->debug_info; 1094 if (info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED 1095 && info.nub_thread == nubThread->id) { 1096 teamDebugInfo = info; 1097 clear_team_debug_info(&info, false); 1098 destroyDebugInfo = true; 1099 } 1100 1101 // update the thread::flags fields 1102 update_threads_debugger_installed_flag(nubThread->team); 1103 1104 RELEASE_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info); 1105 RELEASE_TEAM_LOCK(); 1106 restore_interrupts(state); 1107 1108 if (destroyDebugInfo) 1109 destroy_team_debug_info(&teamDebugInfo); 1110 1111 // notify all threads that the debugger is gone 1112 broadcast_debugged_thread_message(nubThread, 1113 B_DEBUGGED_THREAD_DEBUGGER_CHANGED, NULL, 0); 1114 } 1115 1116 1117 /** \brief Reads data from user memory. 1118 * 1119 * Tries to read \a size bytes of data from user memory address \a address 1120 * into the supplied buffer \a buffer. If only a part could be read the 1121 * function won't fail. The number of bytes actually read is return through 1122 * \a bytesRead. 1123 * 1124 * \param address The user memory address from which to read. 1125 * \param buffer The buffer into which to write. 1126 * \param size The number of bytes to read. 1127 * \param bytesRead Will be set to the number of bytes actually read. 1128 * \return \c B_OK, if reading went fine. Then \a bytesRead will be set to 1129 * the amount of data actually read. An error indicates that nothing 1130 * has been read. 1131 */ 1132 static status_t 1133 read_user_memory(const void *_address, void *_buffer, int32 size, 1134 int32 &bytesRead) 1135 { 1136 const char *address = (const char*)_address; 1137 char *buffer = (char*)_buffer; 1138 1139 // check the parameters 1140 if (!IS_USER_ADDRESS(address)) 1141 return B_BAD_ADDRESS; 1142 if (size <= 0) 1143 return B_BAD_VALUE; 1144 1145 // If the region to be read crosses page boundaries, we split it up into 1146 // smaller chunks. 1147 status_t error = B_OK; 1148 bytesRead = 0; 1149 while (size > 0) { 1150 // check whether we're still in user address space 1151 if (!IS_USER_ADDRESS(address)) { 1152 error = B_BAD_ADDRESS; 1153 break; 1154 } 1155 1156 // don't cross page boundaries in a single read 1157 int32 toRead = size; 1158 int32 maxRead = B_PAGE_SIZE - (addr_t)address % B_PAGE_SIZE; 1159 if (toRead > maxRead) 1160 toRead = maxRead; 1161 1162 error = user_memcpy(buffer, address, toRead); 1163 if (error != B_OK) 1164 break; 1165 1166 bytesRead += toRead; 1167 address += toRead; 1168 buffer += toRead; 1169 size -= toRead; 1170 } 1171 1172 // If reading fails, we only fail, if we haven't read anything yet. 1173 if (error != B_OK) { 1174 if (bytesRead > 0) 1175 return B_OK; 1176 return error; 1177 } 1178 1179 return B_OK; 1180 } 1181 1182 1183 static status_t 1184 write_user_memory(void *_address, const void *_buffer, int32 size, 1185 int32 &bytesWritten) 1186 { 1187 char *address = (char*)_address; 1188 const char *buffer = (const char*)_buffer; 1189 1190 // check the parameters 1191 if (!IS_USER_ADDRESS(address)) 1192 return B_BAD_ADDRESS; 1193 if (size <= 0) 1194 return B_BAD_VALUE; 1195 1196 // If the region to be written crosses area boundaries, we split it up into 1197 // smaller chunks. 1198 status_t error = B_OK; 1199 bytesWritten = 0; 1200 while (size > 0) { 1201 // check whether we're still in user address space 1202 if (!IS_USER_ADDRESS(address)) { 1203 error = B_BAD_ADDRESS; 1204 break; 1205 } 1206 1207 // get the area for the address (we need to use _user_area_for(), since 1208 // we're looking for a user area) 1209 area_id area = _user_area_for((void*)address); 1210 if (area < 0) { 1211 TRACE(("write_user_memory(): area not found for address: %p: " 1212 "%lx\n", address, area)); 1213 error = area; 1214 break; 1215 } 1216 1217 area_info areaInfo; 1218 status_t error = get_area_info(area, &areaInfo); 1219 if (error != B_OK) { 1220 TRACE(("write_user_memory(): failed to get info for area %ld: " 1221 "%lx\n", area, error)); 1222 error = B_BAD_ADDRESS; 1223 break; 1224 } 1225 1226 // restrict this round of writing to the found area 1227 int32 toWrite = size; 1228 int32 maxWrite = (char*)areaInfo.address + areaInfo.size - address; 1229 if (toWrite > maxWrite) 1230 toWrite = maxWrite; 1231 1232 // if the area is read-only, we temporarily need to make it writable 1233 bool protectionChanged = false; 1234 if (!(areaInfo.protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA))) { 1235 error = set_area_protection(area, 1236 areaInfo.protection | B_WRITE_AREA); 1237 if (error != B_OK) { 1238 TRACE(("write_user_memory(): failed to set new protection for " 1239 "area %ld: %lx\n", area, error)); 1240 break; 1241 } 1242 protectionChanged = true; 1243 } 1244 1245 // copy the memory 1246 error = user_memcpy(address, buffer, toWrite); 1247 1248 // reset the area protection 1249 if (protectionChanged) 1250 set_area_protection(area, areaInfo.protection); 1251 1252 if (error != B_OK) { 1253 TRACE(("write_user_memory(): user_memcpy() failed: %lx\n", error)); 1254 break; 1255 } 1256 1257 bytesWritten += toWrite; 1258 address += toWrite; 1259 buffer += toWrite; 1260 size -= toWrite; 1261 } 1262 1263 // If writing fails, we only fail, if we haven't written anything yet. 1264 if (error != B_OK) { 1265 if (bytesWritten > 0) 1266 return B_OK; 1267 return error; 1268 } 1269 1270 return B_OK; 1271 } 1272 1273 1274 /** \brief Debug nub thread helper function that returns the debug port of 1275 * a thread of the same team. 1276 */ 1277 static status_t 1278 debug_nub_thread_get_thread_debug_port(struct thread *nubThread, 1279 thread_id threadID, port_id &threadDebugPort) 1280 { 1281 status_t result = B_OK; 1282 threadDebugPort = -1; 1283 1284 cpu_status state = disable_interrupts(); 1285 GRAB_THREAD_LOCK(); 1286 1287 struct thread *thread = thread_get_thread_struct_locked(threadID); 1288 if (thread) { 1289 if (thread->team != nubThread->team) 1290 result = B_BAD_VALUE; 1291 else if (thread->debug_info.flags & B_THREAD_DEBUG_STOPPED) 1292 threadDebugPort = thread->debug_info.debug_port; 1293 else 1294 result = B_BAD_VALUE; 1295 } else 1296 result = B_BAD_THREAD_ID; 1297 1298 RELEASE_THREAD_LOCK(); 1299 restore_interrupts(state); 1300 1301 if (result == B_OK && threadDebugPort < 0) 1302 result = B_ERROR; 1303 1304 return result; 1305 } 1306 1307 1308 static status_t 1309 debug_nub_thread(void *) 1310 { 1311 struct thread *nubThread = thread_get_current_thread(); 1312 1313 // check, if we're still the current nub thread and get our port 1314 cpu_status state = disable_interrupts(); 1315 1316 GRAB_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info); 1317 1318 if (nubThread->team->debug_info.nub_thread != nubThread->id) 1319 return 0; 1320 1321 port_id port = nubThread->team->debug_info.nub_port; 1322 sem_id writeLock = nubThread->team->debug_info.debugger_write_lock; 1323 1324 RELEASE_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info); 1325 restore_interrupts(state); 1326 1327 TRACE(("debug_nub_thread() thread: %ld, team %ld, nub port: %ld\n", 1328 nubThread->id, nubThread->team->id, port)); 1329 1330 // notify all threads that a debugger has been installed 1331 broadcast_debugged_thread_message(nubThread, 1332 B_DEBUGGED_THREAD_DEBUGGER_CHANGED, NULL, 0); 1333 1334 // command processing loop 1335 while (true) { 1336 int32 command; 1337 debug_nub_message_data message; 1338 ssize_t messageSize = kill_interruptable_read_port(port, &command, 1339 &message, sizeof(message)); 1340 1341 if (messageSize < 0) { 1342 // The port is not longer valid or we were interrupted by a kill 1343 // signal: If we are still listed in the team's debug info as nub 1344 // thread, we need to update that. 1345 nub_thread_cleanup(nubThread); 1346 1347 TRACE(("nub thread %ld: terminating: %lx\n", nubThread->id, 1348 messageSize)); 1349 1350 return messageSize; 1351 } 1352 1353 bool sendReply = false; 1354 union { 1355 debug_nub_read_memory_reply read_memory; 1356 debug_nub_write_memory_reply write_memory; 1357 debug_nub_get_cpu_state_reply get_cpu_state; 1358 debug_nub_set_breakpoint_reply set_breakpoint; 1359 debug_nub_set_watchpoint_reply set_watchpoint; 1360 debug_nub_get_signal_masks_reply get_signal_masks; 1361 debug_nub_get_signal_handler_reply get_signal_handler; 1362 } reply; 1363 int32 replySize = 0; 1364 port_id replyPort = -1; 1365 1366 // process the command 1367 switch (command) { 1368 case B_DEBUG_MESSAGE_READ_MEMORY: 1369 { 1370 // get the parameters 1371 replyPort = message.read_memory.reply_port; 1372 void *address = message.read_memory.address; 1373 int32 size = message.read_memory.size; 1374 status_t result = B_OK; 1375 1376 // check the parameters 1377 if (!IS_USER_ADDRESS(address)) 1378 result = B_BAD_ADDRESS; 1379 else if (size <= 0 || size > B_MAX_READ_WRITE_MEMORY_SIZE) 1380 result = B_BAD_VALUE; 1381 1382 // read the memory 1383 int32 bytesRead = 0; 1384 if (result == B_OK) { 1385 result = read_user_memory(address, reply.read_memory.data, 1386 size, bytesRead); 1387 } 1388 reply.read_memory.error = result; 1389 1390 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_READ_MEMORY: " 1391 "reply port: %ld, address: %p, size: %ld, result: %lx, " 1392 "read: %ld\n", nubThread->id, replyPort, address, size, 1393 result, bytesRead)); 1394 1395 // send only as much data as necessary 1396 reply.read_memory.size = bytesRead; 1397 replySize = reply.read_memory.data + bytesRead - (char*)&reply; 1398 sendReply = true; 1399 break; 1400 } 1401 1402 case B_DEBUG_MESSAGE_WRITE_MEMORY: 1403 { 1404 // get the parameters 1405 replyPort = message.write_memory.reply_port; 1406 void *address = message.write_memory.address; 1407 int32 size = message.write_memory.size; 1408 const char *data = message.write_memory.data; 1409 int32 realSize = (char*)&message + messageSize - data; 1410 status_t result = B_OK; 1411 1412 // check the parameters 1413 if (!IS_USER_ADDRESS(address)) 1414 result = B_BAD_ADDRESS; 1415 else if (size <= 0 || size > realSize) 1416 result = B_BAD_VALUE; 1417 1418 // write the memory 1419 int32 bytesWritten = 0; 1420 if (result == B_OK) { 1421 result = write_user_memory(address, data, size, 1422 bytesWritten); 1423 } 1424 reply.write_memory.error = result; 1425 1426 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_WRITE_MEMORY: " 1427 "reply port: %ld, address: %p, size: %ld, result: %lx, " 1428 "written: %ld\n", nubThread->id, replyPort, address, size, 1429 result, bytesWritten)); 1430 1431 reply.write_memory.size = bytesWritten; 1432 sendReply = true; 1433 replySize = sizeof(debug_nub_write_memory_reply); 1434 break; 1435 } 1436 1437 case B_DEBUG_MESSAGE_SET_TEAM_FLAGS: 1438 { 1439 // get the parameters 1440 int32 flags = message.set_team_flags.flags 1441 & B_TEAM_DEBUG_USER_FLAG_MASK; 1442 1443 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_TEAM_FLAGS: " 1444 "flags: %lx\n", nubThread->id, flags)); 1445 1446 struct team *team = thread_get_current_thread()->team; 1447 1448 // set the flags 1449 cpu_status state = disable_interrupts(); 1450 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 1451 1452 flags |= team->debug_info.flags & B_TEAM_DEBUG_KERNEL_FLAG_MASK; 1453 atomic_set(&team->debug_info.flags, flags); 1454 1455 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 1456 restore_interrupts(state); 1457 1458 break; 1459 } 1460 1461 case B_DEBUG_MESSAGE_SET_THREAD_FLAGS: 1462 { 1463 // get the parameters 1464 thread_id threadID = message.set_thread_flags.thread; 1465 int32 flags = message.set_thread_flags.flags 1466 & B_THREAD_DEBUG_USER_FLAG_MASK; 1467 1468 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_THREAD_FLAGS: " 1469 "thread: %ld, flags: %lx\n", nubThread->id, threadID, 1470 flags)); 1471 1472 // set the flags 1473 cpu_status state = disable_interrupts(); 1474 GRAB_THREAD_LOCK(); 1475 1476 struct thread *thread 1477 = thread_get_thread_struct_locked(threadID); 1478 if (thread 1479 && thread->team == thread_get_current_thread()->team) { 1480 flags |= thread->debug_info.flags 1481 & B_THREAD_DEBUG_KERNEL_FLAG_MASK; 1482 atomic_set(&thread->debug_info.flags, flags); 1483 } 1484 1485 RELEASE_THREAD_LOCK(); 1486 restore_interrupts(state); 1487 1488 break; 1489 } 1490 1491 case B_DEBUG_MESSAGE_CONTINUE_THREAD: 1492 { 1493 // get the parameters 1494 thread_id threadID; 1495 uint32 handleEvent; 1496 bool singleStep; 1497 1498 threadID = message.continue_thread.thread; 1499 handleEvent = message.continue_thread.handle_event; 1500 singleStep = message.continue_thread.single_step; 1501 1502 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CONTINUE_THREAD: " 1503 "thread: %ld, handle event: %lu, single step: %d\n", 1504 nubThread->id, threadID, handleEvent, singleStep)); 1505 1506 // find the thread and get its debug port 1507 port_id threadDebugPort = -1; 1508 status_t result = debug_nub_thread_get_thread_debug_port( 1509 nubThread, threadID, threadDebugPort); 1510 1511 // send a message to the debugged thread 1512 if (result == B_OK) { 1513 debugged_thread_continue commandMessage; 1514 commandMessage.handle_event = handleEvent; 1515 commandMessage.single_step = singleStep; 1516 1517 result = write_port(threadDebugPort, 1518 B_DEBUGGED_THREAD_MESSAGE_CONTINUE, 1519 &commandMessage, sizeof(commandMessage)); 1520 } 1521 1522 break; 1523 } 1524 1525 case B_DEBUG_MESSAGE_SET_CPU_STATE: 1526 { 1527 // get the parameters 1528 thread_id threadID = message.set_cpu_state.thread; 1529 const debug_cpu_state &cpuState 1530 = message.set_cpu_state.cpu_state; 1531 1532 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_CPU_STATE: " 1533 "thread: %ld\n", nubThread->id, threadID)); 1534 1535 // find the thread and get its debug port 1536 port_id threadDebugPort = -1; 1537 status_t result = debug_nub_thread_get_thread_debug_port( 1538 nubThread, threadID, threadDebugPort); 1539 1540 // send a message to the debugged thread 1541 if (result == B_OK) { 1542 debugged_thread_set_cpu_state commandMessage; 1543 memcpy(&commandMessage.cpu_state, &cpuState, 1544 sizeof(debug_cpu_state)); 1545 write_port(threadDebugPort, 1546 B_DEBUGGED_THREAD_SET_CPU_STATE, 1547 &commandMessage, sizeof(commandMessage)); 1548 } 1549 1550 break; 1551 } 1552 1553 case B_DEBUG_MESSAGE_GET_CPU_STATE: 1554 { 1555 // get the parameters 1556 thread_id threadID = message.get_cpu_state.thread; 1557 replyPort = message.get_cpu_state.reply_port; 1558 1559 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_CPU_STATE: " 1560 "thread: %ld\n", nubThread->id, threadID)); 1561 1562 // find the thread and get its debug port 1563 port_id threadDebugPort = -1; 1564 status_t result = debug_nub_thread_get_thread_debug_port( 1565 nubThread, threadID, threadDebugPort); 1566 1567 // send a message to the debugged thread 1568 if (threadDebugPort >= 0) { 1569 debugged_thread_get_cpu_state commandMessage; 1570 commandMessage.reply_port = replyPort; 1571 result = write_port(threadDebugPort, 1572 B_DEBUGGED_THREAD_GET_CPU_STATE, &commandMessage, 1573 sizeof(commandMessage)); 1574 } 1575 1576 // send a reply to the debugger in case of error 1577 if (result != B_OK) { 1578 reply.get_cpu_state.error = result; 1579 sendReply = true; 1580 replySize = sizeof(reply.get_cpu_state); 1581 } 1582 1583 break; 1584 } 1585 1586 case B_DEBUG_MESSAGE_SET_BREAKPOINT: 1587 { 1588 // get the parameters 1589 replyPort = message.set_breakpoint.reply_port; 1590 void *address = message.set_breakpoint.address; 1591 1592 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_BREAKPOINT: " 1593 "address: %p\n", nubThread->id, address)); 1594 1595 // check the address 1596 status_t result = B_OK; 1597 if (address == NULL || !IS_USER_ADDRESS(address)) 1598 result = B_BAD_ADDRESS; 1599 1600 // set the breakpoint 1601 if (result == B_OK) 1602 result = arch_set_breakpoint(address); 1603 1604 if (result == B_OK) 1605 update_threads_breakpoints_flag(); 1606 1607 // prepare the reply 1608 reply.set_breakpoint.error = result; 1609 replySize = sizeof(reply.set_breakpoint); 1610 sendReply = true; 1611 1612 break; 1613 } 1614 1615 case B_DEBUG_MESSAGE_CLEAR_BREAKPOINT: 1616 { 1617 // get the parameters 1618 void *address = message.clear_breakpoint.address; 1619 1620 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CLEAR_BREAKPOINT: " 1621 "address: %p\n", nubThread->id, address)); 1622 1623 // check the address 1624 status_t result = B_OK; 1625 if (address == NULL || !IS_USER_ADDRESS(address)) 1626 result = B_BAD_ADDRESS; 1627 1628 // clear the breakpoint 1629 if (result == B_OK) 1630 result = arch_clear_breakpoint(address); 1631 1632 if (result == B_OK) 1633 update_threads_breakpoints_flag(); 1634 1635 break; 1636 } 1637 1638 case B_DEBUG_MESSAGE_SET_WATCHPOINT: 1639 { 1640 // get the parameters 1641 replyPort = message.set_watchpoint.reply_port; 1642 void *address = message.set_watchpoint.address; 1643 uint32 type = message.set_watchpoint.type; 1644 int32 length = message.set_watchpoint.length; 1645 1646 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_WATCHPOINT: " 1647 "address: %p, type: %lu, length: %ld\n", nubThread->id, 1648 address, type, length)); 1649 1650 // check the address and size 1651 status_t result = B_OK; 1652 if (address == NULL || !IS_USER_ADDRESS(address)) 1653 result = B_BAD_ADDRESS; 1654 if (length < 0) 1655 result = B_BAD_VALUE; 1656 1657 // set the watchpoint 1658 if (result == B_OK) 1659 result = arch_set_watchpoint(address, type, length); 1660 1661 if (result == B_OK) 1662 update_threads_breakpoints_flag(); 1663 1664 // prepare the reply 1665 reply.set_watchpoint.error = result; 1666 replySize = sizeof(reply.set_watchpoint); 1667 sendReply = true; 1668 1669 break; 1670 } 1671 1672 case B_DEBUG_MESSAGE_CLEAR_WATCHPOINT: 1673 { 1674 // get the parameters 1675 void *address = message.clear_watchpoint.address; 1676 1677 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CLEAR_WATCHPOINT: " 1678 "address: %p\n", nubThread->id, address)); 1679 1680 // check the address 1681 status_t result = B_OK; 1682 if (address == NULL || !IS_USER_ADDRESS(address)) 1683 result = B_BAD_ADDRESS; 1684 1685 // clear the watchpoint 1686 if (result == B_OK) 1687 result = arch_clear_watchpoint(address); 1688 1689 if (result == B_OK) 1690 update_threads_breakpoints_flag(); 1691 1692 break; 1693 } 1694 1695 case B_DEBUG_MESSAGE_SET_SIGNAL_MASKS: 1696 { 1697 // get the parameters 1698 thread_id threadID = message.set_signal_masks.thread; 1699 uint64 ignore = message.set_signal_masks.ignore_mask; 1700 uint64 ignoreOnce = message.set_signal_masks.ignore_once_mask; 1701 uint32 ignoreOp = message.set_signal_masks.ignore_op; 1702 uint32 ignoreOnceOp = message.set_signal_masks.ignore_once_op; 1703 1704 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_SIGNAL_MASKS: " 1705 "thread: %ld, ignore: %llx (op: %lu), ignore once: %llx " 1706 "(op: %lu)\n", nubThread->id, threadID, ignore, 1707 ignoreOp, ignoreOnce, ignoreOnceOp)); 1708 1709 // set the masks 1710 cpu_status state = disable_interrupts(); 1711 GRAB_THREAD_LOCK(); 1712 1713 struct thread *thread 1714 = thread_get_thread_struct_locked(threadID); 1715 if (thread 1716 && thread->team == thread_get_current_thread()->team) { 1717 thread_debug_info &threadDebugInfo = thread->debug_info; 1718 // set ignore mask 1719 switch (ignoreOp) { 1720 case B_DEBUG_SIGNAL_MASK_AND: 1721 threadDebugInfo.ignore_signals &= ignore; 1722 break; 1723 case B_DEBUG_SIGNAL_MASK_OR: 1724 threadDebugInfo.ignore_signals |= ignore; 1725 break; 1726 case B_DEBUG_SIGNAL_MASK_SET: 1727 threadDebugInfo.ignore_signals = ignore; 1728 break; 1729 } 1730 1731 // set ignore once mask 1732 switch (ignoreOnceOp) { 1733 case B_DEBUG_SIGNAL_MASK_AND: 1734 threadDebugInfo.ignore_signals_once &= ignoreOnce; 1735 break; 1736 case B_DEBUG_SIGNAL_MASK_OR: 1737 threadDebugInfo.ignore_signals_once |= ignoreOnce; 1738 break; 1739 case B_DEBUG_SIGNAL_MASK_SET: 1740 threadDebugInfo.ignore_signals_once = ignoreOnce; 1741 break; 1742 } 1743 } 1744 1745 RELEASE_THREAD_LOCK(); 1746 restore_interrupts(state); 1747 1748 break; 1749 } 1750 1751 case B_DEBUG_MESSAGE_GET_SIGNAL_MASKS: 1752 { 1753 // get the parameters 1754 replyPort = message.get_signal_masks.reply_port; 1755 thread_id threadID = message.get_signal_masks.thread; 1756 status_t result = B_OK; 1757 1758 // get the masks 1759 uint64 ignore = 0; 1760 uint64 ignoreOnce = 0; 1761 1762 cpu_status state = disable_interrupts(); 1763 GRAB_THREAD_LOCK(); 1764 1765 struct thread *thread 1766 = thread_get_thread_struct_locked(threadID); 1767 if (thread) { 1768 ignore = thread->debug_info.ignore_signals; 1769 ignoreOnce = thread->debug_info.ignore_signals_once; 1770 } else 1771 result = B_BAD_THREAD_ID; 1772 1773 RELEASE_THREAD_LOCK(); 1774 restore_interrupts(state); 1775 1776 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_SIGNAL_MASKS: " 1777 "reply port: %ld, thread: %ld, ignore: %llx, " 1778 "ignore once: %llx, result: %lx\n", nubThread->id, 1779 replyPort, threadID, ignore, ignoreOnce, result)); 1780 1781 // prepare the message 1782 reply.get_signal_masks.error = result; 1783 reply.get_signal_masks.ignore_mask = ignore; 1784 reply.get_signal_masks.ignore_once_mask = ignoreOnce; 1785 replySize = sizeof(reply.get_signal_masks); 1786 sendReply = true; 1787 break; 1788 } 1789 1790 case B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER: 1791 { 1792 // get the parameters 1793 thread_id threadID = message.set_signal_handler.thread; 1794 int signal = message.set_signal_handler.signal; 1795 struct sigaction &handler = message.set_signal_handler.handler; 1796 1797 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER: " 1798 "thread: %ld, signal: %d, handler: %p\n", nubThread->id, 1799 threadID, signal, handler.sa_handler)); 1800 1801 // check, if the thread exists and is ours 1802 cpu_status state = disable_interrupts(); 1803 GRAB_THREAD_LOCK(); 1804 1805 struct thread *thread 1806 = thread_get_thread_struct_locked(threadID); 1807 if (thread 1808 && thread->team != thread_get_current_thread()->team) { 1809 thread = NULL; 1810 } 1811 1812 RELEASE_THREAD_LOCK(); 1813 restore_interrupts(state); 1814 1815 // set the handler 1816 if (thread) 1817 sigaction_etc(threadID, signal, &handler, NULL); 1818 1819 break; 1820 } 1821 1822 case B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER: 1823 { 1824 // get the parameters 1825 replyPort = message.get_signal_handler.reply_port; 1826 thread_id threadID = message.get_signal_handler.thread; 1827 int signal = message.get_signal_handler.signal; 1828 status_t result = B_OK; 1829 1830 // check, if the thread exists and is ours 1831 cpu_status state = disable_interrupts(); 1832 GRAB_THREAD_LOCK(); 1833 1834 struct thread *thread 1835 = thread_get_thread_struct_locked(threadID); 1836 if (thread) { 1837 if (thread->team != thread_get_current_thread()->team) 1838 result = B_BAD_VALUE; 1839 } else 1840 result = B_BAD_THREAD_ID; 1841 1842 RELEASE_THREAD_LOCK(); 1843 restore_interrupts(state); 1844 1845 // get the handler 1846 if (result == B_OK) { 1847 result = sigaction_etc(threadID, signal, NULL, 1848 &reply.get_signal_handler.handler); 1849 } 1850 1851 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER: " 1852 "reply port: %ld, thread: %ld, signal: %d, " 1853 "handler: %p\n", nubThread->id, replyPort, 1854 threadID, signal, 1855 reply.get_signal_handler.handler.sa_handler)); 1856 1857 // prepare the message 1858 reply.get_signal_handler.error = result; 1859 replySize = sizeof(reply.get_signal_handler); 1860 sendReply = true; 1861 break; 1862 } 1863 1864 case B_DEBUG_MESSAGE_PREPARE_HANDOVER: 1865 { 1866 TRACE(("nub thread %ld: B_DEBUG_MESSAGE_PREPARE_HANDOVER\n", 1867 nubThread->id)); 1868 1869 struct team *team = nubThread->team; 1870 1871 // Acquire the debugger write lock. As soon as we have it and 1872 // have set the B_TEAM_DEBUG_DEBUGGER_HANDOVER flag, no thread 1873 // will write anything to the debugger port anymore. 1874 status_t result = acquire_sem_etc(writeLock, 1, 1875 B_KILL_CAN_INTERRUPT, 0); 1876 if (result == B_OK) { 1877 // set the respective team debug flag 1878 cpu_status state = disable_interrupts(); 1879 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 1880 1881 atomic_or(&team->debug_info.flags, 1882 B_TEAM_DEBUG_DEBUGGER_HANDOVER); 1883 1884 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 1885 restore_interrupts(state); 1886 1887 release_sem(writeLock); 1888 } else { 1889 // We probably got a SIGKILL. If so, we will terminate when 1890 // reading the next message fails. 1891 } 1892 1893 break; 1894 } 1895 1896 case B_DEBUG_MESSAGE_HANDED_OVER: 1897 { 1898 // notify all threads that the debugger has changed 1899 broadcast_debugged_thread_message(nubThread, 1900 B_DEBUGGED_THREAD_DEBUGGER_CHANGED, NULL, 0); 1901 1902 break; 1903 } 1904 } 1905 1906 // send the reply, if necessary 1907 if (sendReply) { 1908 status_t error = kill_interruptable_write_port(replyPort, command, 1909 &reply, replySize); 1910 1911 if (error != B_OK) { 1912 // The debugger port is either not longer existing or we got 1913 // interrupted by a kill signal. In either case we terminate. 1914 TRACE(("nub thread %ld: failed to send reply to port %ld: %s\n", 1915 nubThread->id, replyPort, strerror(error))); 1916 1917 nub_thread_cleanup(nubThread); 1918 return error; 1919 } 1920 } 1921 } 1922 } 1923 1924 1925 /** \brief Helper function for install_team_debugger(), that sets up the team 1926 and thread debug infos. 1927 1928 Interrupts must be disabled and the team debug info lock of the team to be 1929 debugged must be held. The function will release the lock, but leave 1930 interrupts disabled. The team lock must be held, too. 1931 1932 The function also clears the arch specific team and thread debug infos 1933 (including among other things formerly set break/watchpoints). 1934 */ 1935 static void 1936 install_team_debugger_init_debug_infos(struct team *team, team_id debuggerTeam, 1937 port_id debuggerPort, port_id nubPort, thread_id nubThread, 1938 sem_id debuggerPortWriteLock) 1939 { 1940 atomic_set(&team->debug_info.flags, 1941 B_TEAM_DEBUG_DEFAULT_FLAGS | B_TEAM_DEBUG_DEBUGGER_INSTALLED); 1942 team->debug_info.nub_port = nubPort; 1943 team->debug_info.nub_thread = nubThread; 1944 team->debug_info.debugger_team = debuggerTeam; 1945 team->debug_info.debugger_port = debuggerPort; 1946 team->debug_info.debugger_write_lock = debuggerPortWriteLock; 1947 1948 arch_clear_team_debug_info(&team->debug_info.arch_info); 1949 1950 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 1951 1952 // set the user debug flags and signal masks of all threads to the default 1953 GRAB_THREAD_LOCK(); 1954 1955 for (struct thread *thread = team->thread_list; 1956 thread; 1957 thread = thread->team_next) { 1958 if (thread->id == nubThread) { 1959 atomic_set(&thread->debug_info.flags, B_THREAD_DEBUG_NUB_THREAD); 1960 } else { 1961 int32 flags = thread->debug_info.flags 1962 & ~B_THREAD_DEBUG_USER_FLAG_MASK; 1963 atomic_set(&thread->debug_info.flags, 1964 flags | B_THREAD_DEBUG_DEFAULT_FLAGS); 1965 thread->debug_info.ignore_signals = 0; 1966 thread->debug_info.ignore_signals_once = 0; 1967 1968 arch_clear_thread_debug_info(&thread->debug_info.arch_info); 1969 } 1970 } 1971 1972 RELEASE_THREAD_LOCK(); 1973 1974 // update the thread::flags fields 1975 update_threads_debugger_installed_flag(team); 1976 } 1977 1978 1979 static port_id 1980 install_team_debugger(team_id teamID, port_id debuggerPort, bool useDefault, 1981 bool dontFail) 1982 { 1983 TRACE(("install_team_debugger(team: %ld, port: %ld, default: %d, " 1984 "dontFail: %d)\n", teamID, debuggerPort, useDefault, dontFail)); 1985 1986 if (useDefault) 1987 debuggerPort = atomic_get(&sDefaultDebuggerPort); 1988 1989 // get the debugger team 1990 port_info debuggerPortInfo; 1991 status_t error = get_port_info(debuggerPort, &debuggerPortInfo); 1992 if (error != B_OK) { 1993 TRACE(("install_team_debugger(): Failed to get debugger port info: " 1994 "%lx\n", error)); 1995 return error; 1996 } 1997 team_id debuggerTeam = debuggerPortInfo.team; 1998 1999 // check the debugger team: It must neither be the kernel team nor the 2000 // debugged team 2001 if (debuggerTeam == team_get_kernel_team_id() || debuggerTeam == teamID) { 2002 TRACE(("install_team_debugger(): Can't debug kernel or debugger team. " 2003 "debugger: %ld, debugged: %ld\n", debuggerTeam, teamID)); 2004 return B_NOT_ALLOWED; 2005 } 2006 2007 // check, if a debugger is already installed 2008 2009 bool done = false; 2010 port_id result = B_ERROR; 2011 bool handOver = false; 2012 bool releaseDebugInfoLock = true; 2013 port_id oldDebuggerPort = -1; 2014 port_id nubPort = -1; 2015 2016 cpu_status state = disable_interrupts(); 2017 GRAB_TEAM_LOCK(); 2018 2019 // get a real team ID 2020 // We look up the team by ID, even in case of the current team, so we can be 2021 // sure, that the team is not already dying. 2022 if (teamID == B_CURRENT_TEAM) 2023 teamID = thread_get_current_thread()->team->id; 2024 2025 struct team *team = team_get_team_struct_locked(teamID); 2026 2027 if (team) { 2028 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2029 2030 int32 teamDebugFlags = team->debug_info.flags; 2031 2032 if (team == team_get_kernel_team()) { 2033 // don't allow to debug the kernel 2034 error = B_NOT_ALLOWED; 2035 } else if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 2036 if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_HANDOVER) { 2037 // a handover to another debugger is requested 2038 // clear the flag 2039 atomic_and(& team->debug_info.flags, 2040 ~B_TEAM_DEBUG_DEBUGGER_HANDOVER); 2041 2042 oldDebuggerPort = team->debug_info.debugger_port; 2043 result = nubPort = team->debug_info.nub_port; 2044 2045 // set the new debugger 2046 install_team_debugger_init_debug_infos(team, debuggerTeam, 2047 debuggerPort, nubPort, team->debug_info.nub_thread, 2048 team->debug_info.debugger_write_lock); 2049 2050 releaseDebugInfoLock = false; 2051 handOver = true; 2052 done = true; 2053 2054 // finally set the new port owner 2055 if (set_port_owner(nubPort, debuggerTeam) != B_OK) { 2056 // The old debugger must just have died. Just proceed as 2057 // if there was no debugger installed. We may still be too 2058 // early, in which case we'll fail, but this race condition 2059 // should be unbelievably rare and relatively harmless. 2060 handOver = false; 2061 done = false; 2062 } 2063 2064 } else { 2065 // there's already a debugger installed 2066 error = (dontFail ? B_OK : B_BAD_VALUE); 2067 done = true; 2068 result = team->debug_info.nub_port; 2069 } 2070 } 2071 2072 // in case of a handover the lock has already been released 2073 if (releaseDebugInfoLock) 2074 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2075 } else 2076 error = B_BAD_TEAM_ID; 2077 2078 RELEASE_TEAM_LOCK(); 2079 restore_interrupts(state); 2080 2081 if (handOver) { 2082 // notify the nub thread 2083 kill_interruptable_write_port(nubPort, B_DEBUG_MESSAGE_HANDED_OVER, 2084 NULL, 0); 2085 2086 // notify the old debugger 2087 debug_handed_over notification; 2088 notification.origin.thread = -1; 2089 notification.origin.team = teamID; 2090 notification.origin.nub_port = nubPort; 2091 notification.debugger = debuggerTeam; 2092 notification.debugger_port = debuggerPort; 2093 2094 error = write_port_etc(oldDebuggerPort, 2095 B_DEBUGGER_MESSAGE_HANDED_OVER, ¬ification, 2096 sizeof(notification), B_RELATIVE_TIMEOUT, 0); 2097 if (error != B_OK) { 2098 TRACE(("install_team_debugger(): Failed to send message to old " 2099 "debugger: %s\n", strerror(error))); 2100 } 2101 2102 TRACE(("install_team_debugger() done: handed over to debugger: team: " 2103 "%ld, port: %ld\n", debuggerTeam, debuggerPort)); 2104 2105 return result; 2106 } 2107 2108 if (done || error != B_OK) { 2109 TRACE(("install_team_debugger() done1: %ld\n", 2110 (error == B_OK ? result : error))); 2111 return (error == B_OK ? result : error); 2112 } 2113 2114 // create the debugger write lock semaphore 2115 char nameBuffer[B_OS_NAME_LENGTH]; 2116 snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debugger port write", 2117 teamID); 2118 sem_id debuggerWriteLock = create_sem(1, nameBuffer); 2119 if (debuggerWriteLock < 0) 2120 error = debuggerWriteLock; 2121 2122 // create the nub port 2123 snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug", teamID); 2124 if (error == B_OK) { 2125 nubPort = create_port(1, nameBuffer); 2126 if (nubPort < 0) 2127 error = nubPort; 2128 else 2129 result = nubPort; 2130 } 2131 2132 // make the debugger team the port owner; thus we know, if the debugger is 2133 // gone and can cleanup 2134 if (error == B_OK) 2135 error = set_port_owner(nubPort, debuggerTeam); 2136 2137 // spawn the nub thread 2138 thread_id nubThread = -1; 2139 if (error == B_OK) { 2140 snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug task", teamID); 2141 nubThread = spawn_kernel_thread_etc(debug_nub_thread, nameBuffer, 2142 B_NORMAL_PRIORITY, NULL, teamID, -1); 2143 if (nubThread < 0) 2144 error = nubThread; 2145 } 2146 2147 // now adjust the debug info accordingly 2148 if (error == B_OK) { 2149 state = disable_interrupts(); 2150 GRAB_TEAM_LOCK(); 2151 2152 // look up again, to make sure the team isn't dying 2153 team = team_get_team_struct_locked(teamID); 2154 2155 if (team) { 2156 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2157 2158 if (team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 2159 // there's already a debugger installed 2160 error = (dontFail ? B_OK : B_BAD_VALUE); 2161 done = true; 2162 result = team->debug_info.nub_port; 2163 2164 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2165 } else { 2166 install_team_debugger_init_debug_infos(team, debuggerTeam, 2167 debuggerPort, nubPort, nubThread, debuggerWriteLock); 2168 } 2169 } else 2170 error = B_BAD_TEAM_ID; 2171 2172 RELEASE_TEAM_LOCK(); 2173 restore_interrupts(state); 2174 } 2175 2176 // if everything went fine, resume the nub thread, otherwise clean up 2177 if (error == B_OK && !done) { 2178 resume_thread(nubThread); 2179 } else { 2180 // delete port and terminate thread 2181 if (nubPort >= 0) { 2182 set_port_owner(nubPort, B_CURRENT_TEAM); 2183 delete_port(nubPort); 2184 } 2185 if (nubThread >= 0) { 2186 int32 result; 2187 wait_for_thread(nubThread, &result); 2188 } 2189 } 2190 2191 TRACE(("install_team_debugger() done2: %ld\n", 2192 (error == B_OK ? result : error))); 2193 return (error == B_OK ? result : error); 2194 } 2195 2196 2197 static status_t 2198 ensure_debugger_installed(team_id teamID, port_id *_port) 2199 { 2200 port_id port = install_team_debugger(teamID, -1, true, true); 2201 if (port < 0) 2202 return port; 2203 2204 if (_port) 2205 *_port = port; 2206 return B_OK; 2207 } 2208 2209 2210 // #pragma mark - 2211 2212 2213 void 2214 _user_debugger(const char *userMessage) 2215 { 2216 // install the default debugger, if there is none yet 2217 struct thread *thread = thread_get_current_thread(); 2218 port_id nubPort; 2219 status_t error = ensure_debugger_installed(B_CURRENT_TEAM, &nubPort); 2220 if (error != B_OK) { 2221 // time to commit suicide 2222 char buffer[128]; 2223 ssize_t length = user_strlcpy(buffer, userMessage, sizeof(buffer)); 2224 if (length >= 0) { 2225 dprintf("_user_debugger(): Failed to install debugger. Message is: " 2226 "`%s'\n", buffer); 2227 } else { 2228 dprintf("_user_debugger(): Failed to install debugger. Message is: " 2229 "%p (%s)\n", userMessage, strerror(length)); 2230 } 2231 _user_exit_team(1); 2232 } 2233 2234 // prepare the message 2235 debug_debugger_call message; 2236 message.message = (void*)userMessage; 2237 2238 thread_hit_debug_event(B_DEBUGGER_MESSAGE_DEBUGGER_CALL, &message, 2239 sizeof(message), true); 2240 } 2241 2242 2243 int 2244 _user_disable_debugger(int state) 2245 { 2246 struct team *team = thread_get_current_thread()->team; 2247 2248 cpu_status cpuState = disable_interrupts(); 2249 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2250 2251 int32 oldFlags; 2252 if (state) 2253 oldFlags = atomic_and(&team->debug_info.flags, ~B_TEAM_DEBUG_SIGNALS); 2254 else 2255 oldFlags = atomic_or(&team->debug_info.flags, B_TEAM_DEBUG_SIGNALS); 2256 2257 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2258 restore_interrupts(cpuState); 2259 2260 // TODO: Check, if the return value is really the old state. 2261 return !(oldFlags & B_TEAM_DEBUG_SIGNALS); 2262 } 2263 2264 2265 status_t 2266 _user_install_default_debugger(port_id debuggerPort) 2267 { 2268 // if supplied, check whether the port is a valid port 2269 if (debuggerPort >= 0) { 2270 port_info portInfo; 2271 status_t error = get_port_info(debuggerPort, &portInfo); 2272 if (error != B_OK) 2273 return error; 2274 2275 // the debugger team must not be the kernel team 2276 if (portInfo.team == team_get_kernel_team_id()) 2277 return B_NOT_ALLOWED; 2278 } 2279 2280 atomic_set(&sDefaultDebuggerPort, debuggerPort); 2281 2282 return B_OK; 2283 } 2284 2285 2286 port_id 2287 _user_install_team_debugger(team_id teamID, port_id debuggerPort) 2288 { 2289 return install_team_debugger(teamID, debuggerPort, false, false); 2290 } 2291 2292 2293 status_t 2294 _user_remove_team_debugger(team_id teamID) 2295 { 2296 struct team_debug_info info; 2297 2298 status_t error = B_OK; 2299 2300 cpu_status state = disable_interrupts(); 2301 GRAB_TEAM_LOCK(); 2302 2303 struct team *team = (teamID == B_CURRENT_TEAM 2304 ? thread_get_current_thread()->team 2305 : team_get_team_struct_locked(teamID)); 2306 2307 if (team) { 2308 GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2309 2310 if (team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) { 2311 // there's a debugger installed 2312 info = team->debug_info; 2313 clear_team_debug_info(&team->debug_info, false); 2314 } else { 2315 // no debugger installed 2316 error = B_BAD_VALUE; 2317 } 2318 2319 RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info); 2320 } else 2321 error = B_BAD_TEAM_ID; 2322 2323 RELEASE_TEAM_LOCK(); 2324 restore_interrupts(state); 2325 2326 // clean up the info, if there was a debugger installed 2327 if (error == B_OK) 2328 destroy_team_debug_info(&info); 2329 2330 return error; 2331 } 2332 2333 2334 status_t 2335 _user_debug_thread(thread_id threadID) 2336 { 2337 TRACE(("[%ld] _user_debug_thread(%ld)\n", find_thread(NULL), threadID)); 2338 2339 // tell the thread to stop as soon as possible 2340 status_t error = B_OK; 2341 cpu_status state = disable_interrupts(); 2342 GRAB_THREAD_LOCK(); 2343 2344 struct thread *thread = thread_get_thread_struct_locked(threadID); 2345 if (!thread) { 2346 // thread doesn't exist any longer 2347 error = B_BAD_THREAD_ID; 2348 } else if (thread->team == team_get_kernel_team()) { 2349 // we can't debug the kernel team 2350 error = B_NOT_ALLOWED; 2351 } else if (thread->debug_info.flags & B_THREAD_DEBUG_DYING) { 2352 // the thread is already dying -- too late to debug it 2353 error = B_BAD_THREAD_ID; 2354 } else if (thread->debug_info.flags & B_THREAD_DEBUG_NUB_THREAD) { 2355 // don't debug the nub thread 2356 error = B_NOT_ALLOWED; 2357 } else if (!(thread->debug_info.flags & B_THREAD_DEBUG_STOPPED)) { 2358 // set the flag that tells the thread to stop as soon as possible 2359 atomic_or(&thread->debug_info.flags, B_THREAD_DEBUG_STOP); 2360 2361 update_thread_user_debug_flag(thread); 2362 2363 switch (thread->state) { 2364 case B_THREAD_SUSPENDED: 2365 // thread suspended: wake it up 2366 scheduler_enqueue_in_run_queue(thread); 2367 break; 2368 2369 case B_THREAD_WAITING: 2370 // thread waiting: interrupt it 2371 if (thread->sem.blocking >= 0) 2372 sem_interrupt_thread(thread); 2373 else if (thread->condition_variable_entry) 2374 condition_variable_interrupt_thread(thread); 2375 break; 2376 } 2377 } 2378 2379 RELEASE_THREAD_LOCK(); 2380 restore_interrupts(state); 2381 2382 return error; 2383 } 2384 2385 2386 void 2387 _user_wait_for_debugger(void) 2388 { 2389 debug_thread_debugged message; 2390 thread_hit_debug_event(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, &message, 2391 sizeof(message), false); 2392 } 2393 2394 2395 status_t 2396 _user_set_debugger_breakpoint(void *address, uint32 type, int32 length, 2397 bool watchpoint) 2398 { 2399 // check the address and size 2400 if (address == NULL || !IS_USER_ADDRESS(address)) 2401 return B_BAD_ADDRESS; 2402 if (watchpoint && length < 0) 2403 return B_BAD_VALUE; 2404 2405 // check whether a debugger is installed already 2406 team_debug_info teamDebugInfo; 2407 get_team_debug_info(teamDebugInfo); 2408 if (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) 2409 return B_BAD_VALUE; 2410 2411 // We can't help it, here's a small but relatively harmless race condition, 2412 // since a debugger could be installed in the meantime. The worst case is 2413 // that we install a break/watchpoint the debugger doesn't know about. 2414 2415 // set the break/watchpoint 2416 status_t result; 2417 if (watchpoint) 2418 result = arch_set_watchpoint(address, type, length); 2419 else 2420 result = arch_set_breakpoint(address); 2421 2422 if (result == B_OK) 2423 update_threads_breakpoints_flag(); 2424 2425 return result; 2426 } 2427 2428 2429 status_t 2430 _user_clear_debugger_breakpoint(void *address, bool watchpoint) 2431 { 2432 // check the address 2433 if (address == NULL || !IS_USER_ADDRESS(address)) 2434 return B_BAD_ADDRESS; 2435 2436 // check whether a debugger is installed already 2437 team_debug_info teamDebugInfo; 2438 get_team_debug_info(teamDebugInfo); 2439 if (teamDebugInfo.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) 2440 return B_BAD_VALUE; 2441 2442 // We can't help it, here's a small but relatively harmless race condition, 2443 // since a debugger could be installed in the meantime. The worst case is 2444 // that we clear a break/watchpoint the debugger has just installed. 2445 2446 // clear the break/watchpoint 2447 status_t result; 2448 if (watchpoint) 2449 result = arch_clear_watchpoint(address); 2450 else 2451 result = arch_clear_breakpoint(address); 2452 2453 if (result == B_OK) 2454 update_threads_breakpoints_flag(); 2455 2456 return result; 2457 } 2458