Skip to content

Commit

Permalink
Debugger: Implement #9783.
Browse files Browse the repository at this point in the history
TeamDebugger:
- When we're notified that the target team has called exec(), take all
  necessary steps to prepare. These include saving settings for the old
  team, clearing out breakpoints, resetting signal dispositions, and
  removing the old team's image list. Also set a flag indicating an exec
  is pending for later processing.
- On image load notification, if the pending flag is set, check if the
  new image is the app image, and if so update the team's name to
  the new image, load that respective team's settings, and set a
  temporary breakpoint in its main() so the user has a chance to
  perform any additional desired actions before starting execution
  in the new executable.
  • Loading branch information
anevilyak committed Jul 26, 2015
1 parent 10bbf8c commit 9123fde
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 9 deletions.
83 changes: 74 additions & 9 deletions src/apps/debugger/controllers/TeamDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ TeamDebugger::TeamDebugger(Listener* listener, UserInterface* userInterface,
fTerminating(false),
fKillTeamOnQuit(false),
fCommandLineArgc(0),
fCommandLineArgv(NULL)
fCommandLineArgv(NULL),
fExecPending(false)
{
fUserInterface->AcquireReference();
}
Expand Down Expand Up @@ -454,7 +455,8 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, int argc,
// set team debugging flags
fDebuggerInterface->SetTeamDebuggingFlags(
B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_IMAGES
| B_TEAM_DEBUG_POST_SYSCALL | B_TEAM_DEBUG_SIGNALS);
| B_TEAM_DEBUG_POST_SYSCALL | B_TEAM_DEBUG_SIGNALS
| B_TEAM_DEBUG_TEAM_CREATION);

// get the initial state of the team
AutoLocker< ::Team> teamLocker(fTeam);
Expand Down Expand Up @@ -1556,10 +1558,15 @@ TeamDebugger::_HandleDebuggerMessage(DebugEvent* event)
break;
}
case B_DEBUGGER_MESSAGE_TEAM_EXEC:
{
TRACE_EVENTS("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %" B_PRId32 "\n",
event->Team());
// TODO: Handle!

TeamExecEvent* teamEvent
= dynamic_cast<TeamExecEvent*>(event);
_PrepareForTeamExec(teamEvent);
break;
}
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
{
ThreadCreatedEvent* threadEvent
Expand Down Expand Up @@ -1849,6 +1856,43 @@ TeamDebugger::_HandlePostSyscall(PostSyscallEvent* event)
}


void
TeamDebugger::_PrepareForTeamExec(TeamExecEvent* event)
{
// NB: must be called with team lock held.

_SaveSettings();

// when notified of exec, we need to clear out data related
// to the old team.
const ImageList& images = fTeam->Images();

for (ImageList::ConstIterator it = images.GetIterator();
Image* image = it.Next();) {
fBreakpointManager->RemoveImageBreakpoints(image);
}

BObjectList<UserBreakpoint> breakpointsToRemove(20, false);
const UserBreakpointList& breakpoints = fTeam->UserBreakpoints();
for (UserBreakpointList::ConstIterator it = breakpoints.GetIterator();
UserBreakpoint* breakpoint = it.Next();) {
breakpointsToRemove.AddItem(breakpoint);
breakpoint->AcquireReference();
}

for (int32 i = 0; i < breakpointsToRemove.CountItems(); i++) {
UserBreakpoint* breakpoint = breakpointsToRemove.ItemAt(i);
fTeam->RemoveUserBreakpoint(breakpoint);
fTeam->NotifyUserBreakpointChanged(breakpoint);
breakpoint->ReleaseReference();
}

fTeam->ClearImages();
fTeam->ClearSignalDispositionMappings();
fExecPending = true;
}


void
TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
{
Expand All @@ -1860,10 +1904,22 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)

Image* image = imageHandler->GetImage();
BReference<Image> imageReference(image);
image_debug_info_state state = image->ImageDebugInfoState();

bool handlePostExecSetup = fExecPending && image->Type() == B_APP_IMAGE
&& state != IMAGE_DEBUG_INFO_LOADING;

// this needs to be done first so that breakpoints are loaded.
// otherwise, UpdateImageBreakpoints() won't find the appropriate
// UserBreakpoints to create/install instances for.
if (handlePostExecSetup) {
fTeam->SetName(image->Name());
_LoadSettings();
fExecPending = false;
}

locker.Unlock();

image_debug_info_state state = image->ImageDebugInfoState();
if (state == IMAGE_DEBUG_INFO_LOADED
|| state == IMAGE_DEBUG_INFO_UNAVAILABLE) {
// update breakpoints in the image
Expand All @@ -1875,9 +1931,9 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
fImageInfoPendingThreads->Remove(thread);
ObjectDeleter<ImageInfoPendingThread> threadDeleter(thread);
locker.Lock();
ThreadHandler* handler = _GetThreadHandler(thread->ThreadID());
BReference<ThreadHandler> handlerReference(handler);
if (fTeam->StopOnImageLoad()) {
ThreadHandler* handler = _GetThreadHandler(thread->ThreadID());
BReference<ThreadHandler> handlerReference(handler);

bool stop = true;
const BString& imageName = image->Name();
Expand All @@ -1899,10 +1955,19 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
return;
} else
locker.Unlock();
} else
} else if (handlePostExecSetup) {
// in the case of an exec(), we can't stop in main() until
// the new app image has been loaded, so we know where to
// set the main breakpoint at.
SymbolInfo symbolInfo;
if (fDebuggerInterface->GetSymbolInfo(fTeam->ID(), image->ID(),
"main", B_SYMBOL_TYPE_TEXT, symbolInfo) == B_OK) {
handler->SetBreakpointAndRun(symbolInfo.Address(), false);
}
} else {
locker.Unlock();

fDebuggerInterface->ContinueThread(thread->ThreadID());
fDebuggerInterface->ContinueThread(thread->ThreadID());
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/apps/debugger/controllers/TeamDebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ class TeamDebugger : public BLooper, private UserInterfaceListener,
bool _HandlePostSyscall(
PostSyscallEvent* event);

void _PrepareForTeamExec(TeamExecEvent* event);

void _HandleImageDebugInfoChanged(image_id imageID);
void _HandleImageFileChanged(image_id imageID);

Expand Down Expand Up @@ -259,6 +261,7 @@ class TeamDebugger : public BLooper, private UserInterfaceListener,
TeamSettings fTeamSettings;
int fCommandLineArgc;
const char** fCommandLineArgv;
bool fExecPending;
};


Expand Down

0 comments on commit 9123fde

Please sign in to comment.