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.
This commit is contained in:
Rene Gollent
2014-06-15 11:03:23 -04:00
parent d9e97187f5
commit 331511009c
8 changed files with 354 additions and 1 deletions
+7 -1
View File
@@ -1,6 +1,6 @@
/*
* Copyright 2009-2012, Ingo Weinhold, [email protected].
* Copyright 2011-2013, Rene Gollent, [email protected].
* Copyright 2011-2014, Rene Gollent, [email protected].
* 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();
}
+6
View File
@@ -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
@@ -0,0 +1,12 @@
/*
* Copyright 2014, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ImageDebugLoadingStateHandler.h"
ImageDebugLoadingStateHandler::~ImageDebugLoadingStateHandler()
{
}
@@ -0,0 +1,30 @@
/*
* Copyright 2014, Rene Gollent, [email protected].
* 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
@@ -0,0 +1,143 @@
/*
* Copyright 2014, Rene Gollent, [email protected].
* 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();
}
@@ -0,0 +1,56 @@
/*
* Copyright 2014, Rene Gollent, [email protected].
* 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
@@ -0,0 +1,73 @@
/*
* Copyright 2014, Rene Gollent, [email protected].
* 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;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2014, Rene Gollent, [email protected].
* 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