2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2010-2017, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
8 #include "controllers/TeamDebugger.h"
16 #include <InterfaceDefs.h>
18 #include <StringList.h>
20 #include <AutoDeleter.h>
21 #include <AutoLocker.h>
23 #include "debug_utils.h"
24 #include "syscall_numbers.h"
26 #include "Architecture.h"
27 #include "BreakpointManager.h"
28 #include "BreakpointSetting.h"
30 #include "DebugEvent.h"
31 #include "DebuggerInterface.h"
32 #include "DebugReportGenerator.h"
33 #include "ExpressionInfo.h"
34 #include "FileManager.h"
36 #include "FunctionID.h"
37 #include "ImageDebugInfo.h"
38 #include "ImageDebugInfoLoadingState.h"
39 #include "ImageDebugLoadingStateHandler.h"
40 #include "ImageDebugLoadingStateHandlerRoster.h"
42 #include "LocatableFile.h"
43 #include "MessageCodes.h"
44 #include "NoOpSettingsManager.h"
45 #include "SettingsManager.h"
46 #include "SourceCode.h"
47 #include "SourceLanguage.h"
48 #include "SpecificImageDebugInfo.h"
49 #include "SpecificImageDebugInfoLoadingState.h"
50 #include "StackFrame.h"
51 #include "StackFrameValues.h"
52 #include "Statement.h"
53 #include "SymbolInfo.h"
54 #include "TeamDebugInfo.h"
56 #include "TeamMemoryBlock.h"
57 #include "TeamMemoryBlockManager.h"
58 #include "TeamSettings.h"
59 #include "TeamSignalSettings.h"
60 #include "TeamUiSettings.h"
62 #include "ValueNode.h"
63 #include "ValueNodeContainer.h"
65 #include "WatchpointManager.h"
68 // #pragma mark - ImageHandler
71 struct TeamDebugger::ImageHandler
: public BReferenceable
,
72 private LocatableFile::Listener
{
74 ImageHandler(TeamDebugger
* teamDebugger
, Image
* image
)
76 fTeamDebugger(teamDebugger
),
79 fImage
->AcquireReference();
80 if (fImage
->ImageFile() != NULL
)
81 fImage
->ImageFile()->AddListener(this);
86 if (fImage
->ImageFile() != NULL
)
87 fImage
->ImageFile()->RemoveListener(this);
88 fImage
->ReleaseReference();
91 Image
* GetImage() const
96 image_id
ImageID() const
102 // LocatableFile::Listener
103 virtual void LocatableFileChanged(LocatableFile
* file
)
105 BMessage
message(MSG_IMAGE_FILE_CHANGED
);
106 message
.AddInt32("image", fImage
->ID());
107 fTeamDebugger
->PostMessage(&message
);
111 TeamDebugger
* fTeamDebugger
;
119 // #pragma mark - ImageHandlerHashDefinition
122 struct TeamDebugger::ImageHandlerHashDefinition
{
123 typedef image_id KeyType
;
124 typedef ImageHandler ValueType
;
126 size_t HashKey(image_id key
) const
131 size_t Hash(const ImageHandler
* value
) const
133 return HashKey(value
->ImageID());
136 bool Compare(image_id key
, const ImageHandler
* value
) const
138 return value
->ImageID() == key
;
141 ImageHandler
*& GetLink(ImageHandler
* value
) const
148 // #pragma mark - ImageInfoPendingThread
151 struct TeamDebugger::ImageInfoPendingThread
{
153 ImageInfoPendingThread(image_id image
, thread_id thread
)
160 ~ImageInfoPendingThread()
164 image_id
ImageID() const
169 thread_id
ThreadID() const
179 ImageInfoPendingThread
* fNext
;
183 // #pragma mark - ImageHandlerHashDefinition
186 struct TeamDebugger::ImageInfoPendingThreadHashDefinition
{
187 typedef image_id KeyType
;
188 typedef ImageInfoPendingThread ValueType
;
190 size_t HashKey(image_id key
) const
195 size_t Hash(const ImageInfoPendingThread
* value
) const
197 return HashKey(value
->ImageID());
200 bool Compare(image_id key
, const ImageInfoPendingThread
* value
) const
202 return value
->ImageID() == key
;
205 ImageInfoPendingThread
*& GetLink(ImageInfoPendingThread
* value
) const
212 // #pragma mark - TeamDebugger
215 TeamDebugger::TeamDebugger(Listener
* listener
, UserInterface
* userInterface
,
216 SettingsManager
* settingsManager
)
218 BLooper("team debugger"),
220 fSettingsManager(settingsManager
),
223 fIsPostMortem(false),
224 fImageHandlers(NULL
),
225 fImageInfoPendingThreads(NULL
),
226 fDebuggerInterface(NULL
),
229 fBreakpointManager(NULL
),
230 fWatchpointManager(NULL
),
231 fMemoryBlockManager(NULL
),
232 fReportGenerator(NULL
),
233 fDebugEventListener(-1),
234 fUserInterface(userInterface
),
236 fKillTeamOnQuit(false),
238 fCommandLineArgv(NULL
),
241 fUserInterface
->AcquireReference();
245 TeamDebugger::~TeamDebugger()
250 AutoLocker
<BLooper
> locker(this);
254 if (fDebuggerInterface
!= NULL
) {
255 fDebuggerInterface
->Close(fKillTeamOnQuit
);
256 fDebuggerInterface
->ReleaseReference();
264 if (fDebugEventListener
>= 0)
265 wait_for_thread(fDebugEventListener
, NULL
);
268 if (fUserInterface
!= NULL
) {
269 fUserInterface
->Terminate();
270 fUserInterface
->ReleaseReference();
273 ThreadHandler
* threadHandler
= fThreadHandlers
.Clear(true);
274 while (threadHandler
!= NULL
) {
275 ThreadHandler
* next
= threadHandler
->fNext
;
276 threadHandler
->ReleaseReference();
277 threadHandler
= next
;
280 if (fImageHandlers
!= NULL
) {
281 ImageHandler
* imageHandler
= fImageHandlers
->Clear(true);
282 while (imageHandler
!= NULL
) {
283 ImageHandler
* next
= imageHandler
->fNext
;
284 imageHandler
->ReleaseReference();
289 delete fImageHandlers
;
291 if (fImageInfoPendingThreads
!= NULL
) {
292 ImageInfoPendingThread
* thread
= fImageInfoPendingThreads
->Clear(true);
293 while (thread
!= NULL
) {
294 ImageInfoPendingThread
* next
= thread
->fNext
;
300 if (fReportGenerator
!= NULL
) {
301 fReportGenerator
->Lock();
302 fReportGenerator
->Quit();
307 delete fImageInfoPendingThreads
;
309 delete fBreakpointManager
;
310 delete fWatchpointManager
;
311 delete fMemoryBlockManager
;
315 for (int i
= 0; i
< fCommandLineArgc
; i
++) {
316 if (fCommandLineArgv
[i
] != NULL
)
317 free(const_cast<char*>(fCommandLineArgv
[i
]));
320 delete [] fCommandLineArgv
;
322 fListener
->TeamDebuggerQuit(this);
327 TeamDebugger::Init(DebuggerInterface
* interface
, thread_id threadID
, int argc
,
328 const char* const* argv
, bool stopInMain
)
330 bool targetIsLocal
= true;
331 // TODO: Support non-local targets!
333 // the first thing we want to do when running
334 PostMessage(MSG_LOAD_SETTINGS
);
336 status_t error
= _HandleSetArguments(argc
, argv
);
340 if (fSettingsManager
== NULL
) {
341 // if we have not been provided with a settings manager,
342 // simply use the no-op manager by default.
343 fSettingsManager
= new(std::nothrow
) NoOpSettingsManager
;
344 if (fSettingsManager
== NULL
)
348 fDebuggerInterface
= interface
;
349 fDebuggerInterface
->AcquireReference();
350 fTeamID
= interface
->TeamID();
351 fIsPostMortem
= interface
->IsPostMortem();
354 // create file manager
355 fFileManager
= new(std::nothrow
) FileManager
;
356 if (fFileManager
== NULL
)
359 error
= fFileManager
->Init(targetIsLocal
);
363 // create team debug info
364 TeamDebugInfo
* teamDebugInfo
= new(std::nothrow
) TeamDebugInfo(
365 fDebuggerInterface
, fDebuggerInterface
->GetArchitecture(),
367 if (teamDebugInfo
== NULL
)
369 BReference
<TeamDebugInfo
> teamDebugInfoReference(teamDebugInfo
, true);
371 error
= teamDebugInfo
->Init();
375 // check whether the team exists at all
377 error
= fDebuggerInterface
->GetTeamInfo(teamInfo
);
381 // create a team object
382 fTeam
= new(std::nothrow
) ::Team(fTeamID
, fDebuggerInterface
,
383 fDebuggerInterface
->GetArchitecture(), teamDebugInfo
,
388 error
= fTeam
->Init();
391 fTeam
->SetName(teamInfo
.Arguments());
392 // TODO: Set a better name!
394 fTeam
->AddListener(this);
396 // init thread handler table
397 error
= fThreadHandlers
.Init();
401 // create image handler table
402 fImageHandlers
= new(std::nothrow
) ImageHandlerTable
;
403 if (fImageHandlers
== NULL
)
406 error
= fImageHandlers
->Init();
410 fImageInfoPendingThreads
= new(std::nothrow
) ImageInfoPendingThreadTable
;
411 if (fImageInfoPendingThreads
== NULL
)
415 fWorker
= new(std::nothrow
) Worker
;
419 error
= fWorker
->Init();
423 // create the breakpoint manager
424 fBreakpointManager
= new(std::nothrow
) BreakpointManager(fTeam
,
426 if (fBreakpointManager
== NULL
)
429 error
= fBreakpointManager
->Init();
433 // create the watchpoint manager
434 fWatchpointManager
= new(std::nothrow
) WatchpointManager(fTeam
,
436 if (fWatchpointManager
== NULL
)
439 error
= fWatchpointManager
->Init();
443 // create the memory block manager
444 fMemoryBlockManager
= new(std::nothrow
) TeamMemoryBlockManager();
445 if (fMemoryBlockManager
== NULL
)
448 error
= fMemoryBlockManager
->Init();
452 // create the debug report generator
453 fReportGenerator
= new(std::nothrow
) DebugReportGenerator(fTeam
, this,
455 if (fReportGenerator
== NULL
)
458 error
= fReportGenerator
->Init();
462 // set team debugging flags
463 fDebuggerInterface
->SetTeamDebuggingFlags(
464 B_TEAM_DEBUG_THREADS
| B_TEAM_DEBUG_IMAGES
465 | B_TEAM_DEBUG_POST_SYSCALL
| B_TEAM_DEBUG_SIGNALS
466 | B_TEAM_DEBUG_TEAM_CREATION
);
468 // get the initial state of the team
469 AutoLocker
< ::Team
> teamLocker(fTeam
);
471 ThreadHandler
* mainThreadHandler
= NULL
;
473 BObjectList
<ThreadInfo
> threadInfos(20, true);
474 status_t error
= fDebuggerInterface
->GetThreadInfos(threadInfos
);
475 for (int32 i
= 0; ThreadInfo
* info
= threadInfos
.ItemAt(i
); i
++) {
477 error
= fTeam
->AddThread(*info
, &thread
);
481 ThreadHandler
* handler
= new(std::nothrow
) ThreadHandler(thread
,
482 fWorker
, fDebuggerInterface
, this, fBreakpointManager
);
486 fThreadHandlers
.Insert(handler
);
488 if (thread
->IsMainThread())
489 mainThreadHandler
= handler
;
495 Image
* appImage
= NULL
;
497 BObjectList
<ImageInfo
> imageInfos(20, true);
498 status_t error
= fDebuggerInterface
->GetImageInfos(imageInfos
);
499 for (int32 i
= 0; ImageInfo
* info
= imageInfos
.ItemAt(i
); i
++) {
501 error
= _AddImage(*info
, &image
);
504 if (image
->Type() == B_APP_IMAGE
)
507 ImageDebugInfoRequested(image
);
511 // create the debug event listener (for live debugging only)
512 if (!fDebuggerInterface
->IsPostMortem()) {
514 snprintf(buffer
, sizeof(buffer
), "team %" B_PRId32
" debug listener",
516 fDebugEventListener
= spawn_thread(_DebugEventListenerEntry
, buffer
,
517 B_NORMAL_PRIORITY
, this);
518 if (fDebugEventListener
< 0)
519 return fDebugEventListener
;
521 resume_thread(fDebugEventListener
);
525 thread_id looperThread
= Run();
526 if (looperThread
< 0)
530 error
= fUserInterface
->Init(fTeam
, this);
532 ERROR("Error: Failed to init the UI: %s\n", strerror(error
));
536 // if requested, stop the given thread
537 if (threadID
>= 0 && !fDebuggerInterface
->IsPostMortem()) {
539 SymbolInfo symbolInfo
;
540 if (appImage
!= NULL
&& mainThreadHandler
!= NULL
541 && fDebuggerInterface
->GetSymbolInfo(
542 fTeam
->ID(), appImage
->ID(), "main", B_SYMBOL_TYPE_TEXT
,
543 symbolInfo
) == B_OK
) {
544 mainThreadHandler
->SetBreakpointAndRun(symbolInfo
.Address());
547 debug_thread(threadID
);
548 // TODO: Superfluous, if the thread is already stopped.
552 fListener
->TeamDebuggerStarted(this);
559 TeamDebugger::Activate()
561 fUserInterface
->Show();
566 TeamDebugger::MessageReceived(BMessage
* message
)
568 switch (message
->what
) {
570 case MSG_THREAD_SET_ADDRESS
:
571 case MSG_THREAD_STOP
:
572 case MSG_THREAD_STEP_OVER
:
573 case MSG_THREAD_STEP_INTO
:
574 case MSG_THREAD_STEP_OUT
:
577 target_addr_t address
;
578 if (message
->FindInt32("thread", &threadID
) != B_OK
)
581 if (message
->FindUInt64("address", &address
) != B_OK
)
584 if (ThreadHandler
* handler
= _GetThreadHandler(threadID
)) {
585 handler
->HandleThreadAction(message
->what
, address
);
586 handler
->ReleaseReference();
591 case MSG_SET_BREAKPOINT
:
592 case MSG_CLEAR_BREAKPOINT
:
594 UserBreakpoint
* breakpoint
= NULL
;
595 BReference
<UserBreakpoint
> breakpointReference
;
598 if (message
->FindPointer("breakpoint", (void**)&breakpoint
)
600 breakpointReference
.SetTo(breakpoint
, true);
601 } else if (message
->FindUInt64("address", &address
) != B_OK
)
604 if (message
->what
== MSG_SET_BREAKPOINT
) {
606 if (message
->FindBool("enabled", &enabled
) != B_OK
)
610 if (message
->FindBool("hidden", &hidden
) != B_OK
)
613 if (breakpoint
!= NULL
)
614 _HandleSetUserBreakpoint(breakpoint
, enabled
);
616 _HandleSetUserBreakpoint(address
, enabled
, hidden
);
618 if (breakpoint
!= NULL
)
619 _HandleClearUserBreakpoint(breakpoint
);
621 _HandleClearUserBreakpoint(address
);
627 case MSG_SET_BREAKPOINT_CONDITION
:
629 UserBreakpoint
* breakpoint
= NULL
;
630 BReference
<UserBreakpoint
> breakpointReference
;
631 if (message
->FindPointer("breakpoint", (void**)&breakpoint
)
636 breakpointReference
.SetTo(breakpoint
, true);
638 const char* condition
;
639 if (message
->FindString("condition", &condition
) != B_OK
)
642 AutoLocker
< ::Team
> teamLocker(fTeam
);
643 breakpoint
->SetCondition(condition
);
644 fTeam
->NotifyUserBreakpointChanged(breakpoint
);
649 case MSG_CLEAR_BREAKPOINT_CONDITION
:
651 UserBreakpoint
* breakpoint
= NULL
;
652 BReference
<UserBreakpoint
> breakpointReference
;
653 if (message
->FindPointer("breakpoint", (void**)&breakpoint
)
657 breakpointReference
.SetTo(breakpoint
, true);
659 AutoLocker
< ::Team
> teamLocker(fTeam
);
660 breakpoint
->SetCondition(NULL
);
661 fTeam
->NotifyUserBreakpointChanged(breakpoint
);
666 case MSG_STOP_ON_IMAGE_LOAD
:
670 if (message
->FindBool("enabled", &enabled
) != B_OK
)
673 if (message
->FindBool("useNames", &useNames
) != B_OK
)
676 AutoLocker
< ::Team
> teamLocker(fTeam
);
677 fTeam
->SetStopOnImageLoad(enabled
, useNames
);
681 case MSG_ADD_STOP_IMAGE_NAME
:
684 if (message
->FindString("name", &imageName
) != B_OK
)
687 AutoLocker
< ::Team
> teamLocker(fTeam
);
688 fTeam
->AddStopImageName(imageName
);
692 case MSG_REMOVE_STOP_IMAGE_NAME
:
695 if (message
->FindString("name", &imageName
) != B_OK
)
698 AutoLocker
< ::Team
> teamLocker(fTeam
);
699 fTeam
->RemoveStopImageName(imageName
);
703 case MSG_SET_DEFAULT_SIGNAL_DISPOSITION
:
706 if (message
->FindInt32("disposition", &disposition
) != B_OK
)
709 AutoLocker
< ::Team
> teamLocker(fTeam
);
710 fTeam
->SetDefaultSignalDisposition(disposition
);
714 case MSG_SET_CUSTOM_SIGNAL_DISPOSITION
:
718 if (message
->FindInt32("signal", &signal
) != B_OK
719 || message
->FindInt32("disposition", &disposition
) != B_OK
) {
723 AutoLocker
< ::Team
> teamLocker(fTeam
);
724 fTeam
->SetCustomSignalDisposition(signal
, disposition
);
728 case MSG_REMOVE_CUSTOM_SIGNAL_DISPOSITION
:
731 if (message
->FindInt32("signal", &signal
) != B_OK
)
734 AutoLocker
< ::Team
> teamLocker(fTeam
);
735 fTeam
->RemoveCustomSignalDisposition(signal
);
739 case MSG_SET_WATCHPOINT
:
740 case MSG_CLEAR_WATCHPOINT
:
742 Watchpoint
* watchpoint
= NULL
;
743 BReference
<Watchpoint
> watchpointReference
;
748 if (message
->FindPointer("watchpoint", (void**)&watchpoint
)
750 watchpointReference
.SetTo(watchpoint
, true);
751 } else if (message
->FindUInt64("address", &address
) != B_OK
)
754 if (message
->what
== MSG_SET_WATCHPOINT
) {
755 if (watchpoint
== NULL
&& (message
->FindUInt32("type", &type
)
757 || message
->FindInt32("length", &length
) != B_OK
)) {
762 if (message
->FindBool("enabled", &enabled
) != B_OK
)
765 if (watchpoint
!= NULL
)
766 _HandleSetWatchpoint(watchpoint
, enabled
);
768 _HandleSetWatchpoint(address
, type
, length
, enabled
);
770 if (watchpoint
!= NULL
)
771 _HandleClearWatchpoint(watchpoint
);
773 _HandleClearWatchpoint(address
);
779 case MSG_INSPECT_ADDRESS
:
781 TeamMemoryBlock::Listener
* listener
;
782 if (message
->FindPointer("listener",
783 reinterpret_cast<void **>(&listener
)) != B_OK
) {
787 target_addr_t address
;
788 if (message
->FindUInt64("address",
790 _HandleInspectAddress(address
, listener
);
795 case MSG_WRITE_TARGET_MEMORY
:
797 target_addr_t address
;
798 if (message
->FindUInt64("address", &address
) != B_OK
)
802 if (message
->FindPointer("data", &data
) != B_OK
)
806 if (message
->FindUInt64("size", &size
) != B_OK
)
809 _HandleWriteMemory(address
, data
, size
);
813 case MSG_EVALUATE_EXPRESSION
:
815 SourceLanguage
* language
;
816 if (message
->FindPointer("language",
817 reinterpret_cast<void**>(&language
)) != B_OK
) {
821 // ExpressionEvaluationRequested() acquires a reference
822 // to both the language and the expression info on our behalf.
823 BReference
<SourceLanguage
> reference(language
, true);
825 ExpressionInfo
* info
;
826 if (message
->FindPointer("info",
827 reinterpret_cast<void**>(&info
)) != B_OK
) {
831 BReference
<ExpressionInfo
> infoReference(info
, true);
834 if (message
->FindPointer("frame",
835 reinterpret_cast<void**>(&frame
)) != B_OK
) {
836 // the stack frame isn't needed, unless variable
837 // evaluation is desired.
842 if (message
->FindPointer("thread",
843 reinterpret_cast<void**>(&thread
)) != B_OK
) {
844 // the thread isn't needed, unless variable
845 // evaluation is desired.
849 _HandleEvaluateExpression(language
, info
, frame
, thread
);
853 case MSG_GENERATE_DEBUG_REPORT
:
855 fReportGenerator
->PostMessage(message
);
859 case MSG_WRITE_CORE_FILE
:
862 if (message
->FindRef("target", &ref
) != B_OK
)
865 _HandleWriteCoreFile(ref
);
869 case MSG_THREAD_STATE_CHANGED
:
872 if (message
->FindInt32("thread", &threadID
) != B_OK
)
875 if (ThreadHandler
* handler
= _GetThreadHandler(threadID
)) {
876 handler
->HandleThreadStateChanged();
877 handler
->ReleaseReference();
881 case MSG_THREAD_CPU_STATE_CHANGED
:
884 if (message
->FindInt32("thread", &threadID
) != B_OK
)
887 if (ThreadHandler
* handler
= _GetThreadHandler(threadID
)) {
888 handler
->HandleCpuStateChanged();
889 handler
->ReleaseReference();
893 case MSG_THREAD_STACK_TRACE_CHANGED
:
896 if (message
->FindInt32("thread", &threadID
) != B_OK
)
899 if (ThreadHandler
* handler
= _GetThreadHandler(threadID
)) {
900 handler
->HandleStackTraceChanged();
901 handler
->ReleaseReference();
906 case MSG_IMAGE_DEBUG_INFO_CHANGED
:
909 if (message
->FindInt32("image", &imageID
) != B_OK
)
912 _HandleImageDebugInfoChanged(imageID
);
916 case MSG_IMAGE_FILE_CHANGED
:
919 if (message
->FindInt32("image", &imageID
) != B_OK
)
922 _HandleImageFileChanged(imageID
);
926 case MSG_DEBUGGER_EVENT
:
929 if (message
->FindPointer("event", (void**)&event
) != B_OK
)
932 _HandleDebuggerMessage(event
);
937 case MSG_LOAD_SETTINGS
:
942 case MSG_TEAM_RESTART_REQUESTED
:
944 if (fCommandLineArgc
== 0)
948 fListener
->TeamDebuggerRestartRequested(this);
952 case MSG_DEBUG_INFO_NEEDS_USER_INPUT
:
955 ImageDebugInfoLoadingState
* state
;
956 if (message
->FindPointer("job", (void**)&job
) != B_OK
)
958 if (message
->FindPointer("state", (void**)&state
) != B_OK
)
961 _HandleDebugInfoJobUserInput(state
);
962 fWorker
->ResumeJob(job
);
967 BLooper::MessageReceived(message
);
974 TeamDebugger::SourceEntryLocateRequested(const char* sourcePath
,
975 const char* locatedPath
)
977 AutoLocker
<FileManager
> locker(fFileManager
);
978 fFileManager
->SourceEntryLocated(sourcePath
, locatedPath
);
983 TeamDebugger::SourceEntryInvalidateRequested(LocatableFile
* sourceFile
)
985 AutoLocker
< ::Team
> locker(fTeam
);
987 fTeam
->DebugInfo()->ClearSourceCode(sourceFile
);
992 TeamDebugger::FunctionSourceCodeRequested(FunctionInstance
* functionInstance
,
993 bool forceDisassembly
)
995 Function
* function
= functionInstance
->GetFunction();
998 AutoLocker
< ::Team
> locker(fTeam
);
1000 if (forceDisassembly
&& functionInstance
->SourceCodeState()
1001 != FUNCTION_SOURCE_NOT_LOADED
) {
1003 } else if (!forceDisassembly
&& function
->SourceCodeState()
1004 == FUNCTION_SOURCE_LOADED
) {
1008 functionInstance
->SetSourceCode(NULL
, FUNCTION_SOURCE_LOADING
);
1010 bool loadForFunction
= false;
1011 if (!forceDisassembly
&& (function
->SourceCodeState()
1012 == FUNCTION_SOURCE_NOT_LOADED
1013 || function
->SourceCodeState() == FUNCTION_SOURCE_SUPPRESSED
)) {
1014 loadForFunction
= true;
1015 function
->SetSourceCode(NULL
, FUNCTION_SOURCE_LOADING
);
1021 if (fWorker
->ScheduleJob(
1022 new(std::nothrow
) LoadSourceCodeJob(fDebuggerInterface
,
1023 fDebuggerInterface
->GetArchitecture(), fTeam
, functionInstance
,
1026 // scheduling failed -- mark unavailable
1028 function
->SetSourceCode(NULL
, FUNCTION_SOURCE_UNAVAILABLE
);
1035 TeamDebugger::ImageDebugInfoRequested(Image
* image
)
1037 LoadImageDebugInfoJob::ScheduleIfNecessary(fWorker
, image
, this);
1042 TeamDebugger::ValueNodeValueRequested(CpuState
* cpuState
,
1043 ValueNodeContainer
* container
, ValueNode
* valueNode
)
1045 AutoLocker
<ValueNodeContainer
> containerLocker(container
);
1046 if (valueNode
->Container() != container
)
1049 // check whether a job is already in progress
1050 AutoLocker
<Worker
> workerLocker(fWorker
);
1051 SimpleJobKey
jobKey(valueNode
, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE
);
1052 if (fWorker
->GetJob(jobKey
) != NULL
)
1054 workerLocker
.Unlock();
1057 status_t error
= fWorker
->ScheduleJob(
1058 new(std::nothrow
) ResolveValueNodeValueJob(fDebuggerInterface
,
1059 fDebuggerInterface
->GetArchitecture(), cpuState
,
1060 fTeam
->GetTeamTypeInformation(), container
, valueNode
), this);
1061 if (error
!= B_OK
) {
1062 // scheduling failed -- set the value to invalid
1063 valueNode
->SetLocationAndValue(NULL
, NULL
, error
);
1068 TeamDebugger::ValueNodeWriteRequested(ValueNode
* node
, CpuState
* state
,
1072 status_t error
= fWorker
->ScheduleJob(
1073 new(std::nothrow
) WriteValueNodeValueJob(fDebuggerInterface
,
1074 fDebuggerInterface
->GetArchitecture(), state
,
1075 fTeam
->GetTeamTypeInformation(), node
, newValue
), this);
1076 if (error
!= B_OK
) {
1078 message
.SetToFormat("Request to write new value for variable %s "
1079 "failed: %s.\n", node
->Name().String(), strerror(error
));
1080 fUserInterface
->NotifyUser("Error", message
.String(),
1081 USER_NOTIFICATION_ERROR
);
1087 TeamDebugger::ThreadActionRequested(thread_id threadID
,
1088 uint32 action
, target_addr_t address
)
1090 BMessage
message(action
);
1091 message
.AddInt32("thread", threadID
);
1092 message
.AddUInt64("address", address
);
1093 PostMessage(&message
);
1098 TeamDebugger::SetBreakpointRequested(target_addr_t address
, bool enabled
,
1101 BMessage
message(MSG_SET_BREAKPOINT
);
1102 message
.AddUInt64("address", (uint64
)address
);
1103 message
.AddBool("enabled", enabled
);
1104 message
.AddBool("hidden", hidden
);
1105 PostMessage(&message
);
1110 TeamDebugger::SetBreakpointEnabledRequested(UserBreakpoint
* breakpoint
,
1113 BMessage
message(MSG_SET_BREAKPOINT
);
1114 BReference
<UserBreakpoint
> breakpointReference(breakpoint
);
1115 if (message
.AddPointer("breakpoint", breakpoint
) == B_OK
1116 && message
.AddBool("enabled", enabled
) == B_OK
1117 && PostMessage(&message
) == B_OK
) {
1118 breakpointReference
.Detach();
1124 TeamDebugger::SetBreakpointConditionRequested(UserBreakpoint
* breakpoint
,
1125 const char* condition
)
1127 BMessage
message(MSG_SET_BREAKPOINT_CONDITION
);
1128 BReference
<UserBreakpoint
> breakpointReference(breakpoint
);
1129 if (message
.AddPointer("breakpoint", breakpoint
) == B_OK
1130 && message
.AddString("condition", condition
) == B_OK
1131 && PostMessage(&message
) == B_OK
) {
1132 breakpointReference
.Detach();
1138 TeamDebugger::ClearBreakpointConditionRequested(UserBreakpoint
* breakpoint
)
1140 BMessage
message(MSG_CLEAR_BREAKPOINT_CONDITION
);
1141 BReference
<UserBreakpoint
> breakpointReference(breakpoint
);
1142 if (message
.AddPointer("breakpoint", breakpoint
) == B_OK
1143 && PostMessage(&message
) == B_OK
) {
1144 breakpointReference
.Detach();
1150 TeamDebugger::ClearBreakpointRequested(target_addr_t address
)
1152 BMessage
message(MSG_CLEAR_BREAKPOINT
);
1153 message
.AddUInt64("address", (uint64
)address
);
1154 PostMessage(&message
);
1159 TeamDebugger::SetStopOnImageLoadRequested(bool enabled
, bool useImageNames
)
1161 BMessage
message(MSG_STOP_ON_IMAGE_LOAD
);
1162 message
.AddBool("enabled", enabled
);
1163 message
.AddBool("useNames", useImageNames
);
1164 PostMessage(&message
);
1169 TeamDebugger::AddStopImageNameRequested(const char* name
)
1171 BMessage
message(MSG_ADD_STOP_IMAGE_NAME
);
1172 message
.AddString("name", name
);
1173 PostMessage(&message
);
1178 TeamDebugger::RemoveStopImageNameRequested(const char* name
)
1180 BMessage
message(MSG_REMOVE_STOP_IMAGE_NAME
);
1181 message
.AddString("name", name
);
1182 PostMessage(&message
);
1187 TeamDebugger::SetDefaultSignalDispositionRequested(int32 disposition
)
1189 BMessage
message(MSG_SET_DEFAULT_SIGNAL_DISPOSITION
);
1190 message
.AddInt32("disposition", disposition
);
1191 PostMessage(&message
);
1196 TeamDebugger::SetCustomSignalDispositionRequested(int32 signal
,
1199 BMessage
message(MSG_SET_CUSTOM_SIGNAL_DISPOSITION
);
1200 message
.AddInt32("signal", signal
);
1201 message
.AddInt32("disposition", disposition
);
1202 PostMessage(&message
);
1207 TeamDebugger::RemoveCustomSignalDispositionRequested(int32 signal
)
1209 BMessage
message(MSG_REMOVE_CUSTOM_SIGNAL_DISPOSITION
);
1210 message
.AddInt32("signal", signal
);
1211 PostMessage(&message
);
1216 TeamDebugger::ClearBreakpointRequested(UserBreakpoint
* breakpoint
)
1218 BMessage
message(MSG_CLEAR_BREAKPOINT
);
1219 BReference
<UserBreakpoint
> breakpointReference(breakpoint
);
1220 if (message
.AddPointer("breakpoint", breakpoint
) == B_OK
1221 && PostMessage(&message
) == B_OK
) {
1222 breakpointReference
.Detach();
1228 TeamDebugger::SetWatchpointRequested(target_addr_t address
, uint32 type
,
1229 int32 length
, bool enabled
)
1231 BMessage
message(MSG_SET_WATCHPOINT
);
1232 message
.AddUInt64("address", (uint64
)address
);
1233 message
.AddUInt32("type", type
);
1234 message
.AddInt32("length", length
);
1235 message
.AddBool("enabled", enabled
);
1236 PostMessage(&message
);
1241 TeamDebugger::SetWatchpointEnabledRequested(Watchpoint
* watchpoint
,
1244 BMessage
message(MSG_SET_WATCHPOINT
);
1245 BReference
<Watchpoint
> watchpointReference(watchpoint
);
1246 if (message
.AddPointer("watchpoint", watchpoint
) == B_OK
1247 && message
.AddBool("enabled", enabled
) == B_OK
1248 && PostMessage(&message
) == B_OK
) {
1249 watchpointReference
.Detach();
1255 TeamDebugger::ClearWatchpointRequested(target_addr_t address
)
1257 BMessage
message(MSG_CLEAR_WATCHPOINT
);
1258 message
.AddUInt64("address", (uint64
)address
);
1259 PostMessage(&message
);
1264 TeamDebugger::ClearWatchpointRequested(Watchpoint
* watchpoint
)
1266 BMessage
message(MSG_CLEAR_WATCHPOINT
);
1267 BReference
<Watchpoint
> watchpointReference(watchpoint
);
1268 if (message
.AddPointer("watchpoint", watchpoint
) == B_OK
1269 && PostMessage(&message
) == B_OK
) {
1270 watchpointReference
.Detach();
1276 TeamDebugger::InspectRequested(target_addr_t address
,
1277 TeamMemoryBlock::Listener
*listener
)
1279 BMessage
message(MSG_INSPECT_ADDRESS
);
1280 message
.AddUInt64("address", address
);
1281 message
.AddPointer("listener", listener
);
1282 PostMessage(&message
);
1287 TeamDebugger::MemoryWriteRequested(target_addr_t address
, const void* data
,
1290 BMessage
message(MSG_WRITE_TARGET_MEMORY
);
1291 message
.AddUInt64("address", address
);
1292 message
.AddPointer("data", data
);
1293 message
.AddUInt64("size", size
);
1294 PostMessage(&message
);
1299 TeamDebugger::ExpressionEvaluationRequested(SourceLanguage
* language
,
1300 ExpressionInfo
* info
, StackFrame
* frame
, ::Thread
* thread
)
1302 BMessage
message(MSG_EVALUATE_EXPRESSION
);
1303 message
.AddPointer("language", language
);
1304 message
.AddPointer("info", info
);
1306 message
.AddPointer("frame", frame
);
1308 message
.AddPointer("thread", thread
);
1310 BReference
<SourceLanguage
> languageReference(language
);
1311 BReference
<ExpressionInfo
> infoReference(info
);
1312 if (PostMessage(&message
) == B_OK
) {
1313 languageReference
.Detach();
1314 infoReference
.Detach();
1320 TeamDebugger::DebugReportRequested(entry_ref
* targetPath
)
1322 BMessage
message(MSG_GENERATE_DEBUG_REPORT
);
1323 message
.AddRef("target", targetPath
);
1324 PostMessage(&message
);
1329 TeamDebugger::WriteCoreFileRequested(entry_ref
* targetPath
)
1331 BMessage
message(MSG_WRITE_CORE_FILE
);
1332 message
.AddRef("target", targetPath
);
1333 PostMessage(&message
);
1338 TeamDebugger::TeamRestartRequested()
1340 PostMessage(MSG_TEAM_RESTART_REQUESTED
);
1345 TeamDebugger::UserInterfaceQuitRequested(QuitOption quitOption
)
1347 bool askUser
= false;
1348 switch (quitOption
) {
1349 case QUIT_OPTION_ASK_USER
:
1353 case QUIT_OPTION_ASK_KILL_TEAM
:
1354 fKillTeamOnQuit
= true;
1357 case QUIT_OPTION_ASK_RESUME_TEAM
:
1362 AutoLocker
< ::Team
> locker(fTeam
);
1363 BString
name(fTeam
->Name());
1367 message
<< "What shall be done about the debugged team '";
1371 name
.Remove(0, name
.FindLast('/') + 1);
1373 BString
killLabel("Kill ");
1376 BString
resumeLabel("Resume ");
1377 resumeLabel
<< name
;
1379 int32 choice
= fUserInterface
->SynchronouslyAskUser("Quit Debugger",
1380 message
, killLabel
, "Cancel", resumeLabel
);
1384 fKillTeamOnQuit
= true;
1390 // Detach from the team and resume and stopped threads.
1395 PostMessage(B_QUIT_REQUESTED
);
1402 TeamDebugger::JobStarted(Job
* job
)
1404 BString
description(job
->GetDescription());
1405 if (!description
.IsEmpty()) {
1406 description
.Append(B_UTF8_ELLIPSIS
);
1407 fUserInterface
->NotifyBackgroundWorkStatus(description
.String());
1413 TeamDebugger::JobDone(Job
* job
)
1415 TRACE_JOBS("TeamDebugger::JobDone(%p)\n", job
);
1416 _ResetUserBackgroundStatusIfNeeded();
1421 TeamDebugger::JobWaitingForInput(Job
* job
)
1423 LoadImageDebugInfoJob
* infoJob
= dynamic_cast<LoadImageDebugInfoJob
*>(job
);
1425 if (infoJob
== NULL
)
1428 BMessage
message(MSG_DEBUG_INFO_NEEDS_USER_INPUT
);
1429 message
.AddPointer("job", infoJob
);
1430 message
.AddPointer("state", infoJob
->GetLoadingState());
1431 PostMessage(&message
);
1436 TeamDebugger::JobFailed(Job
* job
)
1438 TRACE_JOBS("TeamDebugger::JobFailed(%p)\n", job
);
1439 // TODO: notify user
1440 _ResetUserBackgroundStatusIfNeeded();
1445 TeamDebugger::JobAborted(Job
* job
)
1447 TRACE_JOBS("TeamDebugger::JobAborted(%p)\n", job
);
1448 // TODO: For a stack frame source loader thread we should reset the
1449 // loading state! Asynchronously due to locking order.
1450 _ResetUserBackgroundStatusIfNeeded();
1455 TeamDebugger::ThreadStateChanged(const ::Team::ThreadEvent
& event
)
1457 BMessage
message(MSG_THREAD_STATE_CHANGED
);
1458 message
.AddInt32("thread", event
.GetThread()->ID());
1459 PostMessage(&message
);
1464 TeamDebugger::ThreadCpuStateChanged(const ::Team::ThreadEvent
& event
)
1466 BMessage
message(MSG_THREAD_CPU_STATE_CHANGED
);
1467 message
.AddInt32("thread", event
.GetThread()->ID());
1468 PostMessage(&message
);
1473 TeamDebugger::ThreadStackTraceChanged(const ::Team::ThreadEvent
& event
)
1475 BMessage
message(MSG_THREAD_STACK_TRACE_CHANGED
);
1476 message
.AddInt32("thread", event
.GetThread()->ID());
1477 PostMessage(&message
);
1482 TeamDebugger::ImageDebugInfoChanged(const ::Team::ImageEvent
& event
)
1484 BMessage
message(MSG_IMAGE_DEBUG_INFO_CHANGED
);
1485 message
.AddInt32("image", event
.GetImage()->ID());
1486 PostMessage(&message
);
1491 TeamDebugger::_DebugEventListenerEntry(void* data
)
1493 return ((TeamDebugger
*)data
)->_DebugEventListener();
1498 TeamDebugger::_DebugEventListener()
1500 while (!fTerminating
) {
1501 // get the next event
1503 status_t error
= fDebuggerInterface
->GetNextDebugEvent(event
);
1506 // TODO: Error handling!
1508 if (event
->Team() != fTeamID
) {
1509 TRACE_EVENTS("TeamDebugger for team %" B_PRId32
": received event "
1510 "from team %" B_PRId32
"!\n", fTeamID
, event
->Team());
1514 BMessage
message(MSG_DEBUGGER_EVENT
);
1515 if (message
.AddPointer("event", event
) != B_OK
1516 || PostMessage(&message
) != B_OK
) {
1517 // TODO: Continue thread if necessary!
1527 TeamDebugger::_HandleDebuggerMessage(DebugEvent
* event
)
1529 TRACE_EVENTS("TeamDebugger::_HandleDebuggerMessage(): %" B_PRId32
"\n",
1530 event
->EventType());
1532 bool handled
= false;
1534 ThreadHandler
* handler
= _GetThreadHandler(event
->Thread());
1535 BReference
<ThreadHandler
> handlerReference(handler
, true);
1537 switch (event
->EventType()) {
1538 case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED
:
1539 TRACE_EVENTS("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %"
1540 B_PRId32
"\n", event
->Thread());
1542 if (handler
!= NULL
) {
1543 handled
= handler
->HandleThreadDebugged(
1544 dynamic_cast<ThreadDebuggedEvent
*>(event
));
1547 case B_DEBUGGER_MESSAGE_DEBUGGER_CALL
:
1548 TRACE_EVENTS("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %" B_PRId32
1549 "\n", event
->Thread());
1551 if (handler
!= NULL
) {
1552 handled
= handler
->HandleDebuggerCall(
1553 dynamic_cast<DebuggerCallEvent
*>(event
));
1556 case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT
:
1557 TRACE_EVENTS("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %" B_PRId32
1558 "\n", event
->Thread());
1560 if (handler
!= NULL
) {
1561 handled
= handler
->HandleBreakpointHit(
1562 dynamic_cast<BreakpointHitEvent
*>(event
));
1565 case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT
:
1566 TRACE_EVENTS("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %" B_PRId32
1567 "\n", event
->Thread());
1569 if (handler
!= NULL
) {
1570 handled
= handler
->HandleWatchpointHit(
1571 dynamic_cast<WatchpointHitEvent
*>(event
));
1574 case B_DEBUGGER_MESSAGE_SINGLE_STEP
:
1575 TRACE_EVENTS("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %" B_PRId32
1576 "\n", event
->Thread());
1578 if (handler
!= NULL
) {
1579 handled
= handler
->HandleSingleStep(
1580 dynamic_cast<SingleStepEvent
*>(event
));
1583 case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED
:
1584 TRACE_EVENTS("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %"
1585 B_PRId32
"\n", event
->Thread());
1587 if (handler
!= NULL
) {
1588 handled
= handler
->HandleExceptionOccurred(
1589 dynamic_cast<ExceptionOccurredEvent
*>(event
));
1592 // case B_DEBUGGER_MESSAGE_TEAM_CREATED:
1593 //printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team);
1595 case B_DEBUGGER_MESSAGE_TEAM_DELETED
:
1597 TRACE_EVENTS("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %" B_PRId32
1598 "\n", event
->Team());
1599 TeamDeletedEvent
* teamEvent
1600 = dynamic_cast<TeamDeletedEvent
*>(event
);
1601 handled
= _HandleTeamDeleted(teamEvent
);
1604 case B_DEBUGGER_MESSAGE_TEAM_EXEC
:
1606 TRACE_EVENTS("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %" B_PRId32
"\n",
1609 TeamExecEvent
* teamEvent
1610 = dynamic_cast<TeamExecEvent
*>(event
);
1611 _PrepareForTeamExec(teamEvent
);
1614 case B_DEBUGGER_MESSAGE_THREAD_CREATED
:
1616 ThreadCreatedEvent
* threadEvent
1617 = dynamic_cast<ThreadCreatedEvent
*>(event
);
1618 TRACE_EVENTS("B_DEBUGGER_MESSAGE_THREAD_CREATED: thread: %" B_PRId32
1619 "\n", threadEvent
->NewThread());
1620 handled
= _HandleThreadCreated(threadEvent
);
1623 case DEBUGGER_MESSAGE_THREAD_RENAMED
:
1625 ThreadRenamedEvent
* threadEvent
1626 = dynamic_cast<ThreadRenamedEvent
*>(event
);
1627 TRACE_EVENTS("DEBUGGER_MESSAGE_THREAD_RENAMED: thread: %" B_PRId32
1629 threadEvent
->RenamedThread(), threadEvent
->NewName());
1630 handled
= _HandleThreadRenamed(threadEvent
);
1633 case DEBUGGER_MESSAGE_THREAD_PRIORITY_CHANGED
:
1635 ThreadPriorityChangedEvent
* threadEvent
1636 = dynamic_cast<ThreadPriorityChangedEvent
*>(event
);
1637 TRACE_EVENTS("B_DEBUGGER_MESSAGE_THREAD_PRIORITY_CHANGED: thread:"
1638 " %" B_PRId32
"\n", threadEvent
->ChangedThread());
1639 handled
= _HandleThreadPriorityChanged(threadEvent
);
1642 case B_DEBUGGER_MESSAGE_THREAD_DELETED
:
1643 TRACE_EVENTS("B_DEBUGGER_MESSAGE_THREAD_DELETED: thread: %" B_PRId32
1644 "\n", event
->Thread());
1645 handled
= _HandleThreadDeleted(
1646 dynamic_cast<ThreadDeletedEvent
*>(event
));
1648 case B_DEBUGGER_MESSAGE_IMAGE_CREATED
:
1650 ImageCreatedEvent
* imageEvent
1651 = dynamic_cast<ImageCreatedEvent
*>(event
);
1652 TRACE_EVENTS("B_DEBUGGER_MESSAGE_IMAGE_CREATED: image: \"%s\" "
1653 "(%" B_PRId32
")\n", imageEvent
->GetImageInfo().Name().String(),
1654 imageEvent
->GetImageInfo().ImageID());
1655 handled
= _HandleImageCreated(imageEvent
);
1658 case B_DEBUGGER_MESSAGE_IMAGE_DELETED
:
1660 ImageDeletedEvent
* imageEvent
1661 = dynamic_cast<ImageDeletedEvent
*>(event
);
1662 TRACE_EVENTS("B_DEBUGGER_MESSAGE_IMAGE_DELETED: image: \"%s\" "
1663 "(%" B_PRId32
")\n", imageEvent
->GetImageInfo().Name().String(),
1664 imageEvent
->GetImageInfo().ImageID());
1665 handled
= _HandleImageDeleted(imageEvent
);
1668 case B_DEBUGGER_MESSAGE_POST_SYSCALL
:
1670 PostSyscallEvent
* postSyscallEvent
1671 = dynamic_cast<PostSyscallEvent
*>(event
);
1672 TRACE_EVENTS("B_DEBUGGER_MESSAGE_POST_SYSCALL: syscall: %"
1673 B_PRIu32
"\n", postSyscallEvent
->GetSyscallInfo().Syscall());
1674 handled
= _HandlePostSyscall(postSyscallEvent
);
1676 // if a thread was blocked in a syscall when we requested to
1677 // stop it for debugging, then that request will interrupt
1678 // said call, and the post syscall event will be all we get
1679 // in response. Consequently, we need to treat this case as
1680 // equivalent to having received a thread debugged event.
1681 AutoLocker
< ::Team
> teamLocker(fTeam
);
1682 ::Thread
* thread
= fTeam
->ThreadByID(event
->Thread());
1683 if (handler
!= NULL
&& thread
!= NULL
1684 && thread
->StopRequestPending()) {
1685 handled
= handler
->HandleThreadDebugged(NULL
);
1689 case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED
:
1691 TRACE_EVENTS("B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: thread: %"
1692 B_PRId32
"\n", event
->Thread());
1694 if (handler
!= NULL
) {
1695 handled
= handler
->HandleSignalReceived(
1696 dynamic_cast<SignalReceivedEvent
*>(event
));
1700 case B_DEBUGGER_MESSAGE_PRE_SYSCALL
:
1701 case B_DEBUGGER_MESSAGE_PROFILER_UPDATE
:
1702 case B_DEBUGGER_MESSAGE_HANDED_OVER
:
1706 WARNING("TeamDebugger for team %" B_PRId32
": unknown event type: "
1707 "%" B_PRId32
"\n", fTeamID
, event
->EventType());
1711 if (!handled
&& event
->ThreadStopped())
1712 fDebuggerInterface
->ContinueThread(event
->Thread());
1717 TeamDebugger::_HandleTeamDeleted(TeamDeletedEvent
* event
)
1720 fDebuggerInterface
->Close(false);
1722 snprintf(message
, sizeof(message
), "Team %" B_PRId32
" has terminated. ",
1725 int32 result
= fUserInterface
->SynchronouslyAskUser("Team terminated",
1726 message
, "Do nothing", "Quit", fCommandLineArgc
!= 0
1727 ? "Restart team" : NULL
);
1733 PostMessage(B_QUIT_REQUESTED
);
1739 fListener
->TeamDebuggerRestartRequested(this);
1751 TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent
* event
)
1753 AutoLocker
< ::Team
> locker(fTeam
);
1756 status_t error
= fDebuggerInterface
->GetThreadInfo(event
->NewThread(),
1758 if (error
== B_OK
) {
1760 fTeam
->AddThread(info
, &thread
);
1762 ThreadHandler
* handler
= new(std::nothrow
) ThreadHandler(thread
,
1763 fWorker
, fDebuggerInterface
, this, fBreakpointManager
);
1764 if (handler
!= NULL
) {
1765 fThreadHandlers
.Insert(handler
);
1775 TeamDebugger::_HandleThreadRenamed(ThreadRenamedEvent
* event
)
1777 AutoLocker
< ::Team
> locker(fTeam
);
1779 ::Thread
* thread
= fTeam
->ThreadByID(event
->RenamedThread());
1782 thread
->SetName(event
->NewName());
1789 TeamDebugger::_HandleThreadPriorityChanged(ThreadPriorityChangedEvent
*)
1791 // TODO: implement once we actually track thread priorities
1798 TeamDebugger::_HandleThreadDeleted(ThreadDeletedEvent
* event
)
1800 AutoLocker
< ::Team
> locker(fTeam
);
1801 if (ThreadHandler
* handler
= fThreadHandlers
.Lookup(event
->Thread())) {
1802 fThreadHandlers
.Remove(handler
);
1803 handler
->ReleaseReference();
1805 fTeam
->RemoveThread(event
->Thread());
1811 TeamDebugger::_HandleImageCreated(ImageCreatedEvent
* event
)
1813 AutoLocker
< ::Team
> locker(fTeam
);
1814 _AddImage(event
->GetImageInfo());
1816 ImageInfoPendingThread
* info
= new(std::nothrow
) ImageInfoPendingThread(
1817 event
->GetImageInfo().ImageID(), event
->Thread());
1821 fImageInfoPendingThreads
->Insert(info
);
1827 TeamDebugger::_HandleImageDeleted(ImageDeletedEvent
* event
)
1829 AutoLocker
< ::Team
> locker(fTeam
);
1830 fTeam
->RemoveImage(event
->GetImageInfo().ImageID());
1832 ImageHandler
* imageHandler
= fImageHandlers
->Lookup(
1833 event
->GetImageInfo().ImageID());
1834 if (imageHandler
== NULL
)
1837 fImageHandlers
->Remove(imageHandler
);
1838 BReference
<ImageHandler
> imageHandlerReference(imageHandler
, true);
1841 // remove breakpoints in the image
1842 fBreakpointManager
->RemoveImageBreakpoints(imageHandler
->GetImage());
1849 TeamDebugger::_HandlePostSyscall(PostSyscallEvent
* event
)
1851 const SyscallInfo
& info
= event
->GetSyscallInfo();
1853 switch (info
.Syscall()) {
1856 if ((ssize_t
)info
.ReturnValue() <= 0)
1860 target_addr_t address
;
1862 // TODO: decoding the syscall arguments should probably be
1863 // factored out into an Architecture method of its own, since
1864 // there's no guarantee the target architecture has the same
1865 // endianness as the host. This could re-use the syscall
1866 // argument parser that strace uses, though that would need to
1867 // be adapted to handle the aforementioned endian differences.
1868 // This works for x86{-64} for now though.
1869 if (fTeam
->GetArchitecture()->AddressSize() == 4) {
1870 const uint32
* args
= (const uint32
*)info
.Arguments();
1875 const uint64
* args
= (const uint64
*)info
.Arguments();
1881 if (fd
== 1 || fd
== 2) {
1884 ssize_t result
= fDebuggerInterface
->ReadMemoryString(
1885 address
, size
, data
);
1887 fTeam
->NotifyConsoleOutputReceived(fd
, data
);
1891 case SYSCALL_WRITEV
:
1904 TeamDebugger::_PrepareForTeamExec(TeamExecEvent
* event
)
1906 // NB: must be called with team lock held.
1910 // when notified of exec, we need to clear out data related
1912 const ImageList
& images
= fTeam
->Images();
1914 for (ImageList::ConstIterator it
= images
.GetIterator();
1915 Image
* image
= it
.Next();) {
1916 fBreakpointManager
->RemoveImageBreakpoints(image
);
1919 BObjectList
<UserBreakpoint
> breakpointsToRemove(20, false);
1920 const UserBreakpointList
& breakpoints
= fTeam
->UserBreakpoints();
1921 for (UserBreakpointList::ConstIterator it
= breakpoints
.GetIterator();
1922 UserBreakpoint
* breakpoint
= it
.Next();) {
1923 breakpointsToRemove
.AddItem(breakpoint
);
1924 breakpoint
->AcquireReference();
1927 for (int32 i
= 0; i
< breakpointsToRemove
.CountItems(); i
++) {
1928 UserBreakpoint
* breakpoint
= breakpointsToRemove
.ItemAt(i
);
1929 fTeam
->RemoveUserBreakpoint(breakpoint
);
1930 fTeam
->NotifyUserBreakpointChanged(breakpoint
);
1931 breakpoint
->ReleaseReference();
1934 fTeam
->ClearImages();
1935 fTeam
->ClearSignalDispositionMappings();
1936 fExecPending
= true;
1941 TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID
)
1943 // get the image (via the image handler)
1944 AutoLocker
< ::Team
> locker(fTeam
);
1945 ImageHandler
* imageHandler
= fImageHandlers
->Lookup(imageID
);
1946 if (imageHandler
== NULL
)
1949 Image
* image
= imageHandler
->GetImage();
1950 BReference
<Image
> imageReference(image
);
1951 image_debug_info_state state
= image
->ImageDebugInfoState();
1953 bool handlePostExecSetup
= fExecPending
&& image
->Type() == B_APP_IMAGE
1954 && state
!= IMAGE_DEBUG_INFO_LOADING
;
1955 // this needs to be done first so that breakpoints are loaded.
1956 // otherwise, UpdateImageBreakpoints() won't find the appropriate
1957 // UserBreakpoints to create/install instances for.
1958 if (handlePostExecSetup
) {
1959 fTeam
->SetName(image
->Name());
1961 fExecPending
= false;
1966 if (state
== IMAGE_DEBUG_INFO_LOADED
1967 || state
== IMAGE_DEBUG_INFO_UNAVAILABLE
) {
1969 // update breakpoints in the image
1970 fBreakpointManager
->UpdateImageBreakpoints(image
);
1972 ImageInfoPendingThread
* thread
= fImageInfoPendingThreads
1974 if (thread
!= NULL
) {
1975 fImageInfoPendingThreads
->Remove(thread
);
1976 ObjectDeleter
<ImageInfoPendingThread
> threadDeleter(thread
);
1978 ThreadHandler
* handler
= _GetThreadHandler(thread
->ThreadID());
1979 BReference
<ThreadHandler
> handlerReference(handler
, true);
1980 if (fTeam
->StopOnImageLoad()) {
1983 const BString
& imageName
= image
->Name();
1984 // only match on the image filename itself
1985 const char* rawImageName
= imageName
.String()
1986 + imageName
.FindLast('/') + 1;
1987 if (fTeam
->StopImageNameListEnabled()) {
1988 const BStringList
& nameList
= fTeam
->StopImageNames();
1989 stop
= nameList
.HasString(rawImageName
);
1992 if (stop
&& handler
!= NULL
) {
1994 stopReason
.SetToFormat("Image '%s' loaded.",
1998 if (handler
->HandleThreadDebugged(NULL
, stopReason
))
2002 } else if (handlePostExecSetup
) {
2003 // in the case of an exec(), we can't stop in main() until
2004 // the new app image has been loaded, so we know where to
2005 // set the main breakpoint at.
2006 SymbolInfo symbolInfo
;
2007 if (fDebuggerInterface
->GetSymbolInfo(fTeam
->ID(), image
->ID(),
2008 "main", B_SYMBOL_TYPE_TEXT
, symbolInfo
) == B_OK
) {
2009 handler
->SetBreakpointAndRun(symbolInfo
.Address());
2013 fDebuggerInterface
->ContinueThread(thread
->ThreadID());
2021 TeamDebugger::_HandleImageFileChanged(image_id imageID
)
2023 TRACE_IMAGES("TeamDebugger::_HandleImageFileChanged(%" B_PRId32
")\n",
2025 // TODO: Reload the debug info!
2030 TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address
, bool enabled
,
2033 TRACE_CONTROL("TeamDebugger::_HandleSetUserBreakpoint(%#" B_PRIx64
2034 ", %d, %d)\n", address
, enabled
, hidden
);
2036 // check whether there already is a breakpoint
2037 AutoLocker
< ::Team
> locker(fTeam
);
2039 Breakpoint
* breakpoint
= fTeam
->BreakpointAtAddress(address
);
2040 UserBreakpoint
* userBreakpoint
= NULL
;
2041 if (breakpoint
!= NULL
&& breakpoint
->FirstUserBreakpoint() != NULL
)
2042 userBreakpoint
= breakpoint
->FirstUserBreakpoint()->GetUserBreakpoint();
2043 BReference
<UserBreakpoint
> userBreakpointReference(userBreakpoint
);
2045 if (userBreakpoint
== NULL
) {
2046 TRACE_CONTROL(" no breakpoint yet\n");
2048 // get the function at the address
2049 Image
* image
= fTeam
->ImageByAddress(address
);
2051 TRACE_CONTROL(" image: %p\n", image
);
2055 ImageDebugInfo
* imageDebugInfo
= image
->GetImageDebugInfo();
2057 TRACE_CONTROL(" image debug info: %p\n", imageDebugInfo
);
2059 if (imageDebugInfo
== NULL
)
2061 // TODO: Handle this case by loading the debug info, if possible!
2062 FunctionInstance
* functionInstance
2063 = imageDebugInfo
->FunctionAtAddress(address
);
2065 TRACE_CONTROL(" function instance: %p\n", functionInstance
);
2067 if (functionInstance
== NULL
)
2069 Function
* function
= functionInstance
->GetFunction();
2071 TRACE_CONTROL(" function: %p\n", function
);
2073 // get the source location for the address
2074 FunctionDebugInfo
* functionDebugInfo
2075 = functionInstance
->GetFunctionDebugInfo();
2076 SourceLocation sourceLocation
;
2077 Statement
* breakpointStatement
= NULL
;
2078 if (functionDebugInfo
->GetSpecificImageDebugInfo()->GetStatement(
2079 functionDebugInfo
, address
, breakpointStatement
) != B_OK
) {
2083 sourceLocation
= breakpointStatement
->StartSourceLocation();
2084 breakpointStatement
->ReleaseReference();
2086 target_addr_t relativeAddress
= address
- functionInstance
->Address();
2088 TRACE_CONTROL(" relative address: %#" B_PRIx64
", source location: "
2089 "(%" B_PRId32
", %" B_PRId32
")\n", relativeAddress
,
2090 sourceLocation
.Line(), sourceLocation
.Column());
2093 FunctionID
* functionID
= functionInstance
->GetFunctionID();
2094 if (functionID
== NULL
)
2096 BReference
<FunctionID
> functionIDReference(functionID
, true);
2098 // create the user breakpoint
2099 userBreakpoint
= new(std::nothrow
) UserBreakpoint(
2100 UserBreakpointLocation(functionID
, function
->SourceFile(),
2101 sourceLocation
, relativeAddress
));
2102 if (userBreakpoint
== NULL
)
2104 userBreakpointReference
.SetTo(userBreakpoint
, true);
2106 userBreakpoint
->SetHidden(hidden
);
2108 TRACE_CONTROL(" created user breakpoint: %p\n", userBreakpoint
);
2110 // iterate through all function instances and create
2111 // UserBreakpointInstances
2112 for (FunctionInstanceList::ConstIterator it
2113 = function
->Instances().GetIterator();
2114 FunctionInstance
* instance
= it
.Next();) {
2115 TRACE_CONTROL(" function instance %p: range: %#" B_PRIx64
" - %#"
2116 B_PRIx64
"\n", instance
, instance
->Address(),
2117 instance
->Address() + instance
->Size());
2119 // get the breakpoint address for the instance
2120 target_addr_t instanceAddress
= 0;
2121 if (instance
== functionInstance
) {
2122 instanceAddress
= address
;
2123 } else if (functionInstance
->SourceFile() != NULL
) {
2124 // We have a source file, so get the address for the source
2126 Statement
* statement
= NULL
;
2127 functionDebugInfo
= instance
->GetFunctionDebugInfo();
2128 functionDebugInfo
->GetSpecificImageDebugInfo()
2129 ->GetStatementAtSourceLocation(functionDebugInfo
,
2130 sourceLocation
, statement
);
2131 if (statement
!= NULL
) {
2132 instanceAddress
= statement
->CoveringAddressRange().Start();
2133 // TODO: What about BreakpointAllowed()?
2134 statement
->ReleaseReference();
2138 TRACE_CONTROL(" breakpoint address using source info: %" B_PRIx64
2139 "\n", instanceAddress
);
2141 if (instanceAddress
== 0) {
2142 // No source file (or we failed getting the statement), so try
2143 // to use the same relative address.
2144 if (relativeAddress
> instance
->Size())
2146 instanceAddress
= instance
->Address() + relativeAddress
;
2149 TRACE_CONTROL(" final breakpoint address: %" B_PRIx64
"\n",
2152 UserBreakpointInstance
* breakpointInstance
= new(std::nothrow
)
2153 UserBreakpointInstance(userBreakpoint
, instanceAddress
);
2154 if (breakpointInstance
== NULL
2155 || !userBreakpoint
->AddInstance(breakpointInstance
)) {
2156 delete breakpointInstance
;
2160 TRACE_CONTROL(" breakpoint instance: %p\n", breakpointInstance
);
2166 _HandleSetUserBreakpoint(userBreakpoint
, enabled
);
2171 TeamDebugger::_HandleSetUserBreakpoint(UserBreakpoint
* breakpoint
, bool enabled
)
2173 status_t error
= fBreakpointManager
->InstallUserBreakpoint(breakpoint
,
2175 if (error
!= B_OK
) {
2176 _NotifyUser("Install Breakpoint", "Failed to install breakpoint: %s",
2183 TeamDebugger::_HandleClearUserBreakpoint(target_addr_t address
)
2185 TRACE_CONTROL("TeamDebugger::_HandleClearUserBreakpoint(%#" B_PRIx64
")\n",
2188 AutoLocker
< ::Team
> locker(fTeam
);
2190 Breakpoint
* breakpoint
= fTeam
->BreakpointAtAddress(address
);
2191 if (breakpoint
== NULL
|| breakpoint
->FirstUserBreakpoint() == NULL
)
2193 UserBreakpoint
* userBreakpoint
2194 = breakpoint
->FirstUserBreakpoint()->GetUserBreakpoint();
2195 BReference
<UserBreakpoint
> userBreakpointReference(userBreakpoint
);
2199 _HandleClearUserBreakpoint(userBreakpoint
);
2204 TeamDebugger::_HandleClearUserBreakpoint(UserBreakpoint
* breakpoint
)
2206 fBreakpointManager
->UninstallUserBreakpoint(breakpoint
);
2211 TeamDebugger::_HandleSetWatchpoint(target_addr_t address
, uint32 type
,
2212 int32 length
, bool enabled
)
2214 Watchpoint
* watchpoint
= new(std::nothrow
) Watchpoint(address
, type
,
2217 if (watchpoint
== NULL
)
2219 BReference
<Watchpoint
> watchpointRef(watchpoint
, true);
2221 _HandleSetWatchpoint(watchpoint
, enabled
);
2226 TeamDebugger::_HandleSetWatchpoint(Watchpoint
* watchpoint
, bool enabled
)
2228 status_t error
= fWatchpointManager
->InstallWatchpoint(watchpoint
,
2230 if (error
!= B_OK
) {
2231 _NotifyUser("Install Watchpoint", "Failed to install watchpoint: %s",
2238 TeamDebugger::_HandleClearWatchpoint(target_addr_t address
)
2240 TRACE_CONTROL("TeamDebugger::_HandleClearWatchpoint(%#" B_PRIx64
")\n",
2243 AutoLocker
< ::Team
> locker(fTeam
);
2245 Watchpoint
* watchpoint
= fTeam
->WatchpointAtAddress(address
);
2246 if (watchpoint
== NULL
)
2248 BReference
<Watchpoint
> watchpointReference(watchpoint
);
2252 _HandleClearWatchpoint(watchpoint
);
2257 TeamDebugger::_HandleClearWatchpoint(Watchpoint
* watchpoint
)
2259 fWatchpointManager
->UninstallWatchpoint(watchpoint
);
2264 TeamDebugger::_HandleInspectAddress(target_addr_t address
,
2265 TeamMemoryBlock::Listener
* listener
)
2267 TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(%" B_PRIx64
", %p)\n",
2270 TeamMemoryBlock
* memoryBlock
= fMemoryBlockManager
2271 ->GetMemoryBlock(address
);
2273 if (memoryBlock
== NULL
) {
2274 _NotifyUser("Inspect Address", "Failed to allocate memory block");
2278 if (!memoryBlock
->IsValid()) {
2279 AutoLocker
< ::Team
> teamLocker(fTeam
);
2281 if (!memoryBlock
->HasListener(listener
))
2282 memoryBlock
->AddListener(listener
);
2284 TeamMemory
* memory
= fTeam
->GetTeamMemory();
2287 if ((result
= fWorker
->ScheduleJob(
2288 new(std::nothrow
) RetrieveMemoryBlockJob(fTeam
, memory
,
2292 memoryBlock
->NotifyDataRetrieved(result
);
2293 memoryBlock
->ReleaseReference();
2295 _NotifyUser("Inspect Address", "Failed to retrieve memory data: %s",
2299 memoryBlock
->NotifyDataRetrieved();
2305 TeamDebugger::_HandleWriteMemory(target_addr_t address
, void* data
,
2308 TRACE_CONTROL("TeamDebugger::_HandleWriteTargetMemory(%" B_PRIx64
", %p, "
2309 "%" B_PRIu64
")\n", address
, data
, size
);
2311 AutoLocker
< ::Team
> teamLocker(fTeam
);
2312 TeamMemory
* memory
= fTeam
->GetTeamMemory();
2315 if ((result
= fWorker
->ScheduleJob(
2316 new(std::nothrow
) WriteMemoryJob(fTeam
, memory
, address
, data
, size
),
2318 _NotifyUser("Write Memory", "Failed to write memory data: %s",
2325 TeamDebugger::_HandleEvaluateExpression(SourceLanguage
* language
,
2326 ExpressionInfo
* info
, StackFrame
* frame
, ::Thread
* thread
)
2328 status_t result
= fWorker
->ScheduleJob(
2329 new(std::nothrow
) ExpressionEvaluationJob(fTeam
, fDebuggerInterface
,
2330 language
, info
, frame
, thread
));
2331 if (result
!= B_OK
) {
2332 _NotifyUser("Evaluate Expression", "Failed to evaluate expression: %s",
2339 TeamDebugger::_HandleWriteCoreFile(const entry_ref
& targetPath
)
2341 status_t result
= fWorker
->ScheduleJob(
2342 new(std::nothrow
) WriteCoreFileJob(fTeam
, fDebuggerInterface
,
2344 if (result
!= B_OK
) {
2345 _NotifyUser("Write Core File", "Failed to write core file: %s",
2352 TeamDebugger::_HandleSetArguments(int argc
, const char* const* argv
)
2354 fCommandLineArgc
= argc
;
2355 fCommandLineArgv
= new(std::nothrow
) const char*[argc
];
2356 if (fCommandLineArgv
== NULL
)
2359 memset(const_cast<char **>(fCommandLineArgv
), 0, sizeof(char*) * argc
);
2361 for (int i
= 0; i
< argc
; i
++) {
2362 fCommandLineArgv
[i
] = strdup(argv
[i
]);
2363 if (fCommandLineArgv
[i
] == NULL
)
2372 TeamDebugger::_HandleDebugInfoJobUserInput(ImageDebugInfoLoadingState
* state
)
2374 SpecificImageDebugInfoLoadingState
* specificState
2375 = state
->GetSpecificDebugInfoLoadingState();
2377 ImageDebugLoadingStateHandler
* handler
;
2378 if (ImageDebugLoadingStateHandlerRoster::Default()
2379 ->FindStateHandler(specificState
, handler
) != B_OK
) {
2380 TRACE_JOBS("TeamDebugger::_HandleDebugInfoJobUserInput(): "
2381 "Failed to find appropriate information handler, aborting.");
2385 handler
->HandleState(specificState
, fUserInterface
);
2390 TeamDebugger::_GetThreadHandler(thread_id threadID
)
2392 AutoLocker
< ::Team
> locker(fTeam
);
2394 ThreadHandler
* handler
= fThreadHandlers
.Lookup(threadID
);
2395 if (handler
!= NULL
)
2396 handler
->AcquireReference();
2402 TeamDebugger::_AddImage(const ImageInfo
& imageInfo
, Image
** _image
)
2404 LocatableFile
* file
= NULL
;
2405 if (strchr(imageInfo
.Name(), '/') != NULL
)
2406 file
= fFileManager
->GetTargetFile(imageInfo
.Name());
2407 BReference
<LocatableFile
> imageFileReference(file
, true);
2410 status_t error
= fTeam
->AddImage(imageInfo
, file
, &image
);
2414 ImageDebugInfoRequested(image
);
2416 ImageHandler
* imageHandler
= new(std::nothrow
) ImageHandler(this, image
);
2417 if (imageHandler
!= NULL
)
2418 fImageHandlers
->Insert(imageHandler
);
2428 TeamDebugger::_LoadSettings()
2430 // get the team name
2431 AutoLocker
< ::Team
> locker(fTeam
);
2432 BString teamName
= fTeam
->Name();
2435 // load the settings
2436 if (fSettingsManager
->LoadTeamSettings(teamName
, fTeamSettings
) != B_OK
)
2439 // create the saved breakpoints
2440 for (int32 i
= 0; const BreakpointSetting
* breakpointSetting
2441 = fTeamSettings
.BreakpointAt(i
); i
++) {
2442 if (breakpointSetting
->GetFunctionID() == NULL
)
2445 // get the source file, if any
2446 LocatableFile
* sourceFile
= NULL
;
2447 if (breakpointSetting
->SourceFile().Length() > 0) {
2448 sourceFile
= fFileManager
->GetSourceFile(
2449 breakpointSetting
->SourceFile());
2450 if (sourceFile
== NULL
)
2453 BReference
<LocatableFile
> sourceFileReference(sourceFile
, true);
2455 // create the breakpoint
2456 UserBreakpointLocation
location(breakpointSetting
->GetFunctionID(),
2457 sourceFile
, breakpointSetting
->GetSourceLocation(),
2458 breakpointSetting
->RelativeAddress());
2460 UserBreakpoint
* breakpoint
= new(std::nothrow
) UserBreakpoint(location
);
2461 if (breakpoint
== NULL
)
2463 BReference
<UserBreakpoint
> breakpointReference(breakpoint
, true);
2465 breakpoint
->SetHidden(breakpointSetting
->IsHidden());
2466 breakpoint
->SetCondition(breakpointSetting
->Condition());
2469 fBreakpointManager
->InstallUserBreakpoint(breakpoint
,
2470 breakpointSetting
->IsEnabled());
2473 fFileManager
->LoadLocationMappings(fTeamSettings
.FileManagerSettings());
2475 const TeamUiSettings
* uiSettings
= fTeamSettings
.UiSettingFor(
2476 fUserInterface
->ID());
2477 if (uiSettings
!= NULL
)
2478 fUserInterface
->LoadSettings(uiSettings
);
2480 const TeamSignalSettings
* signalSettings
= fTeamSettings
.SignalSettings();
2481 if (signalSettings
!= NULL
) {
2482 fTeam
->SetDefaultSignalDisposition(
2483 signalSettings
->DefaultSignalDisposition());
2487 for (int32 i
= 0; i
< signalSettings
->CountCustomSignalDispositions();
2489 if (signalSettings
->GetCustomSignalDispositionAt(i
, signal
,
2490 disposition
) == B_OK
) {
2491 fTeam
->SetCustomSignalDisposition(signal
, disposition
);
2499 TeamDebugger::_SaveSettings()
2502 AutoLocker
< ::Team
> locker(fTeam
);
2503 TeamSettings settings
;
2504 if (settings
.SetTo(fTeam
) != B_OK
)
2507 TeamUiSettings
* uiSettings
= NULL
;
2508 if (fUserInterface
->SaveSettings(uiSettings
) != B_OK
)
2510 if (uiSettings
!= NULL
)
2511 settings
.AddUiSettings(uiSettings
);
2513 // preserve the UI settings from our cached copy.
2514 for (int32 i
= 0; i
< fTeamSettings
.CountUiSettings(); i
++) {
2515 const TeamUiSettings
* oldUiSettings
= fTeamSettings
.UiSettingAt(i
);
2516 if (strcmp(oldUiSettings
->ID(), fUserInterface
->ID()) != 0) {
2517 TeamUiSettings
* clonedSettings
= oldUiSettings
->Clone();
2518 if (clonedSettings
!= NULL
)
2519 settings
.AddUiSettings(clonedSettings
);
2523 fFileManager
->SaveLocationMappings(settings
.FileManagerSettings());
2526 // save the settings
2527 fSettingsManager
->SaveTeamSettings(settings
);
2532 TeamDebugger::_NotifyUser(const char* title
, const char* text
,...)
2534 // print the message
2537 va_start(args
, text
);
2538 vsnprintf(buffer
, sizeof(buffer
), text
, args
);
2542 fUserInterface
->NotifyUser(title
, buffer
, USER_NOTIFICATION_WARNING
);
2547 TeamDebugger::_ResetUserBackgroundStatusIfNeeded()
2549 if (!fWorker
->HasPendingJobs())
2550 fUserInterface
->NotifyBackgroundWorkStatus("Ready.");
2554 // #pragma mark - Listener
2557 TeamDebugger::Listener::~Listener()