void BreakpointsView::_HandleBreakpointAction(uint32 action) { if (fListener == NULL) return; for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT) { UserBreakpoint* breakpoint = proxy->GetBreakpoint(); if (action == MSG_ENABLE_BREAKPOINT && !breakpoint->IsEnabled()) fListener->SetBreakpointEnabledRequested(breakpoint, true); else if (action == MSG_DISABLE_BREAKPOINT && breakpoint->IsEnabled()) { fListener->SetBreakpointEnabledRequested(breakpoint, false); } else if (action == MSG_CLEAR_BREAKPOINT) fListener->ClearBreakpointRequested(breakpoint); } else { Watchpoint* watchpoint = proxy->GetWatchpoint(); if (action == MSG_ENABLE_BREAKPOINT && !watchpoint->IsEnabled()) fListener->SetWatchpointEnabledRequested(watchpoint, true); else if (action == MSG_DISABLE_BREAKPOINT && watchpoint->IsEnabled()) { fListener->SetWatchpointEnabledRequested(watchpoint, false); } else if (action == MSG_CLEAR_BREAKPOINT) fListener->ClearWatchpointRequested(watchpoint); } } }
void BreakpointsView::_UpdateButtons() { AutoLocker<Team> teamLocker(fTeam); bool hasEnabled = false; bool hasDisabled = false; bool valid = false; for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); switch (proxy->Type()) { case BREAKPOINT_PROXY_TYPE_BREAKPOINT: { UserBreakpoint* breakpoint = proxy->GetBreakpoint(); if (breakpoint->IsValid()) { valid = true; if (breakpoint->IsEnabled()) hasEnabled = true; else hasDisabled = true; } break; } case BREAKPOINT_PROXY_TYPE_WATCHPOINT: { Watchpoint* watchpoint = proxy->GetWatchpoint(); valid = true; if (watchpoint->IsEnabled()) hasEnabled = true; else hasDisabled = true; break; } default: break; } } if (valid) { // if we have at least one disabled breakpoint in the // selection, we leave the button as an Enable button if (hasEnabled && !hasDisabled) { fToggleBreakpointButton->SetLabel("Disable"); fToggleBreakpointButton->SetMessage( new BMessage(MSG_DISABLE_BREAKPOINT)); } else { fToggleBreakpointButton->SetLabel("Enable"); fToggleBreakpointButton->SetMessage( new BMessage(MSG_ENABLE_BREAKPOINT)); } fToggleBreakpointButton->SetEnabled(true); fRemoveBreakpointButton->SetEnabled(true); } else { fToggleBreakpointButton->SetLabel("Enable"); fToggleBreakpointButton->SetEnabled(false); fRemoveBreakpointButton->SetEnabled(false); } }
void Team::GetBreakpointsForSourceCode(SourceCode* sourceCode, BObjectList<UserBreakpoint>& breakpoints) const { if (DisassembledCode* disassembledCode = dynamic_cast<DisassembledCode*>(sourceCode)) { GetBreakpointsInAddressRange(disassembledCode->StatementAddressRange(), breakpoints); return; } LocatableFile* sourceFile = sourceCode->GetSourceFile(); if (sourceFile == NULL) return; // TODO: This can probably be optimized. Maybe by registering the user // breakpoints with the team and sorting them by source code. for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) { UserBreakpointInstance* userBreakpointInstance = breakpoint->FirstUserBreakpoint(); if (userBreakpointInstance == NULL) continue; UserBreakpoint* userBreakpoint = userBreakpointInstance->GetUserBreakpoint(); if (userBreakpoint->Location().SourceFile() == sourceFile) breakpoints.AddItem(userBreakpoint); } }
bool Update(UserBreakpoint* changedBreakpoint) { if (fTeam == NULL) { for (int32 i = 0; UserBreakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) { breakpoint->ReleaseReference(); } fBreakpoints.MakeEmpty(); return true; } AutoLocker<Team> locker(fTeam); UserBreakpointList::ConstIterator it = fTeam->UserBreakpoints().GetIterator(); UserBreakpoint* newBreakpoint = it.Next(); int32 index = 0; // remove no longer existing breakpoints while (UserBreakpoint* oldBreakpoint = fBreakpoints.ItemAt(index)) { if (oldBreakpoint == newBreakpoint) { if (oldBreakpoint == changedBreakpoint) NotifyRowsChanged(index, 1); index++; newBreakpoint = it.Next(); } else { // TODO: Not particularly efficient! fBreakpoints.RemoveItemAt(index); oldBreakpoint->ReleaseReference(); NotifyRowsRemoved(index, 1); } } // add new breakpoints int32 countBefore = fBreakpoints.CountItems(); while (newBreakpoint != NULL) { if (!fBreakpoints.AddItem(newBreakpoint)) return false; newBreakpoint->AcquireReference(); newBreakpoint = it.Next(); } int32 count = fBreakpoints.CountItems(); if (count > countBefore) NotifyRowsAdded(countBefore, count - countBefore); return true; }
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value) { UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex); if (breakpoint == NULL) return false; const UserBreakpointLocation& location = breakpoint->Location(); switch (columnIndex) { case 0: value.SetTo((int32)breakpoint->IsEnabled()); return true; case 1: value.SetTo(location.GetFunctionID()->FunctionName(), B_VARIANT_DONT_COPY_DATA); return true; case 2: if (LocatableFile* sourceFile = location.SourceFile()) { value.SetTo(sourceFile->Name(), B_VARIANT_DONT_COPY_DATA); return true; } return false; case 3: if (location.SourceFile() != NULL) { value.SetTo(location.GetSourceLocation().Line() + 1); return true; } return false; case 4: if (location.SourceFile() == NULL) { AutoLocker<Team> teamLocker(fTeam); if (UserBreakpointInstance* instance = breakpoint->InstanceAt(0)) { value.SetTo(instance->Address()); return true; } } return false; default: return false; } }
void TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled) { TRACE_CONTROL("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled); // check whether there already is a breakpoint AutoLocker< ::Team> locker(fTeam); Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); UserBreakpoint* userBreakpoint = NULL; if (breakpoint != NULL && breakpoint->FirstUserBreakpoint() != NULL) userBreakpoint = breakpoint->FirstUserBreakpoint()->GetUserBreakpoint(); BReference<UserBreakpoint> userBreakpointReference(userBreakpoint); if (userBreakpoint == NULL) { TRACE_CONTROL(" no breakpoint yet\n"); // get the function at the address Image* image = fTeam->ImageByAddress(address); TRACE_CONTROL(" image: %p\n", image); if (image == NULL) return; ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo(); TRACE_CONTROL(" image debug info: %p\n", imageDebugInfo); if (imageDebugInfo == NULL) return; // TODO: Handle this case by loading the debug info, if possible! FunctionInstance* functionInstance = imageDebugInfo->FunctionAtAddress(address); TRACE_CONTROL(" function instance: %p\n", functionInstance); if (functionInstance == NULL) return; Function* function = functionInstance->GetFunction(); TRACE_CONTROL(" function: %p\n", function); // get the source location for the address FunctionDebugInfo* functionDebugInfo = functionInstance->GetFunctionDebugInfo(); SourceLocation sourceLocation; Statement* breakpointStatement = NULL; if (functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement( functionDebugInfo, address, breakpointStatement) != B_OK) { return; } sourceLocation = breakpointStatement->StartSourceLocation(); breakpointStatement->ReleaseReference(); target_addr_t relativeAddress = address - functionInstance->Address(); TRACE_CONTROL(" relative address: %#llx, source location: " "(%ld, %ld)\n", relativeAddress, sourceLocation.Line(), sourceLocation.Column()); // get function id FunctionID* functionID = functionInstance->GetFunctionID(); if (functionID == NULL) return; BReference<FunctionID> functionIDReference(functionID, true); // create the user breakpoint userBreakpoint = new(std::nothrow) UserBreakpoint( UserBreakpointLocation(functionID, function->SourceFile(), sourceLocation, relativeAddress)); if (userBreakpoint == NULL) return; userBreakpointReference.SetTo(userBreakpoint, true); TRACE_CONTROL(" created user breakpoint: %p\n", userBreakpoint); // iterate through all function instances and create // UserBreakpointInstances for (FunctionInstanceList::ConstIterator it = function->Instances().GetIterator(); FunctionInstance* instance = it.Next();) { TRACE_CONTROL(" function instance %p: range: %#llx - %#llx\n", instance, instance->Address(), instance->Address() + instance->Size()); // get the breakpoint address for the instance target_addr_t instanceAddress = 0; if (instance == functionInstance) { instanceAddress = address; } else if (functionInstance->SourceFile() != NULL) { // We have a source file, so get the address for the source // location. Statement* statement = NULL; functionDebugInfo = instance->GetFunctionDebugInfo(); functionDebugInfo->GetSpecificImageDebugInfo() ->GetStatementAtSourceLocation(functionDebugInfo, sourceLocation, statement); if (statement != NULL) { instanceAddress = statement->CoveringAddressRange().Start(); // TODO: What about BreakpointAllowed()? statement->ReleaseReference(); } } TRACE_CONTROL(" breakpoint address using source info: %llx\n", instanceAddress); if (instanceAddress == 0) { // No source file (or we failed getting the statement), so try // to use the same relative address. if (relativeAddress > instance->Size()) continue; instanceAddress = instance->Address() + relativeAddress; } TRACE_CONTROL(" final breakpoint address: %llx\n", instanceAddress); UserBreakpointInstance* breakpointInstance = new(std::nothrow) UserBreakpointInstance(userBreakpoint, instanceAddress); if (breakpointInstance == NULL || !userBreakpoint->AddInstance(breakpointInstance)) { delete breakpointInstance; return; } TRACE_CONTROL(" breakpoint instance: %p\n", breakpointInstance); } } locker.Unlock(); _HandleSetUserBreakpoint(userBreakpoint, enabled); }