1 /* 2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2010-2016, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include "LocalDebuggerInterface.h" 8 9 #include <new> 10 11 #include <stdio.h> 12 13 #include <Locker.h> 14 15 #include <AutoLocker.h> 16 #include <memory_private.h> 17 #include <OS.h> 18 #include <system_info.h> 19 #include <util/DoublyLinkedList.h> 20 #include <util/KMessage.h> 21 22 #include "debug_utils.h" 23 24 #include "ArchitectureX86.h" 25 #include "ArchitectureX8664.h" 26 #include "AreaInfo.h" 27 #include "AutoDeleter.h" 28 #include "CpuState.h" 29 #include "DebugEvent.h" 30 #include "ImageInfo.h" 31 #include "SemaphoreInfo.h" 32 #include "SymbolInfo.h" 33 #include "SystemInfo.h" 34 #include "TeamInfo.h" 35 #include "ThreadInfo.h" 36 37 38 // number of debug contexts the pool does initially create 39 static const int kInitialDebugContextCount = 3; 40 41 // maximum number of debug contexts in the pool 42 static const int kMaxDebugContextCount = 10; 43 44 45 // #pragma mark - LocalDebuggerInterface::DebugContext 46 47 struct LocalDebuggerInterface::DebugContext : debug_context, 48 DoublyLinkedListLinkImpl<DebugContext> { 49 DebugContext() 50 { 51 team = -1; 52 nub_port = -1; 53 reply_port = -1; 54 } 55 56 ~DebugContext() 57 { 58 if (reply_port >= 0) 59 destroy_debug_context(this); 60 } 61 62 status_t Init(team_id team, port_id nubPort) 63 { 64 return init_debug_context(this, team, nubPort); 65 } 66 67 void Close() 68 { 69 if (reply_port >= 0) { 70 destroy_debug_context(this); 71 team = -1; 72 nub_port = -1; 73 reply_port = -1; 74 } 75 } 76 }; 77 78 // #pragma mark - LocalDebuggerInterface::DebugContextPool 79 80 struct LocalDebuggerInterface::DebugContextPool { 81 DebugContextPool(team_id team, port_id nubPort) 82 : 83 fLock("debug context pool"), 84 fTeam(team), 85 fNubPort(nubPort), 86 fBlockSem(-1), 87 fContextCount(0), 88 fWaiterCount(0), 89 fClosed(false) 90 { 91 } 92 93 ~DebugContextPool() 94 { 95 AutoLocker<BLocker> locker(fLock); 96 97 while (DebugContext* context = fFreeContexts.RemoveHead()) 98 delete context; 99 100 if (fBlockSem >= 0) 101 delete_sem(fBlockSem); 102 } 103 104 status_t Init() 105 { 106 status_t error = fLock.InitCheck(); 107 if (error != B_OK) 108 return error; 109 110 fBlockSem = create_sem(0, "debug context pool block"); 111 if (fBlockSem < 0) 112 return fBlockSem; 113 114 for (int i = 0; i < kInitialDebugContextCount; i++) { 115 DebugContext* context; 116 error = _CreateDebugContext(context); 117 if (error != B_OK) 118 return error; 119 120 fFreeContexts.Add(context); 121 } 122 123 return B_OK; 124 } 125 126 void Close() 127 { 128 AutoLocker<BLocker> locker(fLock); 129 fClosed = true; 130 131 for (DebugContextList::Iterator it = fFreeContexts.GetIterator(); 132 DebugContext* context = it.Next();) { 133 context->Close(); 134 } 135 136 for (DebugContextList::Iterator it = fUsedContexts.GetIterator(); 137 DebugContext* context = it.Next();) { 138 context->Close(); 139 } 140 } 141 142 DebugContext* GetContext() 143 { 144 AutoLocker<BLocker> locker(fLock); 145 DebugContext* context = fFreeContexts.RemoveHead(); 146 147 if (context == NULL) { 148 if (fContextCount >= kMaxDebugContextCount 149 || _CreateDebugContext(context) != B_OK) { 150 // wait for a free context 151 while (context == NULL) { 152 fWaiterCount++; 153 locker.Unlock(); 154 while (acquire_sem(fBlockSem) != B_OK); 155 locker.Lock(); 156 context = fFreeContexts.RemoveHead(); 157 } 158 } 159 } 160 161 fUsedContexts.Add(context); 162 163 return context; 164 } 165 166 void PutContext(DebugContext* context) 167 { 168 AutoLocker<BLocker> locker(fLock); 169 fUsedContexts.Remove(context); 170 fFreeContexts.Add(context); 171 172 if (fWaiterCount > 0) 173 release_sem(fBlockSem); 174 } 175 176 private: 177 typedef DoublyLinkedList<DebugContext> DebugContextList; 178 179 private: 180 status_t _CreateDebugContext(DebugContext*& _context) 181 { 182 DebugContext* context = new(std::nothrow) DebugContext; 183 if (context == NULL) 184 return B_NO_MEMORY; 185 186 if (!fClosed) { 187 status_t error = context->Init(fTeam, fNubPort); 188 if (error != B_OK) { 189 delete context; 190 return error; 191 } 192 } 193 194 fContextCount++; 195 196 _context = context; 197 return B_OK; 198 } 199 200 private: 201 BLocker fLock; 202 team_id fTeam; 203 port_id fNubPort; 204 sem_id fBlockSem; 205 int32 fContextCount; 206 int32 fWaiterCount; 207 DebugContextList fFreeContexts; 208 DebugContextList fUsedContexts; 209 bool fClosed; 210 }; 211 212 213 struct LocalDebuggerInterface::DebugContextGetter { 214 DebugContextGetter(DebugContextPool* pool) 215 : 216 fPool(pool), 217 fContext(pool->GetContext()) 218 { 219 } 220 221 ~DebugContextGetter() 222 { 223 fPool->PutContext(fContext); 224 } 225 226 DebugContext* Context() const 227 { 228 return fContext; 229 } 230 231 private: 232 DebugContextPool* fPool; 233 DebugContext* fContext; 234 }; 235 236 // #pragma mark - LocalDebuggerInterface 237 238 LocalDebuggerInterface::LocalDebuggerInterface(team_id team) 239 : 240 DebuggerInterface(), 241 fTeamID(team), 242 fDebuggerPort(-1), 243 fNubPort(-1), 244 fDebugContextPool(NULL), 245 fArchitecture(NULL) 246 { 247 } 248 249 250 LocalDebuggerInterface::~LocalDebuggerInterface() 251 { 252 if (fArchitecture != NULL) 253 fArchitecture->ReleaseReference(); 254 255 Close(false); 256 257 delete fDebugContextPool; 258 } 259 260 261 status_t 262 LocalDebuggerInterface::Init() 263 { 264 // create the architecture 265 #if defined(ARCH_x86) 266 fArchitecture = new(std::nothrow) ArchitectureX86(this); 267 #elif defined(ARCH_x86_64) 268 fArchitecture = new(std::nothrow) ArchitectureX8664(this); 269 #else 270 return B_UNSUPPORTED; 271 #endif 272 273 if (fArchitecture == NULL) 274 return B_NO_MEMORY; 275 276 status_t error = fArchitecture->Init(); 277 if (error != B_OK) 278 return error; 279 280 // create debugger port 281 char buffer[128]; 282 snprintf(buffer, sizeof(buffer), "team %" B_PRId32 " debugger", fTeamID); 283 fDebuggerPort = create_port(100, buffer); 284 if (fDebuggerPort < 0) 285 return fDebuggerPort; 286 287 // install as team debugger 288 fNubPort = install_team_debugger(fTeamID, fDebuggerPort); 289 if (fNubPort < 0) 290 return fNubPort; 291 292 error = __start_watching_system(fTeamID, B_WATCH_SYSTEM_THREAD_PROPERTIES, 293 fDebuggerPort, 0); 294 if (error != B_OK) 295 return error; 296 297 // create debug context pool 298 fDebugContextPool = new(std::nothrow) DebugContextPool(fTeamID, fNubPort); 299 if (fDebugContextPool == NULL) 300 return B_NO_MEMORY; 301 302 error = fDebugContextPool->Init(); 303 if (error != B_OK) 304 return error; 305 306 return B_OK; 307 } 308 309 310 void 311 LocalDebuggerInterface::Close(bool killTeam) 312 { 313 if (killTeam) 314 kill_team(fTeamID); 315 else if (fNubPort >= 0) 316 remove_team_debugger(fTeamID); 317 318 if (fDebuggerPort >= 0) { 319 __stop_watching_system(fTeamID, B_WATCH_SYSTEM_THREAD_PROPERTIES, 320 fDebuggerPort, 0); 321 delete_port(fDebuggerPort); 322 } 323 324 fNubPort = -1; 325 fDebuggerPort = -1; 326 } 327 328 329 bool 330 LocalDebuggerInterface::Connected() const 331 { 332 return fNubPort >= 0; 333 } 334 335 336 team_id 337 LocalDebuggerInterface::TeamID() const 338 { 339 return fTeamID; 340 } 341 342 343 Architecture* 344 LocalDebuggerInterface::GetArchitecture() const 345 { 346 return fArchitecture; 347 } 348 349 350 status_t 351 LocalDebuggerInterface::GetNextDebugEvent(DebugEvent*& _event) 352 { 353 while (true) { 354 char buffer[2048]; 355 int32 messageCode; 356 ssize_t size = read_port(fDebuggerPort, &messageCode, buffer, 357 sizeof(buffer)); 358 if (size < 0) { 359 if (size == B_INTERRUPTED) 360 continue; 361 362 return size; 363 } 364 365 if (messageCode <= B_DEBUGGER_MESSAGE_HANDED_OVER) { 366 debug_debugger_message_data message; 367 memcpy(&message, buffer, size); 368 if (message.origin.team != fTeamID) 369 continue; 370 371 bool ignore = false; 372 status_t error = _CreateDebugEvent(messageCode, message, ignore, 373 _event); 374 if (error != B_OK) 375 return error; 376 377 if (ignore) { 378 if (message.origin.thread >= 0 && message.origin.nub_port >= 0) 379 error = continue_thread(message.origin.nub_port, 380 message.origin.thread); 381 if (error != B_OK) 382 return error; 383 continue; 384 } 385 386 return B_OK; 387 } 388 389 KMessage message; 390 size = message.SetTo(buffer); 391 if (size != B_OK) 392 return size; 393 return _GetNextSystemWatchEvent(_event, message); 394 } 395 396 return B_OK; 397 } 398 399 400 status_t 401 LocalDebuggerInterface::SetTeamDebuggingFlags(uint32 flags) 402 { 403 return set_team_debugging_flags(fNubPort, flags); 404 } 405 406 407 status_t 408 LocalDebuggerInterface::ContinueThread(thread_id thread) 409 { 410 return continue_thread(fNubPort, thread); 411 } 412 413 414 status_t 415 LocalDebuggerInterface::StopThread(thread_id thread) 416 { 417 return debug_thread(thread); 418 } 419 420 421 status_t 422 LocalDebuggerInterface::SingleStepThread(thread_id thread) 423 { 424 debug_nub_continue_thread continueMessage; 425 continueMessage.thread = thread; 426 continueMessage.handle_event = B_THREAD_DEBUG_HANDLE_EVENT; 427 continueMessage.single_step = true; 428 429 return write_port(fNubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD, 430 &continueMessage, sizeof(continueMessage)); 431 } 432 433 434 status_t 435 LocalDebuggerInterface::InstallBreakpoint(target_addr_t address) 436 { 437 DebugContextGetter contextGetter(fDebugContextPool); 438 439 debug_nub_set_breakpoint message; 440 message.reply_port = contextGetter.Context()->reply_port; 441 message.address = (void*)(addr_t)address; 442 443 debug_nub_set_breakpoint_reply reply; 444 445 status_t error = send_debug_message(contextGetter.Context(), 446 B_DEBUG_MESSAGE_SET_BREAKPOINT, &message, sizeof(message), &reply, 447 sizeof(reply)); 448 return error == B_OK ? reply.error : error; 449 } 450 451 452 status_t 453 LocalDebuggerInterface::UninstallBreakpoint(target_addr_t address) 454 { 455 debug_nub_clear_breakpoint message; 456 message.address = (void*)(addr_t)address; 457 458 return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_BREAKPOINT, 459 &message, sizeof(message)); 460 } 461 462 463 status_t 464 LocalDebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type, 465 int32 length) 466 { 467 DebugContextGetter contextGetter(fDebugContextPool); 468 469 debug_nub_set_watchpoint message; 470 message.reply_port = contextGetter.Context()->reply_port; 471 message.address = (void*)(addr_t)address; 472 message.type = type; 473 message.length = length; 474 475 debug_nub_set_watchpoint_reply reply; 476 477 status_t error = send_debug_message(contextGetter.Context(), 478 B_DEBUG_MESSAGE_SET_WATCHPOINT, &message, sizeof(message), &reply, 479 sizeof(reply)); 480 return error == B_OK ? reply.error : error; 481 } 482 483 484 status_t 485 LocalDebuggerInterface::UninstallWatchpoint(target_addr_t address) 486 { 487 DebugContextGetter contextGetter(fDebugContextPool); 488 489 debug_nub_clear_watchpoint message; 490 message.address = (void*)(addr_t)address; 491 492 return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_WATCHPOINT, 493 &message, sizeof(message)); 494 } 495 496 497 status_t 498 LocalDebuggerInterface::GetSystemInfo(SystemInfo& info) 499 { 500 system_info sysInfo; 501 status_t result = get_system_info(&sysInfo); 502 if (result != B_OK) 503 return result; 504 505 utsname name; 506 result = uname(&name); 507 if (result != B_OK) 508 return result; 509 510 info.SetTo(fTeamID, sysInfo, name); 511 return B_OK; 512 } 513 514 515 status_t 516 LocalDebuggerInterface::GetTeamInfo(TeamInfo& info) 517 { 518 team_info teamInfo; 519 status_t result = get_team_info(fTeamID, &teamInfo); 520 if (result != B_OK) 521 return result; 522 523 info.SetTo(fTeamID, teamInfo); 524 return B_OK; 525 } 526 527 528 status_t 529 LocalDebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos) 530 { 531 thread_info threadInfo; 532 int32 cookie = 0; 533 while (get_next_thread_info(fTeamID, &cookie, &threadInfo) == B_OK) { 534 ThreadInfo* info = new(std::nothrow) ThreadInfo(threadInfo.team, 535 threadInfo.thread, threadInfo.name); 536 if (info == NULL || !infos.AddItem(info)) { 537 delete info; 538 return B_NO_MEMORY; 539 } 540 } 541 542 return B_OK; 543 } 544 545 546 status_t 547 LocalDebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos) 548 { 549 // get the team's images 550 image_info imageInfo; 551 int32 cookie = 0; 552 while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) { 553 ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID, imageInfo.id, 554 imageInfo.name, imageInfo.type, (addr_t)imageInfo.text, 555 imageInfo.text_size, (addr_t)imageInfo.data, imageInfo.data_size); 556 if (info == NULL || !infos.AddItem(info)) { 557 delete info; 558 return B_NO_MEMORY; 559 } 560 } 561 562 return B_OK; 563 } 564 565 566 status_t 567 LocalDebuggerInterface::GetAreaInfos(BObjectList<AreaInfo>& infos) 568 { 569 // get the team's areas 570 area_info areaInfo; 571 ssize_t cookie = 0; 572 while (get_next_area_info(fTeamID, &cookie, &areaInfo) == B_OK) { 573 AreaInfo* info = new(std::nothrow) AreaInfo(fTeamID, areaInfo.area, 574 areaInfo.name, (addr_t)areaInfo.address, areaInfo.size, 575 areaInfo.ram_size, areaInfo.lock, areaInfo.protection); 576 if (info == NULL || !infos.AddItem(info)) { 577 delete info; 578 return B_NO_MEMORY; 579 } 580 } 581 582 return B_OK; 583 } 584 585 586 status_t 587 LocalDebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo>& infos) 588 { 589 // get the team's semaphores 590 sem_info semInfo; 591 int32 cookie = 0; 592 while (get_next_sem_info(fTeamID, &cookie, &semInfo) == B_OK) { 593 SemaphoreInfo* info = new(std::nothrow) SemaphoreInfo(fTeamID, 594 semInfo.sem, semInfo.name, semInfo.count, semInfo.latest_holder); 595 if (info == NULL || !infos.AddItem(info)) { 596 delete info; 597 return B_NO_MEMORY; 598 } 599 } 600 601 return B_OK; 602 } 603 604 605 status_t 606 LocalDebuggerInterface::GetSymbolInfos(team_id team, image_id image, 607 BObjectList<SymbolInfo>& infos) 608 { 609 // create a lookup context 610 debug_symbol_lookup_context* lookupContext; 611 status_t error = debug_create_symbol_lookup_context(team, image, 612 &lookupContext); 613 if (error != B_OK) 614 return error; 615 616 // create a symbol iterator 617 debug_symbol_iterator* iterator; 618 error = debug_create_image_symbol_iterator( 619 lookupContext, image, &iterator); 620 if (error != B_OK) { 621 debug_delete_symbol_lookup_context(lookupContext); 622 return error; 623 } 624 625 // get the symbols 626 char name[1024]; 627 int32 type; 628 void* address; 629 size_t size; 630 while (debug_next_image_symbol(iterator, name, sizeof(name), &type, 631 &address, &size) == B_OK) { 632 SymbolInfo* info = new(std::nothrow) SymbolInfo( 633 (target_addr_t)(addr_t)address, size, type, name); 634 if (info == NULL) 635 break; 636 if (!infos.AddItem(info)) { 637 delete info; 638 break; 639 } 640 } 641 642 // delete the symbol iterator and lookup context 643 debug_delete_symbol_iterator(iterator); 644 debug_delete_symbol_lookup_context(lookupContext); 645 646 return B_OK; 647 } 648 649 650 status_t 651 LocalDebuggerInterface::GetSymbolInfo(team_id team, image_id image, const char* name, 652 int32 symbolType, SymbolInfo& info) 653 { 654 // create a lookup context 655 debug_symbol_lookup_context* lookupContext; 656 status_t error = debug_create_symbol_lookup_context(team, image, 657 &lookupContext); 658 if (error != B_OK) 659 return error; 660 661 // try to get the symbol 662 void* foundAddress; 663 size_t foundSize; 664 int32 foundType; 665 error = debug_get_symbol(lookupContext, image, name, symbolType, 666 &foundAddress, &foundSize, &foundType); 667 if (error == B_OK) { 668 info.SetTo((target_addr_t)(addr_t)foundAddress, foundSize, foundType, 669 name); 670 } 671 672 // delete the lookup context 673 debug_delete_symbol_lookup_context(lookupContext); 674 675 return error; 676 } 677 678 679 status_t 680 LocalDebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info) 681 { 682 thread_info threadInfo; 683 status_t error = get_thread_info(thread, &threadInfo); 684 if (error != B_OK) 685 return error; 686 687 info.SetTo(threadInfo.team, threadInfo.thread, threadInfo.name); 688 return B_OK; 689 } 690 691 692 status_t 693 LocalDebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state) 694 { 695 debug_cpu_state debugState; 696 status_t error = _GetDebugCpuState(thread, debugState); 697 if (error != B_OK) 698 return error; 699 return fArchitecture->CreateCpuState(&debugState, sizeof(debug_cpu_state), 700 _state); 701 } 702 703 704 status_t 705 LocalDebuggerInterface::SetCpuState(thread_id thread, const CpuState* state) 706 { 707 debug_cpu_state debugState; 708 status_t error = _GetDebugCpuState(thread, debugState); 709 if (error != B_OK) 710 return error; 711 712 DebugContextGetter contextGetter(fDebugContextPool); 713 714 error = state->UpdateDebugState(&debugState, sizeof(debugState)); 715 if (error != B_OK) 716 return error; 717 718 debug_nub_set_cpu_state message; 719 message.thread = thread; 720 721 memcpy(&message.cpu_state, &debugState, sizeof(debugState)); 722 723 return send_debug_message(contextGetter.Context(), 724 B_DEBUG_MESSAGE_SET_CPU_STATE, &message, sizeof(message), NULL, 725 0); 726 } 727 728 729 status_t 730 LocalDebuggerInterface::GetCpuFeatures(uint32& flags) 731 { 732 return fArchitecture->GetCpuFeatures(flags); 733 } 734 735 736 status_t 737 LocalDebuggerInterface::WriteCoreFile(const char* path) 738 { 739 DebugContextGetter contextGetter(fDebugContextPool); 740 741 debug_nub_write_core_file_reply reply; 742 743 debug_nub_write_core_file message; 744 message.reply_port = contextGetter.Context()->reply_port; 745 strlcpy(message.path, path, sizeof(message.path)); 746 747 status_t error = send_debug_message(contextGetter.Context(), 748 B_DEBUG_WRITE_CORE_FILE, &message, sizeof(message), &reply, 749 sizeof(reply)); 750 if (error == B_OK) 751 error = reply.error; 752 753 return error; 754 } 755 756 757 status_t 758 LocalDebuggerInterface::GetMemoryProperties(target_addr_t address, 759 uint32& protection, uint32& locking) 760 { 761 return get_memory_properties(fTeamID, (const void *)address, 762 &protection, &locking); 763 } 764 765 766 ssize_t 767 LocalDebuggerInterface::ReadMemory(target_addr_t address, void* buffer, size_t size) 768 { 769 DebugContextGetter contextGetter(fDebugContextPool); 770 771 return debug_read_memory(contextGetter.Context(), 772 (const void*)(addr_t)address, buffer, size); 773 } 774 775 776 ssize_t 777 LocalDebuggerInterface::WriteMemory(target_addr_t address, void* buffer, 778 size_t size) 779 { 780 DebugContextGetter contextGetter(fDebugContextPool); 781 782 return debug_write_memory(contextGetter.Context(), 783 (const void*)address, buffer, size); 784 } 785 786 787 status_t 788 LocalDebuggerInterface::_CreateDebugEvent(int32 messageCode, 789 const debug_debugger_message_data& message, bool& _ignore, 790 DebugEvent*& _event) 791 { 792 DebugEvent* event = NULL; 793 794 switch (messageCode) { 795 case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: 796 event = new(std::nothrow) ThreadDebuggedEvent(message.origin.team, 797 message.origin.thread); 798 break; 799 case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: 800 event = new(std::nothrow) DebuggerCallEvent(message.origin.team, 801 message.origin.thread, 802 (target_addr_t)message.debugger_call.message); 803 break; 804 case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: 805 { 806 CpuState* state = NULL; 807 status_t error = fArchitecture->CreateCpuState( 808 &message.breakpoint_hit.cpu_state, 809 sizeof(debug_cpu_state), state); 810 if (error != B_OK) 811 return error; 812 813 event = new(std::nothrow) BreakpointHitEvent(message.origin.team, 814 message.origin.thread, state); 815 state->ReleaseReference(); 816 break; 817 } 818 case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: 819 { 820 CpuState* state = NULL; 821 status_t error = fArchitecture->CreateCpuState( 822 &message.watchpoint_hit.cpu_state, 823 sizeof(debug_cpu_state), state); 824 if (error != B_OK) 825 return error; 826 827 event = new(std::nothrow) WatchpointHitEvent(message.origin.team, 828 message.origin.thread, state); 829 state->ReleaseReference(); 830 break; 831 } 832 case B_DEBUGGER_MESSAGE_SINGLE_STEP: 833 { 834 CpuState* state = NULL; 835 status_t error = fArchitecture->CreateCpuState( 836 &message.single_step.cpu_state, 837 sizeof(debug_cpu_state), state); 838 if (error != B_OK) 839 return error; 840 841 event = new(std::nothrow) SingleStepEvent(message.origin.team, 842 message.origin.thread, state); 843 state->ReleaseReference(); 844 break; 845 } 846 case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: 847 event = new(std::nothrow) ExceptionOccurredEvent( 848 message.origin.team, message.origin.thread, 849 message.exception_occurred.exception); 850 break; 851 case B_DEBUGGER_MESSAGE_TEAM_DELETED: 852 if (message.origin.team != fTeamID) { 853 _ignore = true; 854 return B_OK; 855 } 856 event = new(std::nothrow) TeamDeletedEvent(message.origin.team, 857 message.origin.thread); 858 break; 859 case B_DEBUGGER_MESSAGE_TEAM_EXEC: 860 if (message.origin.team != fTeamID) { 861 _ignore = true; 862 return B_OK; 863 } 864 event = new(std::nothrow) TeamExecEvent(message.origin.team, 865 message.origin.thread); 866 break; 867 case B_DEBUGGER_MESSAGE_THREAD_CREATED: 868 event = new(std::nothrow) ThreadCreatedEvent(message.origin.team, 869 message.origin.thread, message.thread_created.new_thread); 870 break; 871 case B_DEBUGGER_MESSAGE_THREAD_DELETED: 872 event = new(std::nothrow) ThreadDeletedEvent(message.origin.team, 873 message.origin.thread); 874 break; 875 case B_DEBUGGER_MESSAGE_IMAGE_CREATED: 876 { 877 const image_info& info = message.image_created.info; 878 event = new(std::nothrow) ImageCreatedEvent(message.origin.team, 879 message.origin.thread, 880 ImageInfo(fTeamID, info.id, info.name, info.type, 881 (addr_t)info.text, info.text_size, (addr_t)info.data, 882 info.data_size)); 883 break; 884 } 885 case B_DEBUGGER_MESSAGE_IMAGE_DELETED: 886 { 887 const image_info& info = message.image_deleted.info; 888 event = new(std::nothrow) ImageDeletedEvent(message.origin.team, 889 message.origin.thread, 890 ImageInfo(fTeamID, info.id, info.name, info.type, 891 (addr_t)info.text, info.text_size, (addr_t)info.data, 892 info.data_size)); 893 break; 894 } 895 case B_DEBUGGER_MESSAGE_POST_SYSCALL: 896 { 897 event = new(std::nothrow) PostSyscallEvent(message.origin.team, 898 message.origin.thread, 899 SyscallInfo(message.post_syscall.start_time, 900 message.post_syscall.end_time, 901 message.post_syscall.return_value, 902 message.post_syscall.syscall, message.post_syscall.args)); 903 break; 904 } 905 case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: 906 { 907 event = new(std::nothrow) SignalReceivedEvent(message.origin.team, 908 message.origin.thread, 909 SignalInfo(message.signal_received.signal, 910 message.signal_received.handler, 911 message.signal_received.deadly)); 912 break; 913 } 914 default: 915 printf("DebuggerInterface for team %" B_PRId32 ": unknown message " 916 "from kernel: %" B_PRId32 "\n", fTeamID, messageCode); 917 // fall through... 918 case B_DEBUGGER_MESSAGE_TEAM_CREATED: 919 case B_DEBUGGER_MESSAGE_PRE_SYSCALL: 920 case B_DEBUGGER_MESSAGE_PROFILER_UPDATE: 921 case B_DEBUGGER_MESSAGE_HANDED_OVER: 922 _ignore = true; 923 return B_OK; 924 } 925 926 if (event == NULL) 927 return B_NO_MEMORY; 928 929 if (message.origin.thread >= 0 && message.origin.nub_port >= 0) 930 event->SetThreadStopped(true); 931 932 _ignore = false; 933 _event = event; 934 935 return B_OK; 936 } 937 938 939 status_t 940 LocalDebuggerInterface::_GetNextSystemWatchEvent(DebugEvent*& _event, 941 KMessage& message) 942 { 943 status_t error = B_OK; 944 if (message.What() != B_SYSTEM_OBJECT_UPDATE) 945 return B_BAD_DATA; 946 947 int32 opcode = 0; 948 if (message.FindInt32("opcode", &opcode) != B_OK) 949 return B_BAD_DATA; 950 951 DebugEvent* event = NULL; 952 switch (opcode) 953 { 954 case B_THREAD_NAME_CHANGED: 955 { 956 int32 threadID = -1; 957 if (message.FindInt32("thread", &threadID) != B_OK) 958 break; 959 960 thread_info info; 961 error = get_thread_info(threadID, &info); 962 if (error != B_OK) 963 break; 964 965 event = new(std::nothrow) ThreadRenamedEvent(fTeamID, 966 threadID, threadID, info.name); 967 break; 968 } 969 970 default: 971 { 972 error = B_BAD_DATA; 973 break; 974 } 975 } 976 977 if (event != NULL) 978 _event = event; 979 980 return error; 981 } 982 983 984 status_t 985 LocalDebuggerInterface::_GetDebugCpuState(thread_id thread, debug_cpu_state& _state) 986 { 987 DebugContextGetter contextGetter(fDebugContextPool); 988 989 debug_nub_get_cpu_state message; 990 message.reply_port = contextGetter.Context()->reply_port; 991 message.thread = thread; 992 993 debug_nub_get_cpu_state_reply reply; 994 995 status_t error = send_debug_message(contextGetter.Context(), 996 B_DEBUG_MESSAGE_GET_CPU_STATE, &message, sizeof(message), &reply, 997 sizeof(reply)); 998 if (error != B_OK) 999 return error; 1000 if (reply.error != B_OK) 1001 return reply.error; 1002 1003 memcpy(&_state, &reply.cpu_state, sizeof(debug_cpu_state)); 1004 1005 return B_OK; 1006 } 1007