hrev47378 adds 6 changesets to branch 'master' old head: 004f41565ee7ad9c9d7d32f86330401ce5b16796 new head: d44d8207a86103afa47f1862c06ff46e46e1cb33 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=d44d820+%5E004f415 ---------------------------------------------------------------------------- 4605feb: Debugger: Add/handle new suspend state for jobs. - In addition to waiting for one or more dependent jobs to complete, a job can now potentially wait for user input to proceed further. Add a corresponding job_wait_status and respective handling in Worker. a262768: Debugger: Add classes for representing image loading state. Adds a hierarchy of classes for preserving the loading state information for a LoadImageDebugInfoJob. These include: - ImageDebugInfoLoadingState: Top level class that simply stores a reference for the specific info state that we're currently attempting to load. - SpecificImageDebugInfoLoadingState: Abstract base class representing state information specific to a particular kind of debug information. - DwarfImageDebugInfoLoadingState: Implementation of the above for the case of DWARF. - DwarfFileLoadingState: Encapsulates the in-progress loading state of a DWARF file for the case where a file's debug information is referenced externally, but cannot be found. 7cab832: Debugger: Add support for suspending LoadImageDebugInfoJob. DwarfFile: - Loading is now split into two steps, the first of which simply attempts to verify the presence of debug information. If the latter is referenced externally, but cannot be found on disk, the corresponding file reference is returned. TeamDebugInfo: - Add state parameter to LoadImageDebugInfo(). Use it to preserve where we are in the specific info loading loop if necessary. SpecificTeamDebugInfo: - Add parameter to CreateImageDebugInfo() to allow passing in a state object and adjust implementing subclasses accordingly. DwarfTeamDebugInfo: - Preserve and/or pass down DwarfFile's loading state as needed. DwarfManager: - When attempting to load a DwarfFile, detect the case where external debug information is referenced, but could not be located. If so, preserve the relevant details in the loading state, so the user can be notified and asked to find it accordingly. LoadImageDebugInfoJob: - Keep a state object for the progress of the current loading job. If a particular image fails due to needing user input, suspend ourselves until such input has been provided. d9e9718: Debugger: Add file prompt hook to UserInterface. In some circumstances, it may be necessary to ask the user to locate a file from the lower layers. Adds the corresponding hook to UserInterface, and a stub implementation for CommandLineUserInterface. Adds full implementation for GraphicalUserInterface. 3315110: Debugger: Start adding the groundwork for load state handlers. Adds abstract class ImageDebugLoadingStateHandler which simply contains two hooks, which allow one to a) ask it if it supports a handling a particular type of loading state, and b) if so, ask it to attempt to handle that case, given the passed in user interface object. Also adds implementing subclass for DwarfImageDebugInfo, currently intended primarily to handle the case of missing external debug information. At present, this just supports prompting the user to find/install the file, but eventually this will be extended to also support automatically installing the corresponding debug information package, if applicable. Finally, adds ImageDebugLoadingStateHandlerRoster, which acts as a front end for matching up a given loading state with the appropriate handler. d44d820: Debugger: Finish handling of missing debug information. Add a listener interface for LoadImageDebugInfoJob that allows it to request user assistance based on its current state. Adjust callers to pass in said listener accordingly. Implement the aforementioned listener interface in TeamDebugger, and use the loading state handler roster to find the appropriate handler / handle the request. This implements most of what's needed for #10138, the main piece still missing is for the dwarf handler to detect whether the image in question comes from a package, and if so, to offer to install the corresponding debug information package rather than locating the file manually, assuming such a package exists. [ Rene Gollent <rene@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 43 files changed, 1131 insertions(+), 68 deletions(-) src/apps/debugger/Debugger.cpp | 8 +- src/apps/debugger/Jamfile | 9 ++ src/apps/debugger/MessageCodes.h | 5 +- src/apps/debugger/controllers/TeamDebugger.cpp | 58 +++++++- src/apps/debugger/controllers/TeamDebugger.h | 12 +- src/apps/debugger/controllers/ThreadHandler.cpp | 7 +- src/apps/debugger/controllers/ThreadHandler.h | 4 + .../debug_info/DebuggerTeamDebugInfo.cpp | 3 +- .../debugger/debug_info/DebuggerTeamDebugInfo.h | 2 + .../DwarfImageDebugInfoLoadingState.cpp | 27 ++++ .../debug_info/DwarfImageDebugInfoLoadingState.h | 30 ++++ .../debugger/debug_info/DwarfTeamDebugInfo.cpp | 25 +++- .../debugger/debug_info/DwarfTeamDebugInfo.h | 2 + .../debug_info/ImageDebugInfoLoadingState.cpp | 61 ++++++++ .../debug_info/ImageDebugInfoLoadingState.h | 43 ++++++ .../debug_info/ImageDebugLoadingStateHandler.cpp | 12 ++ .../debug_info/ImageDebugLoadingStateHandler.h | 30 ++++ .../ImageDebugLoadingStateHandlerRoster.cpp | 143 ++++++++++++++++++ .../ImageDebugLoadingStateHandlerRoster.h | 56 +++++++ .../SpecificImageDebugInfoLoadingState.cpp | 19 +++ .../SpecificImageDebugInfoLoadingState.h | 21 +++ .../debugger/debug_info/SpecificTeamDebugInfo.h | 4 +- src/apps/debugger/debug_info/TeamDebugInfo.cpp | 16 +- src/apps/debugger/debug_info/TeamDebugInfo.h | 3 + .../DwarfLoadingStateHandler.cpp | 73 +++++++++ .../DwarfLoadingStateHandler.h | 27 ++++ src/apps/debugger/dwarf/DwarfFile.cpp | 57 +++++-- src/apps/debugger/dwarf/DwarfFile.h | 9 +- .../debugger/dwarf/DwarfFileLoadingState.cpp | 26 ++++ src/apps/debugger/dwarf/DwarfFileLoadingState.h | 38 +++++ src/apps/debugger/dwarf/DwarfManager.cpp | 43 ++++-- src/apps/debugger/dwarf/DwarfManager.h | 8 +- src/apps/debugger/dwarf/Jamfile | 1 + src/apps/debugger/jobs/GetStackTraceJob.cpp | 6 +- src/apps/debugger/jobs/Jobs.h | 26 +++- src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp | 49 +++++- src/apps/debugger/user_interface/UserInterface.h | 5 +- .../cli/CommandLineUserInterface.cpp | 9 +- .../cli/CommandLineUserInterface.h | 3 +- .../gui/GraphicalUserInterface.cpp | 148 ++++++++++++++++++- .../user_interface/gui/GraphicalUserInterface.h | 8 + src/apps/debugger/util/Worker.cpp | 51 ++++++- src/apps/debugger/util/Worker.h | 12 +- ############################################################################ Commit: 4605febacfbad61b13dd93e4f599884e2c38f886 URL: http://cgit.haiku-os.org/haiku/commit/?id=4605feb Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Mon Dec 2 02:10:51 2013 UTC Debugger: Add/handle new suspend state for jobs. - In addition to waiting for one or more dependent jobs to complete, a job can now potentially wait for user input to proceed further. Add a corresponding job_wait_status and respective handling in Worker. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/util/Worker.cpp b/src/apps/debugger/util/Worker.cpp index 304c3bd..e395af4 100644 --- a/src/apps/debugger/util/Worker.cpp +++ b/src/apps/debugger/util/Worker.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2012-2014, Rene Gollent, rene@xxxxxxxxxxx. * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. * Distributed under the terms of the MIT License. */ @@ -114,6 +114,13 @@ Job::WaitFor(const JobKey& key) } +status_t +Job::WaitForUserInput() +{ + return fWorker->WaitForUserInput(this); +} + + void Job::SetWorker(Worker* worker) { @@ -141,6 +148,7 @@ Job::SetWaitStatus(job_wait_status status) fWaitStatus = status; switch (fWaitStatus) { case JOB_DEPENDENCY_ACTIVE: + case JOB_USER_INPUT_WAITING: fState = JOB_STATE_WAITING; break; default: @@ -316,6 +324,25 @@ Worker::GetJob(const JobKey& key) status_t +Worker::ResumeJob(Job* job) +{ + AutoLocker<Worker> locker(this); + + for (JobList::Iterator it = fSuspendedJobs.GetIterator(); it.Next();) { + if (it.Current() == job) { + it.Remove(); + job->SetState(JOB_STATE_UNSCHEDULED); + fUnscheduledJobs.Add(job); + release_sem(fWorkToDoSem); + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t Worker::AddListener(const JobKey& key, JobListener* listener) { AutoLocker<Worker> locker(this); @@ -359,6 +386,21 @@ Worker::WaitForJob(Job* waitingJob, const JobKey& key) } +status_t +Worker::WaitForUserInput(Job* waitingJob) +{ + AutoLocker<Worker> locker(this); + + if (fTerminating || waitingJob->State() == JOB_STATE_ABORTED) + return B_INTERRUPTED; + + waitingJob->SetWaitStatus(JOB_USER_INPUT_WAITING); + fSuspendedJobs.Add(waitingJob); + + return B_OK; +} + + /*static*/ status_t Worker::_WorkerLoopEntry(void* data) { @@ -439,10 +481,13 @@ Worker::_AbortJob(Job* job, bool removeFromTable) break; case JOB_STATE_WAITING: - job->Dependency()->DependentJobs().Remove(job); + { + Job* dependency = job->Dependency(); + if (dependency != NULL) + dependency->DependentJobs().Remove(job); job->SetDependency(NULL); break; - + } case JOB_STATE_ACTIVE: case JOB_STATE_FAILED: case JOB_STATE_SUCCEEDED: diff --git a/src/apps/debugger/util/Worker.h b/src/apps/debugger/util/Worker.h index 411b9cb..f3fa550 100644 --- a/src/apps/debugger/util/Worker.h +++ b/src/apps/debugger/util/Worker.h @@ -1,5 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef WORKER_H @@ -31,7 +32,9 @@ enum job_wait_status { JOB_DEPENDENCY_SUCCEEDED, JOB_DEPENDENCY_FAILED, JOB_DEPENDENCY_ABORTED, - JOB_DEPENDENCY_ACTIVE + JOB_DEPENDENCY_ACTIVE, + + JOB_USER_INPUT_WAITING // internal only }; @@ -88,6 +91,7 @@ public: protected: job_wait_status WaitFor(const JobKey& key); + status_t WaitForUserInput(); private: friend class Worker; @@ -141,6 +145,10 @@ public: void AbortJob(const JobKey& key); Job* GetJob(const JobKey& key); + status_t ResumeJob(Job* job); + // only valid for jobs that are + // suspended pending user input + status_t AddListener(const JobKey& key, JobListener* listener); void RemoveListener(const JobKey& key, @@ -178,6 +186,7 @@ private: private: job_wait_status WaitForJob(Job* waitingJob, const JobKey& key); + status_t WaitForUserInput(Job* waitingJob); static status_t _WorkerLoopEntry(void* data); status_t _WorkerLoop(); @@ -191,6 +200,7 @@ private: JobTable fJobs; JobList fUnscheduledJobs; JobList fAbortedJobs; + JobList fSuspendedJobs; sem_id fWorkToDoSem; thread_id fWorkerThread; volatile bool fTerminating; ############################################################################ Commit: a262768084fef1a4ad73c570f259fab2a31ed8f9 URL: http://cgit.haiku-os.org/haiku/commit/?id=a262768 Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Sun Jun 8 15:41:49 2014 UTC Debugger: Add classes for representing image loading state. Adds a hierarchy of classes for preserving the loading state information for a LoadImageDebugInfoJob. These include: - ImageDebugInfoLoadingState: Top level class that simply stores a reference for the specific info state that we're currently attempting to load. - SpecificImageDebugInfoLoadingState: Abstract base class representing state information specific to a particular kind of debug information. - DwarfImageDebugInfoLoadingState: Implementation of the above for the case of DWARF. - DwarfFileLoadingState: Encapsulates the in-progress loading state of a DWARF file for the case where a file's debug information is referenced externally, but cannot be found. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 18ff810..95550ff 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -100,6 +100,7 @@ Application Debugger : DebuggerTeamDebugInfo.cpp DwarfFunctionDebugInfo.cpp DwarfImageDebugInfo.cpp + DwarfImageDebugInfoLoadingState.cpp DwarfStackFrameDebugInfo.cpp DwarfTeamDebugInfo.cpp DwarfTypeFactory.cpp @@ -109,9 +110,11 @@ Application Debugger : FunctionInstance.cpp GlobalTypeLookup.cpp ImageDebugInfo.cpp + ImageDebugInfoLoadingState.cpp ImageDebugInfoProvider.cpp NoOpStackFrameDebugInfo.cpp SpecificImageDebugInfo.cpp + SpecificImageDebugInfoLoadingState.cpp SpecificTeamDebugInfo.cpp StackFrameDebugInfo.cpp TeamDebugInfo.cpp diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfoLoadingState.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfoLoadingState.cpp new file mode 100644 index 0000000..d372017 --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfoLoadingState.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "DwarfImageDebugInfoLoadingState.h" + + +DwarfImageDebugInfoLoadingState::DwarfImageDebugInfoLoadingState() + : + SpecificImageDebugInfoLoadingState(), + fState() +{ +} + + +DwarfImageDebugInfoLoadingState::~DwarfImageDebugInfoLoadingState() +{ +} + + +bool +DwarfImageDebugInfoLoadingState::UserInputRequired() const +{ + return fState.state == DWARF_FILE_LOADING_STATE_USER_INPUT_NEEDED; +} diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfoLoadingState.h b/src/apps/debugger/debug_info/DwarfImageDebugInfoLoadingState.h new file mode 100644 index 0000000..f2edd1c --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfoLoadingState.h @@ -0,0 +1,30 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_IMAGE_DEBUG_INFO_LOADING_STATE_H +#define DWARF_IMAGE_DEBUG_INFO_LOADING_STATE_H + + +#include "DwarfFileLoadingState.h" +#include "SpecificImageDebugInfoLoadingState.h" + + +class DwarfImageDebugInfoLoadingState + : public SpecificImageDebugInfoLoadingState { +public: + DwarfImageDebugInfoLoadingState(); + virtual ~DwarfImageDebugInfoLoadingState(); + + virtual bool UserInputRequired() const; + + DwarfFileLoadingState& GetFileState() + { return fState; } + +private: + DwarfFileLoadingState fState; +}; + + +#endif // DWARF_IMAGE_DEBUG_INFO_LOADING_STATE_H + diff --git a/src/apps/debugger/debug_info/ImageDebugInfoLoadingState.cpp b/src/apps/debugger/debug_info/ImageDebugInfoLoadingState.cpp new file mode 100644 index 0000000..dffab2f --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugInfoLoadingState.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "ImageDebugInfoLoadingState.h" + +#include "SpecificImageDebugInfoLoadingState.h" + + +ImageDebugInfoLoadingState::ImageDebugInfoLoadingState() + : + fSpecificInfoLoadingState(), + fSpecificInfoIndex(0) +{ +} + + +ImageDebugInfoLoadingState::~ImageDebugInfoLoadingState() +{ +} + + +bool +ImageDebugInfoLoadingState::HasSpecificDebugInfoLoadingState() const +{ + return fSpecificInfoLoadingState.Get() != NULL; +} + + +void +ImageDebugInfoLoadingState::SetSpecificDebugInfoLoadingState( + SpecificImageDebugInfoLoadingState* state) +{ + fSpecificInfoLoadingState.SetTo(state, true); +} + + +void +ImageDebugInfoLoadingState::ClearSpecificDebugInfoLoadingState() +{ + fSpecificInfoLoadingState = NULL; +} + + +bool +ImageDebugInfoLoadingState::UserInputRequired() const +{ + if (HasSpecificDebugInfoLoadingState()) + return fSpecificInfoLoadingState->UserInputRequired(); + + return false; +} + + +void +ImageDebugInfoLoadingState::SetSpecificInfoIndex(int32 index) +{ + fSpecificInfoIndex = index; +} diff --git a/src/apps/debugger/debug_info/ImageDebugInfoLoadingState.h b/src/apps/debugger/debug_info/ImageDebugInfoLoadingState.h new file mode 100644 index 0000000..8089759 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugInfoLoadingState.h @@ -0,0 +1,43 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_DEBUG_INFO_LOADING_STATE_H +#define IMAGE_DEBUG_INFO_LOADING_STATE_H + +#include <Referenceable.h> + + +class SpecificImageDebugInfoLoadingState; + + +class ImageDebugInfoLoadingState { +public: + ImageDebugInfoLoadingState(); + virtual ~ImageDebugInfoLoadingState(); + + bool HasSpecificDebugInfoLoadingState() const; + SpecificImageDebugInfoLoadingState* + GetSpecificDebugInfoLoadingState() const + { return fSpecificInfoLoadingState; } + void SetSpecificDebugInfoLoadingState( + SpecificImageDebugInfoLoadingState* state); + // note: takes over reference of passed + // in state object. + void ClearSpecificDebugInfoLoadingState(); + + bool UserInputRequired() const; + + + int32 GetSpecificInfoIndex() const + { return fSpecificInfoIndex; } + void SetSpecificInfoIndex(int32 index); + +private: + BReference<SpecificImageDebugInfoLoadingState> + fSpecificInfoLoadingState; + int32 fSpecificInfoIndex; +}; + + +#endif // IMAGE_DEBUG_INFO_LOADING_STATE_H diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfoLoadingState.cpp b/src/apps/debugger/debug_info/SpecificImageDebugInfoLoadingState.cpp new file mode 100644 index 0000000..23fabb8 --- /dev/null +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfoLoadingState.cpp @@ -0,0 +1,19 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "SpecificImageDebugInfoLoadingState.h" + + +SpecificImageDebugInfoLoadingState::SpecificImageDebugInfoLoadingState() + : + BReferenceable() +{ +} + + +SpecificImageDebugInfoLoadingState::~SpecificImageDebugInfoLoadingState() +{ +} diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfoLoadingState.h b/src/apps/debugger/debug_info/SpecificImageDebugInfoLoadingState.h new file mode 100644 index 0000000..ce4393b --- /dev/null +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfoLoadingState.h @@ -0,0 +1,21 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef SPECIFIC_IMAGE_DEBUG_INFO_LOADING_STATE_H +#define SPECIFIC_IMAGE_DEBUG_INFO_LOADING_STATE_H + + +#include <Referenceable.h> + + +class SpecificImageDebugInfoLoadingState : public BReferenceable { +public: + SpecificImageDebugInfoLoadingState(); + virtual ~SpecificImageDebugInfoLoadingState(); + + virtual bool UserInputRequired() const = 0; +}; + + +#endif // SPECIFIC_IMAGE_DEBUG_INFO_LOADING_STATE_H diff --git a/src/apps/debugger/dwarf/DwarfFileLoadingState.cpp b/src/apps/debugger/dwarf/DwarfFileLoadingState.cpp new file mode 100644 index 0000000..bcf33da --- /dev/null +++ b/src/apps/debugger/dwarf/DwarfFileLoadingState.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "DwarfFileLoadingState.h" + +#include "DwarfFile.h" + + +DwarfFileLoadingState::DwarfFileLoadingState() + : + dwarfFile(), + externalInfoFileName(), + locatedExternalInfoPath(), + state(DWARF_FILE_LOADING_STATE_INITIAL) +{ +} + + +DwarfFileLoadingState::~DwarfFileLoadingState() +{ +} + + diff --git a/src/apps/debugger/dwarf/DwarfFileLoadingState.h b/src/apps/debugger/dwarf/DwarfFileLoadingState.h new file mode 100644 index 0000000..7f1467d --- /dev/null +++ b/src/apps/debugger/dwarf/DwarfFileLoadingState.h @@ -0,0 +1,38 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_FILE_LOADING_STATE_H +#define DWARF_FILE_LOADING_STATE_H + + +#include <Referenceable.h> +#include <String.h> + + +class DwarfFile; + + +enum dwarf_file_loading_state { + DWARF_FILE_LOADING_STATE_INITIAL = 0, + DWARF_FILE_LOADING_STATE_USER_INPUT_NEEDED, + DWARF_FILE_LOADING_STATE_USER_INPUT_PROVIDED, + DWARF_FILE_LOADING_STATE_FAILED, + DWARF_FILE_LOADING_STATE_SUCCEEDED +}; + + +struct DwarfFileLoadingState { + BReference<DwarfFile> + dwarfFile; + BString externalInfoFileName; + BString locatedExternalInfoPath; + dwarf_file_loading_state + state; + + DwarfFileLoadingState(); + ~DwarfFileLoadingState(); +}; + + +#endif // DWARF_FILE_LOADING_STATE_H diff --git a/src/apps/debugger/dwarf/Jamfile b/src/apps/debugger/dwarf/Jamfile index 4cf6b78..f806498 100644 --- a/src/apps/debugger/dwarf/Jamfile +++ b/src/apps/debugger/dwarf/Jamfile @@ -22,6 +22,7 @@ MergeObject Debugger_dwarf.o DebugInfoEntry.cpp DwarfExpressionEvaluator.cpp DwarfFile.cpp + DwarfFileLoadingState.cpp DwarfManager.cpp DwarfTargetInterface.cpp DwarfUtils.cpp ############################################################################ Commit: 7cab8329564c7bccca42693808e9445ccfe6e108 URL: http://cgit.haiku-os.org/haiku/commit/?id=7cab832 Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Sun Dec 8 22:20:11 2013 UTC Debugger: Add support for suspending LoadImageDebugInfoJob. DwarfFile: - Loading is now split into two steps, the first of which simply attempts to verify the presence of debug information. If the latter is referenced externally, but cannot be found on disk, the corresponding file reference is returned. TeamDebugInfo: - Add state parameter to LoadImageDebugInfo(). Use it to preserve where we are in the specific info loading loop if necessary. SpecificTeamDebugInfo: - Add parameter to CreateImageDebugInfo() to allow passing in a state object and adjust implementing subclasses accordingly. DwarfTeamDebugInfo: - Preserve and/or pass down DwarfFile's loading state as needed. DwarfManager: - When attempting to load a DwarfFile, detect the case where external debug information is referenced, but could not be located. If so, preserve the relevant details in the loading state, so the user can be notified and asked to find it accordingly. LoadImageDebugInfoJob: - Keep a state object for the progress of the current loading job. If a particular image fails due to needing user input, suspend ourselves until such input has been provided. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp index 3c46e5f..66195db 100644 --- a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp @@ -33,7 +33,8 @@ DebuggerTeamDebugInfo::Init() status_t DebuggerTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, - LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo) + LocatableFile* imageFile, ImageDebugInfoLoadingState& _state, + SpecificImageDebugInfo*& _imageDebugInfo) { DebuggerImageDebugInfo* debuggerInfo = new(std::nothrow) DebuggerImageDebugInfo(imageInfo, diff --git a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h index d3895c0..3736754 100644 --- a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef DEBUGGER_TEAM_DEBUG_INFO_H @@ -24,6 +25,7 @@ public: virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, + ImageDebugInfoLoadingState& _state, SpecificImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp index 331f0a3..da04aca 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -12,8 +13,10 @@ #include "DebuggerInterface.h" #include "DwarfFile.h" #include "DwarfImageDebugInfo.h" +#include "DwarfImageDebugInfoLoadingState.h" #include "DwarfManager.h" #include "GlobalTypeLookup.h" +#include "ImageDebugInfoLoadingState.h" #include "LocatableFile.h" @@ -58,7 +61,8 @@ DwarfTeamDebugInfo::Init() status_t DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, - LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo) + LocatableFile* imageFile, ImageDebugInfoLoadingState& _state, + SpecificImageDebugInfo*& _imageDebugInfo) { // We only like images whose file we can play with. BString filePath; @@ -66,11 +70,22 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, return B_ENTRY_NOT_FOUND; // try to load the DWARF file - DwarfFile* file; - status_t error = fManager->LoadFile(filePath, file); + DwarfImageDebugInfoLoadingState* dwarfState; + if (_state.HasSpecificDebugInfoLoadingState()) { + dwarfState = dynamic_cast<DwarfImageDebugInfoLoadingState*>( + _state.GetSpecificDebugInfoLoadingState()); + if (dwarfState == NULL) + return B_BAD_VALUE; + } else { + dwarfState = new(std::nothrow) DwarfImageDebugInfoLoadingState(); + if (dwarfState == NULL) + return B_NO_MEMORY; + _state.SetSpecificDebugInfoLoadingState(dwarfState); + } + + status_t error = fManager->LoadFile(filePath, dwarfState->GetFileState()); if (error != B_OK) return error; - BReference<DwarfFile> fileReference(file, true); error = fManager->FinishLoading(); if (error != B_OK) @@ -79,7 +94,7 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, // create the image debug info DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo( imageInfo, fDebuggerInterface, fArchitecture, fFileManager, - fTypeLookup, fTypeCache, file); + fTypeLookup, fTypeCache, dwarfState->GetFileState().dwarfFile); if (debugInfo == NULL) return B_NO_MEMORY; diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h index 90c2434..fa2891b 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef DWARF_TEAM_DEBUG_INFO_H @@ -31,6 +32,7 @@ public: virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, + ImageDebugInfoLoadingState& _state, SpecificImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h b/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h index 1d3a47d..f9ac7c6 100644 --- a/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef SPECIFIC_TEAM_DEBUG_INFO_H @@ -8,17 +9,18 @@ #include <SupportDefs.h> +class ImageDebugInfoLoadingState; class ImageInfo; class LocatableFile; class SpecificImageDebugInfo; - class SpecificTeamDebugInfo { public: virtual ~SpecificTeamDebugInfo(); virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, + ImageDebugInfoLoadingState& _state, SpecificImageDebugInfo*& _imageDebugInfo) = 0; }; diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.cpp b/src/apps/debugger/debug_info/TeamDebugInfo.cpp index 700caa4..00b174e 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/TeamDebugInfo.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2012-2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2012-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -24,6 +24,7 @@ #include "Function.h" #include "FunctionID.h" #include "ImageDebugInfo.h" +#include "ImageDebugInfoLoadingState.h" #include "LocatableFile.h" #include "SourceFile.h" #include "SourceLanguage.h" @@ -426,7 +427,8 @@ TeamDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, status_t TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo, - LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo) + LocatableFile* imageFile, ImageDebugInfoLoadingState& _state, + ImageDebugInfo*& _imageDebugInfo) { ImageDebugInfo* imageDebugInfo = new(std::nothrow) ImageDebugInfo( imageInfo); @@ -438,15 +440,23 @@ TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo, = fSpecificInfos.ItemAt(i); i++) { SpecificImageDebugInfo* specificImageInfo; status_t error = specificTeamInfo->CreateImageDebugInfo(imageInfo, - imageFile, specificImageInfo); + imageFile, _state, specificImageInfo); if (error == B_OK) { if (!imageDebugInfo->AddSpecificInfo(specificImageInfo)) { delete specificImageInfo; return B_NO_MEMORY; } + } else if (_state.UserInputRequired()) { + _state.SetSpecificInfoIndex(i); + return error; } else if (error == B_NO_MEMORY) return error; // fail only when out of memory + + _state.ClearSpecificDebugInfoLoadingState(); + // if we made it this far, then we're done with current specific + // info, and its corresponding state object, if any, is no longer + // needed } status_t error = imageDebugInfo->FinishInit(fDebuggerInterface); diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.h b/src/apps/debugger/debug_info/TeamDebugInfo.h index 06b7fe0..884a1a3 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.h +++ b/src/apps/debugger/debug_info/TeamDebugInfo.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef TEAM_DEBUG_INFO_H @@ -26,6 +27,7 @@ class Function; class FunctionID; class FunctionInstance; class ImageDebugInfo; +class ImageDebugInfoLoadingState; class ImageInfo; class LocatableFile; class SourceCode; @@ -54,6 +56,7 @@ public: status_t LoadImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, + ImageDebugInfoLoadingState& state, ImageDebugInfo*& _imageDebugInfo); status_t LoadSourceCode(LocatableFile* file, diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index ad2fd47..fa38af5 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2012-2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2012-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -504,7 +504,7 @@ DwarfFile::~DwarfFile() status_t -DwarfFile::Load(const char* fileName) +DwarfFile::StartLoading(const char* fileName, BString& _requiredExternalFile) { fName = strdup(fileName); if (fName == NULL) @@ -523,9 +523,21 @@ DwarfFile::Load(const char* fileName) if (error != B_OK) return error; - error = _LocateDebugInfo(); - if (error != B_OK) - return error; + return _LocateDebugInfo(_requiredExternalFile); +} + + +status_t +DwarfFile::Load(const BString& externalInfoFilePath) +{ + status_t error = B_OK; + if (fDebugInfoSection == NULL) { + BString path; + error = _LocateDebugInfo(path, externalInfoFilePath.IsEmpty() + ? NULL : externalInfoFilePath.String()); + if (error != B_OK) + return error; + } ElfFile* debugInfoFile = fAlternateElfFile != NULL ? fAlternateElfFile : fElfFile; @@ -2686,7 +2698,8 @@ DwarfFile::_FindLocationExpression(CompilationUnit* unit, uint64 offset, status_t -DwarfFile::_LocateDebugInfo() +DwarfFile::_LocateDebugInfo(BString& _requiredExternalFileName, + const char* locatedFilePath) { ElfFile* debugInfoFile = fElfFile; ElfSection* debugLinkSection = fElfFile->GetSection(".gnu_debuglink"); @@ -2700,10 +2713,19 @@ DwarfFile::_LocateDebugInfo() // by a 32-bit CRC BString debugPath; - status_t result = _GetDebugInfoPath( - (const char*)debugLinkSection->Data(), debugPath); - if (result != B_OK) - return result; + if (locatedFilePath) + debugPath = locatedFilePath; + else { + status_t result = _GetDebugInfoPath( + (const char*)debugLinkSection->Data(), + _requiredExternalFileName); + if (result != B_OK) + return result; + debugPath = _requiredExternalFileName; + } + + if (fAlternateName != NULL) + free(fAlternateName); fAlternateName = strdup(debugPath.String()); @@ -2715,11 +2737,13 @@ DwarfFile::_LocateDebugInfo() int32 debugCRC = *(int32*)((char*)debugLinkSection->Data() + debugLinkSection->Size() - sizeof(int32)); */ - fAlternateElfFile = new(std::nothrow) ElfFile; - if (fAlternateElfFile == NULL) - return B_NO_MEMORY; + if (fAlternateElfFile == NULL) { + fAlternateElfFile = new(std::nothrow) ElfFile; + if (fAlternateElfFile == NULL) + return B_NO_MEMORY; + } - result = fAlternateElfFile->Init(fAlternateName); + status_t result = fAlternateElfFile->Init(fAlternateName); if (result != B_OK) return result; @@ -2780,6 +2804,11 @@ DwarfFile::_GetDebugInfoPath(const char* debugFileName, if (result == B_OK) { _infoPath = basePath.Path(); return B_OK; + } else { + // if we failed to find a match, then it's up to the user to + // locate it. As such, return the external info file name + // for user interface purposes. + _infoPath.SetTo(debugFileName); } return B_ENTRY_NOT_FOUND; diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index 17dee90..b778383 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -35,7 +35,9 @@ public: DwarfFile(); ~DwarfFile(); - status_t Load(const char* fileName); + status_t StartLoading(const char* fileName, + BString& _requiredExternalFile); + status_t Load(const BString& externalFilePath); status_t FinishLoading(); const char* Name() const { return fName; } @@ -172,7 +174,10 @@ private: const void*& _expression, off_t& _length) const; - status_t _LocateDebugInfo(); + status_t _LocateDebugInfo( + BString& _requiredExternalFileName, + const char* locatedFilePath = NULL); + status_t _GetDebugInfoPath(const char* fileName, BString& _infoPath) const; diff --git a/src/apps/debugger/dwarf/DwarfManager.cpp b/src/apps/debugger/dwarf/DwarfManager.cpp index b6fb6bf..4f033da 100644 --- a/src/apps/debugger/dwarf/DwarfManager.cpp +++ b/src/apps/debugger/dwarf/DwarfManager.cpp @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -11,6 +12,7 @@ #include <AutoLocker.h> #include "DwarfFile.h" +#include "DwarfFileLoadingState.h" DwarfManager::DwarfManager() @@ -33,26 +35,49 @@ DwarfManager::Init() status_t -DwarfManager::LoadFile(const char* fileName, DwarfFile*& _file) +DwarfManager::LoadFile(const char* fileName, DwarfFileLoadingState& _state) { AutoLocker<DwarfManager> locker(this); - DwarfFile* file = new(std::nothrow) DwarfFile; - if (file == NULL) - return B_NO_MEMORY; + DwarfFile* file = _state.dwarfFile; + BReference<DwarfFile> fileReference; + if (file == NULL) { + file = new(std::nothrow) DwarfFile; + if (file == NULL) + return B_NO_MEMORY; + fileReference.SetTo(file, true); + _state.dwarfFile = file; + } else + fileReference.SetTo(file); + + status_t error; + if (_state.externalInfoFileName.IsEmpty()) { + error = file->StartLoading(fileName, _state.externalInfoFileName); + if (error != B_OK) { + // only preserve state in the failure case if an external + // debug information reference was found, but the corresponding + // file could not be located on disk. + _state.state = _state.externalInfoFileName.IsEmpty() + ? DWARF_FILE_LOADING_STATE_FAILED + : DWARF_FILE_LOADING_STATE_USER_INPUT_NEEDED; - BReference<DwarfFile> fileReference(file, true); - status_t error = file->Load(fileName); + return error; + } + } + + error = file->Load(_state.locatedExternalInfoPath); if (error != B_OK) { + _state.state = DWARF_FILE_LOADING_STATE_FAILED; return error; } fFiles.Add(file); + fileReference.Detach(); - // we keep the initial reference for ourselves + // keep a reference for ourselves in the list. + + _state.state = DWARF_FILE_LOADING_STATE_SUCCEEDED; - file->AcquireReference(); - _file = file; return B_OK; } diff --git a/src/apps/debugger/dwarf/DwarfManager.h b/src/apps/debugger/dwarf/DwarfManager.h index 8da0755..375402f 100644 --- a/src/apps/debugger/dwarf/DwarfManager.h +++ b/src/apps/debugger/dwarf/DwarfManager.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef DWARF_MANAGER_H @@ -11,6 +12,7 @@ class DwarfFile; +struct DwarfFileLoadingState; class DwarfManager { @@ -24,8 +26,10 @@ public: void Unlock() { fLock.Unlock(); } status_t LoadFile(const char* fileName, - DwarfFile*& _file); - // returns a reference + DwarfFileLoadingState& _loadingState); + // _loadingState receives a reference + // to the corresponding DwarfFile. + status_t FinishLoading(); private: diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 1cf7a06..f024bc3 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -1,12 +1,13 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2011-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef JOBS_H #define JOBS_H +#include "ImageDebugInfoLoadingState.h" #include "ImageDebugInfoProvider.h" #include "Types.h" #include "Worker.h" @@ -128,6 +129,8 @@ public: private: SimpleJobKey fKey; Image* fImage; + ImageDebugInfoLoadingState + fState; }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index dc1706c..418873f 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -17,7 +17,8 @@ LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) : fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), - fImage(image) + fImage(image), + fState() { fImage->AcquireReference(); } @@ -47,10 +48,16 @@ LoadImageDebugInfoJob::Do() // create the debug info ImageDebugInfo* debugInfo; status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( - imageInfo, fImage->ImageFile(), debugInfo); + imageInfo, fImage->ImageFile(), fState, debugInfo); // set the result locker.Lock(); + + if (fState.UserInputRequired()) { + // TODO: notify the user interface + return WaitForUserInput(); + } + if (error == B_OK) { error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); debugInfo->ReleaseReference(); ############################################################################ Commit: d9e97187f53201ae200731a0503448c04acec988 URL: http://cgit.haiku-os.org/haiku/commit/?id=d9e9718 Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Tue Jun 10 23:10:53 2014 UTC Debugger: Add file prompt hook to UserInterface. In some circumstances, it may be necessary to ask the user to locate a file from the lower layers. Adds the corresponding hook to UserInterface, and a stub implementation for CommandLineUserInterface. Adds full implementation for GraphicalUserInterface. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index e0efd00..ab6d8c5 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -72,7 +72,10 @@ enum { MSG_SHOW_WATCH_VARIABLE_PROMPT = 'swvp', MSG_SHOW_CONTAINER_RANGE_PROMPT = 'scrp', MSG_SET_CONTAINER_RANGE = 'chcr', - MSG_GENERATE_DEBUG_REPORT = 'gdrp' + MSG_GENERATE_DEBUG_REPORT = 'gdrp', + + MSG_DEBUG_INFO_NEEDS_USER_INPUT = 'dnui', + MSG_USER_INTERFACE_FILE_CHOSEN = 'uifc' }; diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index cb00459..67fa804 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef USER_INTERFACE_H @@ -67,6 +67,9 @@ public: = 0; // returns -1, if not implemented or user // cannot be asked + + virtual status_t SynchronouslyAskUserForFile(entry_ref* _ref) + = 0; }; diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index ab2c837..33a467f 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2011-2014, Rene Gollent, rene@xxxxxxxxxxx. * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxx. * Distributed under the terms of the MIT License. */ @@ -201,6 +201,13 @@ CommandLineUserInterface::SynchronouslyAskUser(const char* title, } +status_t +CommandLineUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) +{ + return B_UNSUPPORTED; +} + + void CommandLineUserInterface::Run() { diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h index 12d479c..b89e634 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2011-2014, Rene Gollent, rene@xxxxxxxxxxx. * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxx. * Distributed under the terms of the MIT License. */ @@ -43,6 +43,7 @@ public: virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3); + virtual status_t SynchronouslyAskUserForFile(entry_ref* _ref); void Run(); // Called by the main thread, when diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp index 136c721..9fd2c6c 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2011-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -8,16 +8,127 @@ #include "GraphicalUserInterface.h" #include <Alert.h> +#include <Autolock.h> +#include <FilePanel.h> +#include <Locker.h> #include "GuiTeamUiSettings.h" +#include "MessageCodes.h" #include "TeamWindow.h" #include "Tracing.h" +// #pragma mark - GraphicalUserInterface::FilePanelHandler + + +class GraphicalUserInterface::FilePanelHandler : public BHandler { +public: + FilePanelHandler(); + virtual ~FilePanelHandler(); + + status_t Init(); + + virtual void MessageReceived(BMessage* message); + + status_t WaitForPanel(); + + void SetCurrentRef(entry_ref* ref); + + BLocker& Locker() + { return fPanelLock; } + +private: + entry_ref* fCurrentRef; + BLocker fPanelLock; + sem_id fPanelWaitSem; +}; + + +GraphicalUserInterface::FilePanelHandler::FilePanelHandler() + : + BHandler("GuiPanelHandler"), + fCurrentRef(NULL), + fPanelLock(), + fPanelWaitSem(-1) +{ +} + + +GraphicalUserInterface::FilePanelHandler::~FilePanelHandler() +{ + if (fPanelWaitSem >= 0) + delete_sem(fPanelWaitSem); +} + + +status_t +GraphicalUserInterface::FilePanelHandler::Init() +{ + fPanelWaitSem = create_sem(0, "FilePanelWaitSem"); + + if (fPanelWaitSem < 0) + return fPanelWaitSem; + + return B_OK; +} + + +void +GraphicalUserInterface::FilePanelHandler::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_USER_INTERFACE_FILE_CHOSEN: + { + entry_ref ref; + if (message->FindRef("refs", &ref) == B_OK + && fCurrentRef != NULL) { + *fCurrentRef = ref; + fCurrentRef = NULL; + } + // fall through + } + + case B_CANCEL: + { + release_sem(fPanelWaitSem); + break; + } + + default: + BHandler::MessageReceived(message); + break; + } +} + + +status_t +GraphicalUserInterface::FilePanelHandler::WaitForPanel() +{ + status_t result = B_OK; + do { + result = acquire_sem(fPanelWaitSem); + } while (result == B_INTERRUPTED); + + return result; +} + + +void +GraphicalUserInterface::FilePanelHandler::SetCurrentRef(entry_ref* ref) +{ + fCurrentRef = ref; +} + + +// #pragma mark - GraphicalUserInterface + + GraphicalUserInterface::GraphicalUserInterface() : fTeamWindow(NULL), - fTeamWindowMessenger(NULL) + fTeamWindowMessenger(NULL), + fFilePanelHandler(NULL), + fFilePanel(NULL) { } @@ -25,6 +136,7 @@ GraphicalUserInterface::GraphicalUserInterface() GraphicalUserInterface::~GraphicalUserInterface() { delete fTeamWindowMessenger; + delete fFilePanel; } @@ -41,6 +153,13 @@ GraphicalUserInterface::Init(Team* team, UserInterfaceListener* listener) try { fTeamWindow = TeamWindow::Create(team, listener); fTeamWindowMessenger = new BMessenger(fTeamWindow); + fFilePanelHandler = new FilePanelHandler(); + status_t error = fFilePanelHandler->Init(); + if (error != B_OK) { + ERROR("Error: Failed to create file panel semaphore!\n"); + return error; + } + fTeamWindow->AddHandler(fFilePanelHandler); // start the message loop fTeamWindow->Hide(); @@ -132,3 +251,28 @@ GraphicalUserInterface::SynchronouslyAskUser(const char* title, return 0; return alert->Go(); } + + +status_t +GraphicalUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) +{ + BAutolock lock(&fFilePanelHandler->Locker()); + + if (fFilePanel == NULL) { + BMessenger messenger(fFilePanelHandler); + BMessage* message = new(std::nothrow) BMessage( + MSG_USER_INTERFACE_FILE_CHOSEN); + if (message == NULL) + return B_NO_MEMORY; + ObjectDeleter<BMessage> messageDeleter(message); + fFilePanel = new(std::nothrow) BFilePanel(B_OPEN_PANEL, + &messenger, NULL, B_FILE_NODE, false, message); + if (fFilePanel == NULL) + return B_NO_MEMORY; + messageDeleter.Detach(); + } + + fFilePanelHandler->SetCurrentRef(_ref); + fFilePanel->Show(); + return fFilePanelHandler->WaitForPanel(); +} diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h index 60b7d5b..ef79cfd 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef GRAPHICAL_USER_INTERFACE_H @@ -9,6 +10,8 @@ #include "UserInterface.h" +class BFilePanel; +class BHandler; class BMessenger; class TeamWindow; @@ -36,10 +39,15 @@ public: virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3); + virtual status_t SynchronouslyAskUserForFile(entry_ref* _ref); +private: + class FilePanelHandler; private: TeamWindow* fTeamWindow; BMessenger* fTeamWindowMessenger; + FilePanelHandler* fFilePanelHandler; + BFilePanel* fFilePanel; }; ############################################################################ Commit: 331511009c7f769f4c4dad00c7a31e2d926e7731 URL: http://cgit.haiku-os.org/haiku/commit/?id=3315110 Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Tue Jun 10 23:12:45 2014 UTC Debugger: Start adding the groundwork for load state handlers. Adds abstract class ImageDebugLoadingStateHandler which simply contains two hooks, which allow one to a) ask it if it supports a handling a particular type of loading state, and b) if so, ask it to attempt to handle that case, given the passed in user interface object. Also adds implementing subclass for DwarfImageDebugInfo, currently intended primarily to handle the case of missing external debug information. At present, this just supports prompting the user to find/install the file, but eventually this will be extended to also support automatically installing the corresponding debug information package, if applicable. Finally, adds ImageDebugLoadingStateHandlerRoster, which acts as a front end for matching up a given loading state with the appropriate handler. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp index 46e146d..dbf24e3 100644 --- a/src/apps/debugger/Debugger.cpp +++ b/src/apps/debugger/Debugger.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx. - * Copyright 2011-2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2011-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ @@ -24,6 +24,7 @@ #include "CommandLineUserInterface.h" #include "GraphicalUserInterface.h" +#include "ImageDebugLoadingStateHandlerRoster.h" #include "MessageCodes.h" #include "SettingsManager.h" #include "SignalSet.h" @@ -212,6 +213,10 @@ global_init() if (error != B_OK) return error; + error = ImageDebugLoadingStateHandlerRoster::CreateDefault(); + if (error != B_OK) + return error; + return B_OK; } @@ -402,6 +407,7 @@ Debugger::~Debugger() { ValueHandlerRoster::DeleteDefault(); TypeHandlerRoster::DeleteDefault(); + ImageDebugLoadingStateHandlerRoster::DeleteDefault(); } diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 95550ff..e7f38af 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -14,6 +14,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86_64 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) controllers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info loading_state_handlers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; @@ -112,6 +113,8 @@ Application Debugger : ImageDebugInfo.cpp ImageDebugInfoLoadingState.cpp ImageDebugInfoProvider.cpp + ImageDebugLoadingStateHandler.cpp + ImageDebugLoadingStateHandlerRoster.cpp NoOpStackFrameDebugInfo.cpp SpecificImageDebugInfo.cpp SpecificImageDebugInfoLoadingState.cpp @@ -119,6 +122,9 @@ Application Debugger : StackFrameDebugInfo.cpp TeamDebugInfo.cpp + # debug_info/loading_state_handlers + DwarfLoadingStateHandler.cpp + # debugger_interface DebugEvent.cpp DebuggerInterface.cpp diff --git a/src/apps/debugger/debug_info/ImageDebugLoadingStateHandler.cpp b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandler.cpp new file mode 100644 index 0000000..f57cd29 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandler.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "ImageDebugLoadingStateHandler.h" + + +ImageDebugLoadingStateHandler::~ImageDebugLoadingStateHandler() +{ +} diff --git a/src/apps/debugger/debug_info/ImageDebugLoadingStateHandler.h b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandler.h new file mode 100644 index 0000000..24f54f4 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandler.h @@ -0,0 +1,30 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_DEBUG_LOADING_STATE_HANDLER_H +#define IMAGE_DEBUG_LOADING_STATE_HANDLER_H + + +#include <Referenceable.h> + + +class SpecificImageDebugInfoLoadingState; +class UserInterface; + + +class ImageDebugLoadingStateHandler : public BReferenceable { +public: + virtual ~ImageDebugLoadingStateHandler(); + + virtual bool SupportsState( + SpecificImageDebugInfoLoadingState* state) + = 0; + + virtual void HandleState( + SpecificImageDebugInfoLoadingState* state, + UserInterface* interface) = 0; +}; + + +#endif // IMAGE_DEBUG_LOADING_STATE_HANDLER_H diff --git a/src/apps/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.cpp b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.cpp new file mode 100644 index 0000000..8745d21 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "ImageDebugLoadingStateHandlerRoster.h" + +#include <new> + +#include <AutoDeleter.h> +#include <AutoLocker.h> + +#include "DwarfLoadingStateHandler.h" +#include "ImageDebugInfoLoadingState.h" +#include "ImageDebugLoadingStateHandler.h" +#include "SpecificImageDebugInfoLoadingState.h" + + +/*static*/ ImageDebugLoadingStateHandlerRoster* + ImageDebugLoadingStateHandlerRoster::sDefaultInstance = NULL; + + +ImageDebugLoadingStateHandlerRoster::ImageDebugLoadingStateHandlerRoster() + : + fLock("type handler roster") +{ +} + + +ImageDebugLoadingStateHandlerRoster::~ImageDebugLoadingStateHandlerRoster() +{ +} + + +/*static*/ ImageDebugLoadingStateHandlerRoster* +ImageDebugLoadingStateHandlerRoster::Default() +{ + return sDefaultInstance; +} + + +/*static*/ status_t +ImageDebugLoadingStateHandlerRoster::CreateDefault() +{ + if (sDefaultInstance != NULL) + return B_OK; + + ImageDebugLoadingStateHandlerRoster* roster + = new(std::nothrow) ImageDebugLoadingStateHandlerRoster; + if (roster == NULL) + return B_NO_MEMORY; + ObjectDeleter<ImageDebugLoadingStateHandlerRoster> rosterDeleter(roster); + + status_t error = roster->Init(); + if (error != B_OK) + return error; + + error = roster->RegisterDefaultHandlers(); + if (error != B_OK) + return error; + + sDefaultInstance = rosterDeleter.Detach(); + return B_OK; +} + + +/*static*/ void +ImageDebugLoadingStateHandlerRoster::DeleteDefault() +{ + ImageDebugLoadingStateHandlerRoster* roster = sDefaultInstance; + sDefaultInstance = NULL; + delete roster; +} + + +status_t +ImageDebugLoadingStateHandlerRoster::Init() +{ + return fLock.InitCheck(); +} + + +status_t +ImageDebugLoadingStateHandlerRoster::RegisterDefaultHandlers() +{ + ImageDebugLoadingStateHandler* handler; + BReference<ImageDebugLoadingStateHandler> handlerReference; + + handler = new(std::nothrow) DwarfLoadingStateHandler(); + if (handler == NULL) + return B_NO_MEMORY; + handlerReference.SetTo(handler, true); + + if (!RegisterHandler(handler)) + return B_NO_MEMORY; + + return B_OK; +} + + +status_t +ImageDebugLoadingStateHandlerRoster::FindStateHandler( + SpecificImageDebugInfoLoadingState* state, + ImageDebugLoadingStateHandler*& _handler) +{ + AutoLocker<BLocker> locker(fLock); + + bool found = false; + ImageDebugLoadingStateHandler* handler = NULL; + for (int32 i = 0; (handler = fStateHandlers.ItemAt(i)); i++) { + if ((found = handler->SupportsState(state))) + break; + } + + if (!found) + return B_ENTRY_NOT_FOUND; + + handler->AcquireReference(); + _handler = handler; + return B_OK; +} + + +bool +ImageDebugLoadingStateHandlerRoster::RegisterHandler( + ImageDebugLoadingStateHandler* handler) +{ + if (!fStateHandlers.AddItem(handler)) + return false; + + handler->AcquireReference(); + return true; +} + + +void +ImageDebugLoadingStateHandlerRoster::UnregisterHandler( + ImageDebugLoadingStateHandler* handler) +{ + if (fStateHandlers.RemoveItem(handler)) + handler->ReleaseReference(); +} diff --git a/src/apps/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.h b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.h new file mode 100644 index 0000000..6731ae2 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugLoadingStateHandlerRoster.h @@ -0,0 +1,56 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_DEBUG_LOADING_STATE_HANDLER_ROSTER_H +#define IMAGE_DEBUG_LOADING_STATE_HANDLER_ROSTER_H + + +#include <Locker.h> +#include <ObjectList.h> + + +class ImageDebugLoadingStateHandler; +class SpecificImageDebugInfoLoadingState; + + +typedef BObjectList<ImageDebugLoadingStateHandler> LoadingStateHandlerList; + + +class ImageDebugLoadingStateHandlerRoster { +public: + ImageDebugLoadingStateHandlerRoster(); + ~ImageDebugLoadingStateHandlerRoster(); + + static ImageDebugLoadingStateHandlerRoster* + Default(); + static status_t CreateDefault(); + static void DeleteDefault(); + + status_t Init(); + status_t RegisterDefaultHandlers(); + + status_t FindStateHandler( + SpecificImageDebugInfoLoadingState* state, + ImageDebugLoadingStateHandler*& + _handler); + // returns a reference + + bool RegisterHandler( + ImageDebugLoadingStateHandler* + handler); + void UnregisterHandler( + ImageDebugLoadingStateHandler* + handler); + +private: + BLocker fLock; + LoadingStateHandlerList + fStateHandlers; + static ImageDebugLoadingStateHandlerRoster* + sDefaultInstance; +}; + + +#endif // IMAGE_DEBUG_LOADING_STATE_HANDLER_ROSTER_H + diff --git a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp new file mode 100644 index 0000000..21b58b5 --- /dev/null +++ b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp @@ -0,0 +1,73 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "DwarfLoadingStateHandler.h" + +#include <Entry.h> +#include <Path.h> + +#include "DwarfFile.h" +#include "DwarfImageDebugInfoLoadingState.h" +#include "Tracing.h" +#include "UserInterface.h" + + +DwarfLoadingStateHandler::DwarfLoadingStateHandler() + : + ImageDebugLoadingStateHandler() +{ +} + + +DwarfLoadingStateHandler::~DwarfLoadingStateHandler() +{ +} + + +bool +DwarfLoadingStateHandler::SupportsState( + SpecificImageDebugInfoLoadingState* state) +{ + return dynamic_cast<DwarfImageDebugInfoLoadingState*>(state) != NULL; +} + + +void +DwarfLoadingStateHandler::HandleState( + SpecificImageDebugInfoLoadingState* state, UserInterface* interface) +{ + DwarfImageDebugInfoLoadingState* dwarfState + = dynamic_cast<DwarfImageDebugInfoLoadingState*>(state); + + if (dwarfState == NULL) { + ERROR("DwarfLoadingStateHandler::HandleState() passed " + "non-dwarf state object %p.", state); + return; + } + + DwarfFileLoadingState& fileState = dwarfState->GetFileState(); + + // TODO: if the image in question is packaged, query if it has a + // corresponding debug info package. If so, offer to install it and + // then locate the file automatically rather than forcing the user to + // locate the file manually. + BString message; + message.SetToFormat("The debug information file '%s' for image '%s' is " + "missing. Please locate it if possible.", + fileState.externalInfoFileName.String(), fileState.dwarfFile->Name()); + int32 choice = interface->SynchronouslyAskUser("Debug info missing", + message.String(), "Locate", "Skip", NULL); + + if (choice == 0) { + entry_ref ref; + interface->SynchronouslyAskUserForFile(&ref); + BPath path(&ref); + if (path.InitCheck() == B_OK) + fileState.locatedExternalInfoPath = path.Path(); + } + + fileState.state = DWARF_FILE_LOADING_STATE_USER_INPUT_PROVIDED; +} diff --git a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.h b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.h new file mode 100644 index 0000000..18bbb00 --- /dev/null +++ b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.h @@ -0,0 +1,27 @@ +/* + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_LOADING_STATE_HANDLER +#define DWARF_LOADING_STATE_HANDLER + + +#include "ImageDebugLoadingStateHandler.h" + + +class DwarfLoadingStateHandler : public ImageDebugLoadingStateHandler { +public: + DwarfLoadingStateHandler(); + virtual ~DwarfLoadingStateHandler(); + + virtual bool SupportsState( + SpecificImageDebugInfoLoadingState* state); + + virtual void HandleState( + SpecificImageDebugInfoLoadingState* state, + UserInterface* interface); + +}; + + +#endif // DWARF_LOADING_STATE_HANDLER_H ############################################################################ Revision: hrev47378 Commit: d44d8207a86103afa47f1862c06ff46e46e1cb33 URL: http://cgit.haiku-os.org/haiku/commit/?id=d44d820 Author: Rene Gollent <rene@xxxxxxxxxxx> Date: Sat Jun 14 00:25:13 2014 UTC Ticket: https://dev.haiku-os.org/ticket/10138 Debugger: Finish handling of missing debug information. Add a listener interface for LoadImageDebugInfoJob that allows it to request user assistance based on its current state. Adjust callers to pass in said listener accordingly. Implement the aforementioned listener interface in TeamDebugger, and use the loading state handler roster to find the appropriate handler / handle the request. This implements most of what's needed for #10138, the main piece still missing is for the dwarf handler to detect whether the image in question comes from a package, and if so, to offer to install the corresponding debug information package rather than locating the file manually, assuming such a package exists. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 5be1681..d084e22 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); } @@ -1122,6 +1139,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) { BMessage message(MSG_THREAD_STATE_CHANGED); @@ -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 c91fc58..46fa880 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@xxxxxx. - * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx. * Distributed under the terms of the MIT License. */ #ifndef TEAM_DEBUGGER_H @@ -13,6 +13,7 @@ #include <debug_support.h> #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 3a1a02f..a9653c2 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@xxxxxx. - * Copyright 2010-2013, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2010-2014, Rene Gollent, rene@xxxxxxxxxxx. * 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 3bbff41..eb80905 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@xxxxxx. + * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx. * 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 0bc286e..d0b28ce 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 f024bc3..bc5df71 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<ImageDebugInfoJobListener> 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 418873f..600055c 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx. + * Copyright 2012-2014, Rene Gollent, rene@xxxxxxxxxxx. * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx. * 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<Team> 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); +} +