Initial work towards retrieving function return values.

- When creating a stack frame, we now look at the current function's
  state to determine if the last executed statement was a function call.
  Still need to determine the call destination in order to look up
  the latter function, retrieve its return type, and then request
  retrieval of the actual return value if applicable.
This commit is contained in:
Rene Gollent
2012-12-26 00:21:06 -05:00
parent 1167ae5274
commit bc1ec2ec41
2 changed files with 62 additions and 0 deletions
@@ -26,6 +26,7 @@
#include "DebuggerInterface.h"
#include "DebugInfoEntries.h"
#include "Demangler.h"
#include "DisassembledCode.h"
#include "Dwarf.h"
#include "DwarfFile.h"
#include "DwarfFunctionDebugInfo.h"
@@ -40,6 +41,7 @@
#include "FunctionID.h"
#include "FunctionInstance.h"
#include "GlobalTypeLookup.h"
#include "InstructionInfo.h"
#include "LocatableFile.h"
#include "Register.h"
#include "RegisterMap.h"
@@ -665,6 +667,14 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
instructionPointer, functionInstance->Address() - fRelocationDelta,
subprogramEntry->Variables(), subprogramEntry->Blocks());
// determine if the previously executed instruction was a function
// call to see if we need to potentially retrieve a return value
// as well
if (instructionPointer > functionInstance->Address() - fRelocationDelta) {
_CreateReturnValue(functionInstance, function, frame,
*stackFrameDebugInfo, instructionPointer);
}
}
_frame = frameReference.Detach();
@@ -1073,6 +1083,50 @@ DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
}
status_t
DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
DwarfFunctionDebugInfo* function, StackFrame* frame,
DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
{
DisassembledCode* sourceCode = NULL;
target_size_t bufferSize = std::min(functionInstance->Size(),
(target_size_t)64 * 1024);
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
ssize_t bytesRead = function->GetSpecificImageDebugInfo()
->ReadCode(functionInstance->Address(), buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
status_t result = fArchitecture->DisassembleCode(function, buffer,
bytesRead, sourceCode);
if (result != B_OK)
return result;
BReference<DisassembledCode> sourceCodeReference(sourceCode, true);
target_addr_t previousStatementAddress = instructionPointer + fRelocationDelta - 1;
Statement* statement = sourceCode->StatementAtAddress(
previousStatementAddress);
if (statement == NULL)
return B_BAD_VALUE;
TargetAddressRange range = statement->CoveringAddressRange();
InstructionInfo info;
if (fArchitecture->GetInstructionInfo(range.Start(), info) == B_OK
&& info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) {
// TODO: determine where the previous instruction actually jumps to,
// retrieve that function (could potentially be in another image),
// and use its return type to retrieve the return value (will need
// architecture support since function return value passing convention
// is arch-dependent).
}
return B_OK;
}
bool
DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type,
const TypeLookupConstraints& constraints)
@@ -21,12 +21,14 @@ class Architecture;
class CompilationUnit;
class DebuggerInterface;
class DIEType;
class DwarfFunctionDebugInfo;
class DwarfStackFrameDebugInfo;
class DwarfFile;
class ElfSegment;
class FileManager;
class FileSourceCode;
class FunctionID;
class FunctionInstance;
class GlobalTypeCache;
class GlobalTypeLookup;
class LocatableFile;
@@ -101,6 +103,12 @@ private:
const EntryListWrapper& variableEntries,
const EntryListWrapper& blockEntries);
status_t _CreateReturnValue(FunctionInstance* instance,
DwarfFunctionDebugInfo* info,
StackFrame* frame,
DwarfStackFrameDebugInfo& factory,
target_addr_t instructionPointer);
bool _EvaluateBaseTypeConstraints(DIEType* type,
const TypeLookupConstraints& constraints);