diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 5be1681dc2..d084e22f6e 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -32,12 +32,16 @@ #include "Function.h" #include "FunctionID.h" #include "ImageDebugInfo.h" +#include "ImageDebugInfoLoadingState.h" +#include "ImageDebugLoadingStateHandler.h" +#include "ImageDebugLoadingStateHandlerRoster.h" #include "Jobs.h" #include "LocatableFile.h" #include "MessageCodes.h" #include "SettingsManager.h" #include "SourceCode.h" #include "SpecificImageDebugInfo.h" +#include "SpecificImageDebugInfoLoadingState.h" #include "StackFrame.h" #include "StackFrameValues.h" #include "Statement.h" @@ -463,8 +467,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, int argc, return error; ThreadHandler* handler = new(std::nothrow) ThreadHandler(thread, - fWorker, fDebuggerInterface, - fBreakpointManager); + fWorker, fDebuggerInterface, this, fBreakpointManager); if (handler == NULL) return B_NO_MEMORY; @@ -787,6 +790,20 @@ TeamDebugger::MessageReceived(BMessage* message) break; } + case MSG_DEBUG_INFO_NEEDS_USER_INPUT: + { + Job* job; + ImageDebugInfoLoadingState* state; + if (message->FindPointer("job", (void**)&job) != B_OK) + break; + if (message->FindPointer("state", (void**)&state) != B_OK) + break; + + _HandleDebugInfoJobUserInput(state); + fWorker->ResumeJob(job); + break; + } + default: BLooper::MessageReceived(message); break; @@ -848,7 +865,7 @@ TeamDebugger::FunctionSourceCodeRequested(FunctionInstance* functionInstance, void TeamDebugger::ImageDebugInfoRequested(Image* image) { - LoadImageDebugInfoJob::ScheduleIfNecessary(fWorker, image); + LoadImageDebugInfoJob::ScheduleIfNecessary(fWorker, image, this); } @@ -1121,6 +1138,20 @@ TeamDebugger::JobAborted(Job* job) } +void +TeamDebugger::ImageDebugInfoJobNeedsUserInput(Job* job, + ImageDebugInfoLoadingState* state) +{ + TRACE_JOBS("TeamDebugger::DebugInfoJobNeedsUserInput(%p, %p)\n", + job, state); + + BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); + message.AddPointer("job", job); + message.AddPointer("state", state); + PostMessage(&message); +} + + void TeamDebugger::ThreadStateChanged(const ::Team::ThreadEvent& event) { @@ -1405,8 +1436,7 @@ TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event) fTeam->AddThread(info, &thread); ThreadHandler* handler = new(std::nothrow) ThreadHandler(thread, - fWorker, fDebuggerInterface, - fBreakpointManager); + fWorker, fDebuggerInterface, this, fBreakpointManager); if (handler != NULL) { fThreadHandlers.Insert(handler); handler->Init(); @@ -1909,6 +1939,24 @@ TeamDebugger::_HandleSetArguments(int argc, const char* const* argv) } +void +TeamDebugger::_HandleDebugInfoJobUserInput(ImageDebugInfoLoadingState* state) +{ + SpecificImageDebugInfoLoadingState* specificState + = state->GetSpecificDebugInfoLoadingState(); + + ImageDebugLoadingStateHandler* handler; + if (ImageDebugLoadingStateHandlerRoster::Default() + ->FindStateHandler(specificState, handler) != B_OK) { + TRACE_JOBS("TeamDebugger::_HandleDebugInfoJobUserInput(): " + "Failed to find appropriate information handler, aborting."); + return; + } + + handler->HandleState(specificState, fUserInterface); +} + + ThreadHandler* TeamDebugger::_GetThreadHandler(thread_id threadID) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index c91fc583da..46fa880378 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef TEAM_DEBUGGER_H @@ -13,6 +13,7 @@ #include #include "DebugEvent.h" +#include "Jobs.h" #include "Team.h" #include "TeamSettings.h" #include "ThreadHandler.h" @@ -30,7 +31,8 @@ class WatchpointManager; class TeamDebugger : public BLooper, private UserInterfaceListener, - private JobListener, private Team::Listener { + private JobListener, private ImageDebugInfoJobListener, + private Team::Listener { public: class Listener; @@ -110,6 +112,9 @@ private: virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); + virtual void ImageDebugInfoJobNeedsUserInput(Job* job, + ImageDebugInfoLoadingState* state); + // Team::Listener virtual void ThreadStateChanged( const ::Team::ThreadEvent& event); @@ -178,6 +183,9 @@ private: status_t _HandleSetArguments(int argc, const char* const* argv); + void _HandleDebugInfoJobUserInput( + ImageDebugInfoLoadingState* state); + ThreadHandler* _GetThreadHandler(thread_id threadID); status_t _AddImage(const ImageInfo& imageInfo, diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index 3a1a02f289..a9653c200b 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2010-2013, Rene Gollent, rene@gollent.com. + * Copyright 2010-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -44,11 +44,13 @@ enum { ThreadHandler::ThreadHandler(Thread* thread, Worker* worker, DebuggerInterface* debuggerInterface, + ImageDebugInfoJobListener* listener, BreakpointManager* breakpointManager) : fThread(thread), fWorker(worker), fDebuggerInterface(debuggerInterface), + fDebugInfoJobListener(listener), fBreakpointManager(breakpointManager), fStepMode(STEP_NONE), fStepStatement(NULL), @@ -376,7 +378,8 @@ ThreadHandler::HandleCpuStateChanged() if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) { fWorker->ScheduleJob( new(std::nothrow) GetStackTraceJob(fDebuggerInterface, - fDebuggerInterface->GetArchitecture(), fThread)); + fDebugInfoJobListener, fDebuggerInterface->GetArchitecture(), + fThread)); } } diff --git a/src/apps/debugger/controllers/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h index 3bbff417bb..eb80905d21 100644 --- a/src/apps/debugger/controllers/ThreadHandler.h +++ b/src/apps/debugger/controllers/ThreadHandler.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef THREAD_HANDLER_H @@ -17,6 +18,7 @@ class BreakpointManager; class DebuggerInterface; +class ImageDebugInfoJobListener; class StackFrame; class Statement; class Worker; @@ -27,6 +29,7 @@ class ThreadHandler : public BReferenceable, private ImageDebugInfoProvider, public: ThreadHandler(Thread* thread, Worker* worker, DebuggerInterface* debuggerInterface, + ImageDebugInfoJobListener* listener, BreakpointManager* breakpointManager); ~ThreadHandler(); @@ -103,6 +106,7 @@ private: Thread* fThread; Worker* fWorker; DebuggerInterface* fDebuggerInterface; + ImageDebugInfoJobListener* fDebugInfoJobListener; BreakpointManager* fBreakpointManager; uint32 fStepMode; Statement* fStepStatement; diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index 0bc286ea73..d0b28ce167 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -18,10 +18,12 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, - Architecture* architecture, Thread* thread) + ImageDebugInfoJobListener* listener, Architecture* architecture, + Thread* thread) : fKey(thread, JOB_TYPE_GET_STACK_TRACE), fDebuggerInterface(debuggerInterface), + fDebugInfoJobListener(listener), fArchitecture(architecture), fThread(thread) { @@ -82,7 +84,7 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) // schedule a job, if not loaded ImageDebugInfo* info; status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), - image, &info); + image, fDebugInfoJobListener, &info); if (error != B_OK) return error; diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index f024bc38a3..bc5df71558 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -83,10 +83,19 @@ private: }; +class ImageDebugInfoJobListener { +public: + virtual ~ImageDebugInfoJobListener(); + virtual void ImageDebugInfoJobNeedsUserInput(Job* job, + ImageDebugInfoLoadingState* state); +}; + + class GetStackTraceJob : public Job, private ImageDebugInfoProvider { public: GetStackTraceJob( DebuggerInterface* debuggerInterface, + ImageDebugInfoJobListener* listener, Architecture* architecture, Thread* thread); virtual ~GetStackTraceJob(); @@ -101,6 +110,7 @@ private: private: SimpleJobKey fKey; DebuggerInterface* fDebuggerInterface; + ImageDebugInfoJobListener* fDebugInfoJobListener; Architecture* fArchitecture; Thread* fThread; CpuState* fCpuState; @@ -109,7 +119,8 @@ private: class LoadImageDebugInfoJob : public Job { public: - LoadImageDebugInfoJob(Image* image); + LoadImageDebugInfoJob(Image* image, + ImageDebugInfoJobListener* listener); virtual ~LoadImageDebugInfoJob(); virtual const JobKey& Key() const; @@ -117,6 +128,7 @@ public: static status_t ScheduleIfNecessary(Worker* worker, Image* image, + ImageDebugInfoJobListener* listener, ImageDebugInfo** _imageDebugInfo = NULL); // If already loaded returns a // reference, if desired. If not loaded @@ -125,12 +137,19 @@ public: // if scheduling the job failed, or the // debug info already failed to load // earlier. +private: + void NotifyUserInputListener(); + +private: + typedef BObjectList ListenerList; + private: SimpleJobKey fKey; Image* fImage; ImageDebugInfoLoadingState fState; + ImageDebugInfoJobListener* fListener; }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index 418873f5eb..600055c0f6 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2012-2014, Rene Gollent, rene@gollent.com. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -14,11 +14,31 @@ #include "Team.h" -LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) +// #pragma mark - ImageDebugInfoJobListener + + +ImageDebugInfoJobListener::~ImageDebugInfoJobListener() +{ +} + + +void +ImageDebugInfoJobListener::ImageDebugInfoJobNeedsUserInput(Job* job, + ImageDebugInfoLoadingState* state) +{ +} + + +// #pragma mark - LoadImageDebugInfoJob + + +LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image, + ImageDebugInfoJobListener* listener) : fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), fImage(image), - fState() + fState(), + fListener(listener) { fImage->AcquireReference(); } @@ -54,11 +74,9 @@ LoadImageDebugInfoJob::Do() locker.Lock(); if (fState.UserInputRequired()) { - // TODO: notify the user interface + NotifyUserInputListener(); return WaitForUserInput(); - } - - if (error == B_OK) { + } else if (error == B_OK) { error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); debugInfo->ReleaseReference(); } else @@ -70,7 +88,7 @@ LoadImageDebugInfoJob::Do() /*static*/ status_t LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfo** _imageDebugInfo) + ImageDebugInfoJobListener* listener, ImageDebugInfo** _imageDebugInfo) { AutoLocker teamLocker(image->GetTeam()); @@ -95,7 +113,8 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, return B_ERROR; // schedule a job - LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image); + LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image, + listener); if (job == NULL) return B_NO_MEMORY; @@ -111,3 +130,12 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, *_imageDebugInfo = NULL; return B_OK; } + + +void +LoadImageDebugInfoJob::NotifyUserInputListener() +{ + if (fListener != NULL) + fListener->ImageDebugInfoJobNeedsUserInput(this, &fState); +} +