void BreakpointManager::UninstallTemporaryBreakpoint(target_addr_t address, BreakpointClient* client) { AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); if (breakpoint == NULL) return; // remove the client breakpoint->RemoveClient(client); // check whether the breakpoint needs to be uninstalled bool uninstall = !breakpoint->ShouldBeInstalled() && breakpoint->IsInstalled(); // if unused remove it BReference<Breakpoint> breakpointReference(breakpoint); if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); teamLocker.Unlock(); if (uninstall) { fDebuggerInterface->UninstallBreakpoint(address); breakpoint->SetInstalled(false); } }
status_t BreakpointManager::InstallTemporaryBreakpoint(target_addr_t address, BreakpointClient* client) { AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); // create a breakpoint, if it doesn't exist yet Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); if (breakpoint == NULL) { Image* image = fTeam->ImageByAddress(address); if (image == NULL) return B_BAD_ADDRESS; breakpoint = new(std::nothrow) Breakpoint(image, address); if (breakpoint == NULL) return B_NO_MEMORY; if (!fTeam->AddBreakpoint(breakpoint)) return B_NO_MEMORY; } BReference<Breakpoint> breakpointReference(breakpoint); // add the client status_t error; if (breakpoint->AddClient(client)) { if (breakpoint->IsInstalled()) return B_OK; // install teamLocker.Unlock(); error = fDebuggerInterface->InstallBreakpoint(address); if (error == B_OK) { breakpoint->SetInstalled(true); return B_OK; } teamLocker.Lock(); breakpoint->RemoveClient(client); } else error = B_NO_MEMORY; // clean up on error if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); return error; }
status_t BreakpointManager::InstallUserBreakpoint(UserBreakpoint* userBreakpoint, bool enabled) { TRACE_CONTROL("BreakpointManager::InstallUserBreakpoint(%p, %d)\n", userBreakpoint, enabled); AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); bool oldEnabled = userBreakpoint->IsEnabled(); if (userBreakpoint->IsValid() && enabled == oldEnabled) { TRACE_CONTROL(" user breakpoint already valid and with same enabled " "state\n"); return B_OK; } // get/create the breakpoints for all instances TRACE_CONTROL(" creating breakpoints for breakpoint instances\n"); status_t error = B_OK; for (int32 i = 0; UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) { TRACE_CONTROL(" breakpoint instance %p\n", instance); if (instance->GetBreakpoint() != NULL) { TRACE_CONTROL(" -> already has breakpoint\n"); continue; } target_addr_t address = instance->Address(); Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); if (breakpoint == NULL) { TRACE_CONTROL(" -> no breakpoint at that address yet\n"); Image* image = fTeam->ImageByAddress(address); if (image == NULL) { TRACE_CONTROL(" -> no image at that address\n"); error = B_BAD_ADDRESS; break; } breakpoint = new(std::nothrow) Breakpoint(image, address); if (breakpoint == NULL || !fTeam->AddBreakpoint(breakpoint)) { delete breakpoint; error = B_NO_MEMORY; break; } } TRACE_CONTROL(" -> adding instance to breakpoint %p\n", breakpoint); breakpoint->AddUserBreakpoint(instance); instance->SetBreakpoint(breakpoint); } // If everything looks good so far mark the user breakpoint according to // its new state. if (error == B_OK) userBreakpoint->SetEnabled(enabled); // notify user breakpoint listeners if (error == B_OK) fTeam->NotifyUserBreakpointChanged(userBreakpoint); teamLocker.Unlock(); // install/uninstall the breakpoints as needed TRACE_CONTROL(" updating breakpoints\n"); if (error == B_OK) { for (int32 i = 0; UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) { TRACE_CONTROL(" breakpoint instance %p\n", instance); error = _UpdateBreakpointInstallation(instance->GetBreakpoint()); if (error != B_OK) break; } } if (error == B_OK) { TRACE_CONTROL(" success, marking user breakpoint valid\n"); // everything went fine -- mark the user breakpoint valid if (!userBreakpoint->IsValid()) { teamLocker.Lock(); userBreakpoint->SetValid(true); userBreakpoint->AcquireReference(); fTeam->AddUserBreakpoint(userBreakpoint); fTeam->NotifyUserBreakpointChanged(userBreakpoint); // notify again -- the breakpoint hadn't been added before teamLocker.Unlock(); } } else { // something went wrong -- revert the situation TRACE_CONTROL(" error, reverting\n"); teamLocker.Lock(); userBreakpoint->SetEnabled(oldEnabled); teamLocker.Unlock(); if (!oldEnabled || !userBreakpoint->IsValid()) { for (int32 i = 0; UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) { Breakpoint* breakpoint = instance->GetBreakpoint(); if (breakpoint == NULL) continue; if (!userBreakpoint->IsValid()) { instance->SetBreakpoint(NULL); breakpoint->RemoveUserBreakpoint(instance); } _UpdateBreakpointInstallation(breakpoint); teamLocker.Lock(); if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); teamLocker.Unlock(); } teamLocker.Lock(); fTeam->NotifyUserBreakpointChanged(userBreakpoint); teamLocker.Unlock(); } } installLocker.Unlock(); return error; }
void BreakpointManager::_UpdateImageBreakpoints(Image* image, bool removeOnly) { AutoLocker<BLocker> installLocker(fLock); AutoLocker<Team> teamLocker(fTeam); // remove obsolete user breakpoint instances BObjectList<Breakpoint> breakpointsToUpdate; for (UserBreakpointList::ConstIterator it = fTeam->UserBreakpoints().GetIterator(); UserBreakpoint* userBreakpoint = it.Next();) { int32 instanceCount = userBreakpoint->CountInstances(); for (int32 i = instanceCount - 1; i >= 0; i--) { UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); Breakpoint* breakpoint = instance->GetBreakpoint(); if (breakpoint == NULL || breakpoint->GetImage() != image) continue; userBreakpoint->RemoveInstanceAt(i); breakpoint->RemoveUserBreakpoint(instance); if (!breakpointsToUpdate.AddItem(breakpoint)) { _UpdateBreakpointInstallation(breakpoint); if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); } delete instance; } } // update breakpoints teamLocker.Unlock(); for (int32 i = 0; Breakpoint* breakpoint = breakpointsToUpdate.ItemAt(i); i++) { _UpdateBreakpointInstallation(breakpoint); } teamLocker.Lock(); for (int32 i = 0; Breakpoint* breakpoint = breakpointsToUpdate.ItemAt(i); i++) { if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); } // add breakpoint instances for function instances in the image (if we have // an image debug info) BObjectList<UserBreakpointInstance> newInstances; ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo(); if (imageDebugInfo == NULL) return; for (UserBreakpointList::ConstIterator it = fTeam->UserBreakpoints().GetIterator(); UserBreakpoint* userBreakpoint = it.Next();) { // get the function Function* function = fTeam->FunctionByID( userBreakpoint->Location().GetFunctionID()); if (function == NULL) continue; const SourceLocation& sourceLocation = userBreakpoint->Location().GetSourceLocation(); target_addr_t relativeAddress = userBreakpoint->Location().RelativeAddress(); // iterate through the function instances for (FunctionInstanceList::ConstIterator it = function->Instances().GetIterator(); FunctionInstance* functionInstance = it.Next();) { if (functionInstance->GetImageDebugInfo() != imageDebugInfo) continue; // get the breakpoint address for the instance target_addr_t instanceAddress = 0; if (functionInstance->SourceFile() != NULL) { // We have a source file, so get the address for the source // location. Statement* statement = NULL; FunctionDebugInfo* functionDebugInfo = functionInstance->GetFunctionDebugInfo(); functionDebugInfo->GetSpecificImageDebugInfo() ->GetStatementAtSourceLocation(functionDebugInfo, sourceLocation, statement); if (statement != NULL) { instanceAddress = statement->CoveringAddressRange().Start(); // TODO: What about BreakpointAllowed()? statement->ReleaseReference(); // TODO: Make sure we do hit the function in question! } } if (instanceAddress == 0) { // No source file (or we failed getting the statement), so try // to use the same relative address. if (relativeAddress > functionInstance->Size()) continue; instanceAddress = functionInstance->Address() + relativeAddress; // TODO: Make sure it does at least hit an instruction! } // create the user breakpoint instance UserBreakpointInstance* instance = new(std::nothrow) UserBreakpointInstance(userBreakpoint, instanceAddress); if (instance == NULL || !newInstances.AddItem(instance)) { delete instance; continue; } if (!userBreakpoint->AddInstance(instance)) { newInstances.RemoveItemAt(newInstances.CountItems() - 1); delete instance; } // get/create the breakpoint for the address target_addr_t address = instance->Address(); Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); if (breakpoint == NULL) { breakpoint = new(std::nothrow) Breakpoint(image, address); if (breakpoint == NULL || !fTeam->AddBreakpoint(breakpoint)) { delete breakpoint; break; } } breakpoint->AddUserBreakpoint(instance); instance->SetBreakpoint(breakpoint); } } // install the breakpoints for the new user breakpoint instances teamLocker.Unlock(); for (int32 i = 0; UserBreakpointInstance* instance = newInstances.ItemAt(i); i++) { Breakpoint* breakpoint = instance->GetBreakpoint(); if (breakpoint == NULL || _UpdateBreakpointInstallation(breakpoint) != B_OK) { // something went wrong -- remove the instance teamLocker.Lock(); instance->GetUserBreakpoint()->RemoveInstance(instance); if (breakpoint != NULL) { breakpoint->AddUserBreakpoint(instance); if (breakpoint->IsUnused()) fTeam->RemoveBreakpoint(breakpoint); } teamLocker.Unlock(); } } }