* Made FunctionID abstract. There are now two implementing subclasses,
SourceFunctionID (where we know the souce location of the function) and ImageFunctionID (where we don't know the source location). Made the classes archivable. * Added support to find functions by ID. * Improved user breakpoint handling. We can now "install" a breakpoint before we even know the function instances in which to install it. Whenever image debug information become available, breakpoints are installed in the concerned function instances of the respective image. * Always trigger loading image debug info as soon as we become aware of an image. * Implemented a settings management mechanism. ATM only the breakpoint locations for debugged teams are persisted. This seriously improves the debugging fun, though. :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31728 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -19,14 +19,17 @@
|
||||
#include "debug_utils.h"
|
||||
|
||||
#include "BreakpointManager.h"
|
||||
#include "BreakpointSetting.h"
|
||||
#include "CpuState.h"
|
||||
#include "DebuggerInterface.h"
|
||||
#include "FileManager.h"
|
||||
#include "Function.h"
|
||||
#include "FunctionID.h"
|
||||
#include "ImageDebugInfo.h"
|
||||
#include "Jobs.h"
|
||||
#include "LocatableFile.h"
|
||||
#include "MessageCodes.h"
|
||||
#include "SettingsManager.h"
|
||||
#include "SourceCode.h"
|
||||
#include "SpecificImageDebugInfo.h"
|
||||
#include "StackFrame.h"
|
||||
@@ -34,6 +37,7 @@
|
||||
#include "Statement.h"
|
||||
#include "SymbolInfo.h"
|
||||
#include "TeamDebugInfo.h"
|
||||
#include "TeamSettings.h"
|
||||
#include "Variable.h"
|
||||
|
||||
// #pragma mark - ImageHandler
|
||||
@@ -116,10 +120,11 @@ struct TeamDebugger::ImageHandlerHashDefinition {
|
||||
// #pragma mark - TeamDebugger
|
||||
|
||||
|
||||
TeamDebugger::TeamDebugger(Listener* listener)
|
||||
TeamDebugger::TeamDebugger(Listener* listener, SettingsManager* settingsManager)
|
||||
:
|
||||
BLooper("team debugger"),
|
||||
fListener(listener),
|
||||
fSettingsManager(settingsManager),
|
||||
fTeam(NULL),
|
||||
fTeamID(-1),
|
||||
fImageHandlers(NULL),
|
||||
@@ -137,6 +142,9 @@ TeamDebugger::TeamDebugger(Listener* listener)
|
||||
|
||||
TeamDebugger::~TeamDebugger()
|
||||
{
|
||||
if (fTeam != NULL)
|
||||
_SaveSettings();
|
||||
|
||||
AutoLocker<BLooper> locker(this);
|
||||
|
||||
fTerminating = true;
|
||||
@@ -192,6 +200,9 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
||||
bool targetIsLocal = true;
|
||||
// TODO: Support non-local targets!
|
||||
|
||||
// the first thing we want to do when running
|
||||
PostMessage(MSG_LOAD_SETTINGS);
|
||||
|
||||
fTeamID = teamID;
|
||||
|
||||
// create debugger interface
|
||||
@@ -321,6 +332,8 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
||||
return error;
|
||||
if (image->Type() == B_APP_IMAGE)
|
||||
appImage = image;
|
||||
|
||||
ImageDebugInfoRequested(image);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,6 +459,16 @@ TeamDebugger::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_IMAGE_DEBUG_INFO_CHANGED:
|
||||
{
|
||||
int32 imageID;
|
||||
if (message->FindInt32("image", &imageID) != B_OK)
|
||||
break;
|
||||
|
||||
_HandleImageDebugInfoChanged(imageID);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_IMAGE_FILE_CHANGED:
|
||||
{
|
||||
int32 imageID;
|
||||
@@ -464,8 +487,13 @@ TeamDebugger::MessageReceived(BMessage* message)
|
||||
|
||||
_HandleDebuggerMessage(event);
|
||||
delete event;
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_LOAD_SETTINGS:
|
||||
_LoadSettings();
|
||||
break;
|
||||
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
break;
|
||||
@@ -661,6 +689,15 @@ TeamDebugger::ThreadStackTraceChanged(const ::Team::ThreadEvent& event)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::ImageDebugInfoChanged(const ::Team::ImageEvent& event)
|
||||
{
|
||||
BMessage message(MSG_IMAGE_DEBUG_INFO_CHANGED);
|
||||
message.AddInt32("image", event.GetImage()->ID());
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
TeamDebugger::_DebugEventListenerEntry(void* data)
|
||||
{
|
||||
@@ -850,17 +887,39 @@ TeamDebugger::_HandleImageDeleted(ImageDeletedEvent* event)
|
||||
|
||||
ImageHandler* imageHandler = fImageHandlers->Lookup(
|
||||
event->GetImageInfo().ImageID());
|
||||
if (imageHandler != NULL) {
|
||||
fImageHandlers->Remove(imageHandler);
|
||||
imageHandler->ReleaseReference();
|
||||
}
|
||||
if (imageHandler == NULL)
|
||||
return false;
|
||||
|
||||
// TODO: Remove breakpoints in the image!
|
||||
fImageHandlers->Remove(imageHandler);
|
||||
Reference<ImageHandler> imageHandlerReference(imageHandler, true);
|
||||
locker.Unlock();
|
||||
|
||||
// remove breakpoints in the image
|
||||
fBreakpointManager->RemoveImageBreakpoints(imageHandler->GetImage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
|
||||
{
|
||||
// get the image (via the image handler)
|
||||
AutoLocker< ::Team> locker(fTeam);
|
||||
ImageHandler* imageHandler = fImageHandlers->Lookup(imageID);
|
||||
if (imageHandler == NULL)
|
||||
return;
|
||||
|
||||
Image* image = imageHandler->GetImage();
|
||||
Reference<Image> imageReference(image);
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// update breakpoints in the image
|
||||
fBreakpointManager->UpdateImageBreakpoints(image);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_HandleImageFileChanged(image_id imageID)
|
||||
{
|
||||
@@ -918,8 +977,16 @@ printf(" function: %p\n", function);
|
||||
target_addr_t relativeAddress = address - functionInstance->Address();
|
||||
printf(" relative address: %#llx, source location: (%ld, %ld)\n", relativeAddress, sourceLocation.Line(), sourceLocation.Column());
|
||||
|
||||
// get function id
|
||||
FunctionID* functionID = functionInstance->GetFunctionID();
|
||||
if (functionID == NULL)
|
||||
return;
|
||||
Reference<FunctionID> functionIDReference(functionID, true);
|
||||
|
||||
// create the user breakpoint
|
||||
userBreakpoint = new(std::nothrow) UserBreakpoint(function);
|
||||
userBreakpoint = new(std::nothrow) UserBreakpoint(
|
||||
UserBreakpointLocation(functionID, function->SourceFile(),
|
||||
sourceLocation, relativeAddress));
|
||||
if (userBreakpoint == NULL)
|
||||
return;
|
||||
userBreakpointReference.SetTo(userBreakpoint, true);
|
||||
@@ -1027,6 +1094,8 @@ TeamDebugger::_AddImage(const ImageInfo& imageInfo, Image** _image)
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
ImageDebugInfoRequested(image);
|
||||
|
||||
ImageHandler* imageHandler = new(std::nothrow) ImageHandler(this, image);
|
||||
if (imageHandler != NULL)
|
||||
fImageHandlers->Insert(imageHandler);
|
||||
@@ -1038,6 +1107,67 @@ TeamDebugger::_AddImage(const ImageInfo& imageInfo, Image** _image)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_LoadSettings()
|
||||
{
|
||||
// get the team name
|
||||
AutoLocker< ::Team> locker(fTeam);
|
||||
BString teamName = fTeam->Name();
|
||||
locker.Unlock();
|
||||
|
||||
// load the settings
|
||||
TeamSettings settings;
|
||||
if (fSettingsManager->LoadTeamSettings(teamName, settings) != B_OK)
|
||||
return;
|
||||
|
||||
// create the saved breakpoints
|
||||
for (int32 i = 0; const BreakpointSetting* breakpointSetting
|
||||
= settings.BreakpointAt(i); i++) {
|
||||
if (breakpointSetting->GetFunctionID() == NULL)
|
||||
continue;
|
||||
|
||||
// get the source file, if any
|
||||
LocatableFile* sourceFile = NULL;
|
||||
if (breakpointSetting->SourceFile().Length() > 0) {
|
||||
sourceFile = fFileManager->GetSourceFile(
|
||||
breakpointSetting->SourceFile());
|
||||
if (sourceFile == NULL)
|
||||
continue;
|
||||
}
|
||||
Reference<LocatableFile> sourceFileReference(sourceFile, true);
|
||||
|
||||
// create the breakpoint
|
||||
UserBreakpointLocation location(breakpointSetting->GetFunctionID(),
|
||||
sourceFile, breakpointSetting->GetSourceLocation(),
|
||||
breakpointSetting->RelativeAddress());
|
||||
|
||||
UserBreakpoint* breakpoint = new(std::nothrow) UserBreakpoint(location);
|
||||
if (breakpoint == NULL)
|
||||
return;
|
||||
Reference<UserBreakpoint> breakpointReference(breakpoint, true);
|
||||
|
||||
// install it
|
||||
fBreakpointManager->InstallUserBreakpoint(breakpoint,
|
||||
breakpointSetting->IsEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_SaveSettings()
|
||||
{
|
||||
// get the settings
|
||||
AutoLocker< ::Team> locker(fTeam);
|
||||
TeamSettings settings;
|
||||
if (settings.SetTo(fTeam) != B_OK)
|
||||
return;
|
||||
locker.Unlock();
|
||||
|
||||
// save the settings
|
||||
fSettingsManager->SaveTeamSettings(settings);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_NotifyUser(const char* title, const char* text,...)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user