Very much work in progress, not in a particularly working state. Haiku munged

a good part of the source tree, so I rather get those changes into the
repository before continuing.
The general aim of the work is to deal with multiple instances of the same
function, e.g. inlined or non-inlined inline functions or those weird duplicates
gcc (4 at least) seems to be generating for no apparent reason.
* Added classes FunctionInstance (wrapping FunctionDebugInfo) and Function.
  FunctionInstance represents a physical instance of a function (e.g. inlined
  function at a particular address). A Function collects all FunctionInstances
  referring to the same source code location.
* Moved the SourceCode property from FunctionDebugInfo to Function accordingly.
* Since SourceCode is no longer associated with a concrete function instance,
  several methods dealing with statements have been removed and the
  functionality has been provided through other means (e.g. TeamDebugModel or
  SpecificImageDebugModel). This part is not yet completed.
* Introduced UserBreakpoint and UserBreakpointInstance. The user sets a
  breakpoint at a source code location, which is represented by a
  UserBreakpoint. Since that source location can be mapped to one address per
  instance of the respective function, UserBreakpoint has a
  UserBreakpointInstance per such function instance, which in turn refers to a
  Breakpoint (an actual breakpoint at an address).
* Adjusted Breakpoint, BreakpointManager, and TeamDebugger accordingly.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31447 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-07 20:47:39 +00:00
parent ccf28e4dd1
commit f66bd6256a
54 changed files with 1549 additions and 515 deletions
+131 -4
View File
@@ -21,11 +21,15 @@
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "FileManager.h"
#include "Function.h"
#include "ImageDebugInfo.h"
#include "Jobs.h"
#include "LocatableFile.h"
#include "MessageCodes.h"
#include "SymbolInfo.h"
#include "SourceCode.h"
#include "SpecificImageDebugInfo.h"
#include "Statement.h"
#include "SymbolInfo.h"
#include "TeamDebugInfo.h"
#include "TeamDebugModel.h"
@@ -479,8 +483,10 @@ TeamDebugger::MessageReceived(BMessage* message)
void
TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window,
FunctionDebugInfo* function)
FunctionInstance* functionInstance)
{
Function* function = functionInstance->GetFunction();
// mark loading
AutoLocker< ::Team> locker(fTeam);
if (function->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
@@ -821,6 +827,8 @@ TeamDebugger::_HandleImageDeleted(ImageDeletedEvent* event)
imageHandler->ReleaseReference();
}
// TODO: Remove breakpoints in the image!
return false;
}
@@ -837,7 +845,114 @@ void
TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled)
{
printf("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled);
status_t error = fBreakpointManager->InstallUserBreakpoint(address,
// check whether there already is a breakpoint
AutoLocker< ::Team> locker(fTeam);
Breakpoint* breakpoint = fDebugModel->BreakpointAtAddress(address);
UserBreakpoint* userBreakpoint = NULL;
if (breakpoint != NULL && breakpoint->FirstUserBreakpoint() != NULL)
userBreakpoint = breakpoint->FirstUserBreakpoint()->GetUserBreakpoint();
Reference<UserBreakpoint> userBreakpointReference(userBreakpoint);
if (userBreakpoint == NULL) {
printf(" no breakpoint yet\n");
// get the function at the address
Image* image = fTeam->ImageByAddress(address);
printf(" image: %p\n", image);
if (image == NULL)
return;
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
printf(" 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);
printf(" function instance: %p\n", functionInstance);
if (functionInstance == NULL)
return;
Function* function = functionInstance->GetFunction();
printf(" function: %p\n", function);
// get the source location for the address
FunctionDebugInfo* functionDebugInfo
= functionInstance->GetFunctionDebugInfo();
SourceLocation sourceLocation;
Statement* breakpointStatement = NULL;
// if (SourceCode* sourceCode = functionDebugInfo->GetSourceCode()) {
// breakpointStatement = sourceCode->StatementAtAddress(address);
// if (breakpointStatement != NULL)
// sourceLocation = breakpointStatement->StartSourceLocation();
// }
if (breakpointStatement == NULL
&& functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement(
functionDebugInfo, address, breakpointStatement) != B_OK) {
return;
}
sourceLocation = breakpointStatement->StartSourceLocation();
breakpointStatement->ReleaseReference();
target_addr_t relativeAddress = address - functionInstance->Address();
printf(" relative address: %#llx, source location: (%ld, %ld)\n", relativeAddress, sourceLocation.Line(), sourceLocation.Column());
// create the user breakpoint
userBreakpoint = new(std::nothrow) UserBreakpoint(function);
if (userBreakpoint == NULL)
return;
userBreakpointReference.SetTo(userBreakpoint, true);
printf(" 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();) {
printf(" 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()
->GetStatementForSourceLocation(functionDebugInfo,
sourceLocation, statement);
if (statement != NULL) {
instanceAddress = statement->CoveringAddressRange().Start();
// TODO: What about BreakpointAllowed()?
statement->ReleaseReference();
}
}
printf(" 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;
}
printf(" final breakpoint address: %llx\n", instanceAddress);
UserBreakpointInstance* breakpointInstance = new(std::nothrow)
UserBreakpointInstance(userBreakpoint, instanceAddress);
if (breakpointInstance == NULL
|| !userBreakpoint->AddInstance(breakpointInstance)) {
delete breakpointInstance;
return;
}
printf(" breakpoint instance: %p\n", breakpointInstance);
}
}
locker.Unlock();
status_t error = fBreakpointManager->InstallUserBreakpoint(userBreakpoint,
enabled);
if (error != B_OK) {
_NotifyUser("Install Breakpoint", "Failed to install breakpoint: %s",
@@ -850,7 +965,19 @@ void
TeamDebugger::_HandleClearUserBreakpoint(target_addr_t address)
{
printf("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address);
fBreakpointManager->UninstallUserBreakpoint(address);
AutoLocker< ::Team> locker(fTeam);
Breakpoint* breakpoint = fDebugModel->BreakpointAtAddress(address);
if (breakpoint == NULL || breakpoint->FirstUserBreakpoint() == NULL)
return;
UserBreakpoint* userBreakpoint
= breakpoint->FirstUserBreakpoint()->GetUserBreakpoint();
Reference<UserBreakpoint> userBreakpointReference(userBreakpoint);
locker.Unlock();
fBreakpointManager->UninstallUserBreakpoint(userBreakpoint);
}