[haiku-commits] haiku: hrev45116 - in src/apps/debugger: debug_info arch/x86/disasm arch/x86 arch controllers

  • From: anevilyak@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 1 Jan 2013 05:04:20 +0100 (CET)

hrev45116 adds 8 changesets to branch 'master'
old head: eed38dfa96a8fcfdd4d01c15ff6840272f924f73
new head: 5745a40dd1813a745fc4b899862597c3f618ef6c
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5745a40+%5Eeed38df

----------------------------------------------------------------------------

9ede3c0: Add ReturnValueID base type.

84ea02a: Extend InstructionInfo for subroutines.
  
  - InstructionInfo now also stores the destination address of subroutine
    call instructions.
  - Adjust callers.

dc693e9: Extend Architecture to help retrieve return values.
  
  - Architecture now has a new function to retrieve the location where
    a return value can be found. Added implementation for x86 and stub
    for x86-64.

c7ca91f: Add helper functions for creating return value variables.

f733c60: Initial implementation of _GetReturnValue().
  
  - Look at the destination of the subroutine instruction and try to
    resolve it to a function. Currently only handles functions whose
    destination are within the same image.
  
  - If found, look up debug info for the target function. If available,
    determine if it returns a value. If so, construct an appropriate
    placeholder variable and add it to the frame's variable list.

cf2e209: More improvements to return value handling.
  
  - Thread now has a data member indicating if a subroutine was
    executed during the last set of steps.
  - ThreadHandler now sets the aforementioned state appropriate during
    Step Over/Step Out.
  - Architecture::CreateStackTrace() now takes a parameter indicating
    whether return value retrieval is desired (based on aforementioned
    thread value). Adjust callers accordingly.
  - DwarfImageDebugInfo: If return value retrieval is requested, loop
    backwards from the current IP to find the call instruction.

bdbbc10: Thread now also tracks the address of the last executed function.

5745a40: Rework how return values are handled.
  
  - ArchitectureX86 now hands off the work for GetInstructionInfo() to
    DisassemblerX86, since the latter has all the information we need
    to properly classify and evaluate instructions. Correspondingly a
    CpuState is passed down to it in order to perform address calculations
    for the instruction if it's a jump or call instruction. The latter's
    targets are then stored on the thread for later retrieval when
    constructing a stack trace. Adjust X86_64 accordingly for the
    signature changes. This also fixes a bug where Step Over would
    sometimes result in a Step Into instead due to the previous
    implementation of GetInstructionInfo() occasionally failing to
    classify call instructions correctly.
  
  - Architecture::CreateStackTrace() now takes an argument specifying
    the address of the last executed function if applicable. This is used
    to decide who/where to decode a return value from. Adjust callers.
  
  - DwarfImageDebugInfo::_CreateReturnValue() uses the above information
    in order to know directly who the caller it needs to look up a return
    value for is, rather than trying to walk backwards to find them.
    Type resolution is now also a bit more sophisticated due to various
    cases where the subprogram entry didn't directly contain the return
    type but referred to another DIE that did. Retrieving return value
    now appears to work properly in all cases except when position
    independent code is involved. The latter however will require
    resolving the appropriate function address in the PLT, which will
    need some additional work.

                                      [ Rene Gollent <anevilyak@xxxxxxxxx> ]

----------------------------------------------------------------------------

25 files changed, 480 insertions(+), 108 deletions(-)
src/apps/debugger/Jamfile                        |   3 +-
src/apps/debugger/arch/Architecture.cpp          |   7 +-
src/apps/debugger/arch/Architecture.h            |   9 +-
src/apps/debugger/arch/InstructionInfo.cpp       |  10 +-
src/apps/debugger/arch/InstructionInfo.h         |   9 +-
src/apps/debugger/arch/x86/ArchitectureX86.cpp   |  84 ++++++++------
src/apps/debugger/arch/x86/ArchitectureX86.h     |   7 +-
.../debugger/arch/x86/disasm/DisassemblerX86.cpp | 112 ++++++++++++++++++
.../debugger/arch/x86/disasm/DisassemblerX86.h   |  12 ++
src/apps/debugger/arch/x86/disasm/Jamfile        |   3 +
.../debugger/arch/x86_64/ArchitectureX8664.cpp   |  16 ++-
.../debugger/arch/x86_64/ArchitectureX8664.h     |   6 +-
src/apps/debugger/controllers/ThreadHandler.cpp  |  39 +++++--
.../debug_info/DebuggerImageDebugInfo.cpp        |   4 +-
.../debugger/debug_info/DebuggerImageDebugInfo.h |   1 +
.../debugger/debug_info/DwarfImageDebugInfo.cpp  | 116 ++++++++++++-------
.../debugger/debug_info/DwarfImageDebugInfo.h    |   9 +-
.../debug_info/DwarfStackFrameDebugInfo.cpp      |  76 ++++++++++++
.../debug_info/DwarfStackFrameDebugInfo.h        |   7 ++
.../debugger/debug_info/SpecificImageDebugInfo.h |   1 +
src/apps/debugger/ids/ReturnValueID.cpp          |  13 +++
src/apps/debugger/ids/ReturnValueID.h            |  18 +++
src/apps/debugger/jobs/GetStackTraceJob.cpp      |   3 +-
src/apps/debugger/model/Thread.cpp               |  13 +++
src/apps/debugger/model/Thread.h                 |  10 ++

############################################################################

Commit:      9ede3c06e8b42ae5428b6580a0416555af4dad05
URL:         http://cgit.haiku-os.org/haiku/commit/?id=9ede3c0
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sat Dec 29 03:24:40 2012 UTC

Add ReturnValueID base type.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
index 44c56d0..c2aaa66 100644
--- a/src/apps/debugger/Jamfile
+++ b/src/apps/debugger/Jamfile
@@ -124,9 +124,10 @@ Application Debugger :
 
        # ids
        FunctionID.cpp
+       FunctionParameterID.cpp
        LocalVariableID.cpp
        ObjectID.cpp
-       FunctionParameterID.cpp
+       ReturnValueID.cpp
 
        # jobs
        GetCPUStateJob.cpp
diff --git a/src/apps/debugger/ids/ReturnValueID.cpp 
b/src/apps/debugger/ids/ReturnValueID.cpp
new file mode 100644
index 0000000..38e6c84
--- /dev/null
+++ b/src/apps/debugger/ids/ReturnValueID.cpp
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "ReturnValueID.h"
+
+
+ReturnValueID::~ReturnValueID()
+{
+}
+
diff --git a/src/apps/debugger/ids/ReturnValueID.h 
b/src/apps/debugger/ids/ReturnValueID.h
new file mode 100644
index 0000000..021a917
--- /dev/null
+++ b/src/apps/debugger/ids/ReturnValueID.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef RETURN_VALUE_ID_H
+#define RETURN_VALUE_ID_H
+
+
+#include "ObjectID.h"
+
+
+class ReturnValueID : public ObjectID {
+public:
+       virtual                                         ~ReturnValueID();
+};
+
+
+#endif // RETURN_VALUE_ID_H

############################################################################

Commit:      84ea02a0f4e9cc454dc587d7920d18bf979c19b1
URL:         http://cgit.haiku-os.org/haiku/commit/?id=84ea02a
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sat Dec 29 03:26:22 2012 UTC

Extend InstructionInfo for subroutines.

- InstructionInfo now also stores the destination address of subroutine
  call instructions.
- Adjust callers.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/arch/InstructionInfo.cpp 
b/src/apps/debugger/arch/InstructionInfo.cpp
index 03afae4..1a48c70 100644
--- a/src/apps/debugger/arch/InstructionInfo.cpp
+++ b/src/apps/debugger/arch/InstructionInfo.cpp
@@ -9,6 +9,7 @@
 InstructionInfo::InstructionInfo()
        :
        fAddress(0),
+       fTargetAddress(0),
        fSize(0),
        fType(INSTRUCTION_TYPE_OTHER),
        fBreakpointAllowed(false),
@@ -17,11 +18,13 @@ InstructionInfo::InstructionInfo()
 }
 
 
-InstructionInfo::InstructionInfo(target_addr_t address, target_size_t size,
+InstructionInfo::InstructionInfo(target_addr_t address,
+       target_addr_t targetAddress, target_size_t size,
        instruction_type type, bool breakpointAllowed,
        const BString& disassembledLine)
        :
        fAddress(address),
+       fTargetAddress(targetAddress),
        fSize(size),
        fType(type),
        fBreakpointAllowed(breakpointAllowed),
@@ -31,11 +34,12 @@ InstructionInfo::InstructionInfo(target_addr_t address, 
target_size_t size,
 
 
 bool
-InstructionInfo::SetTo(target_addr_t address, target_size_t size,
-       instruction_type type, bool breakpointAllowed,
+InstructionInfo::SetTo(target_addr_t address, target_addr_t targetAddress,
+       target_size_t size, instruction_type type, bool breakpointAllowed,
        const BString& disassembledLine)
 {
        fAddress = address;
+       fTargetAddress = targetAddress;
        fSize = size;
        fType = type;
        fBreakpointAllowed = breakpointAllowed;
diff --git a/src/apps/debugger/arch/InstructionInfo.h 
b/src/apps/debugger/arch/InstructionInfo.h
index 36c2fa2..f130080 100644
--- a/src/apps/debugger/arch/InstructionInfo.h
+++ b/src/apps/debugger/arch/InstructionInfo.h
@@ -20,16 +20,21 @@ class InstructionInfo {
 public:
                                                                
InstructionInfo();
                                                                
InstructionInfo(target_addr_t address,
+                                                                       
target_addr_t targetAddress,
                                                                        
target_size_t size, instruction_type type,
                                                                        bool 
breakpointAllowed,
                                                                        const 
BString& disassembledLine);
 
-                       bool                            SetTo(target_addr_t 
address, target_size_t size,
+                       bool                            SetTo(target_addr_t 
address,
+                                                                       
target_addr_t targetAddress,
+                                                                       
target_size_t size,
                                                                        
instruction_type type,
                                                                        bool 
breakpointAllowed,
                                                                        const 
BString& disassembledLine);
 
                        target_addr_t           Address() const         { 
return fAddress; }
+                       target_addr_t           TargetAddress() const
+                                                                       { 
return fTargetAddress; }
                        target_size_t           Size() const            { 
return fSize; }
                        instruction_type        Type() const            { 
return fType; }
                        bool                            IsBreakpointAllowed() 
const
@@ -40,6 +45,7 @@ public:
 
 private:
                        target_addr_t           fAddress;
+                       target_addr_t           fTargetAddress;
                        target_size_t           fSize;
                        instruction_type        fType;
                        bool                            fBreakpointAllowed;
diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp 
b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
index dd19a90..5eccb06 100644
--- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp
+++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
@@ -596,6 +596,7 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address,
        // disassemble the instruction
        BString line;
        target_addr_t instructionAddress;
+       target_addr_t targetAddress = 0;
        target_size_t instructionSize;
        bool breakpointAllowed;
        error = disassembler.GetNextInstruction(line, instructionAddress,
@@ -607,17 +608,21 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address,
        if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
                // absolute call with r/m32
                instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
+               // TODO: retrieve target address (might be in a register)
        } else if (buffer[0] == 0xe8 && instructionSize == 5) {
                // relative call with rel32 -- don't categorize the call with 0 
as
                // subroutine call, since it is only used to get the address of 
the GOT
                if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
                        || buffer[4] != 0) {
                        instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
+                       int32 offset;
+                       memcpy(&offset, &buffer[1], 4);
+                       targetAddress = instructionAddress + instructionSize + 
offset;
                }
        }
 
-       if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
-                       breakpointAllowed, line)) {
+       if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
+                       instructionType, breakpointAllowed, line)) {
                return B_NO_MEMORY;
        }
 
diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
index 2152562..f32b820 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
@@ -487,6 +487,7 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address,
        // disassemble the instruction
        BString line;
        target_addr_t instructionAddress;
+       target_addr_t targetAddress = 0;
        target_size_t instructionSize;
        bool breakpointAllowed;
        error = disassembler.GetNextInstruction(line, instructionAddress,
@@ -508,8 +509,8 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address,
                }
        }
 
-       if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
-                       breakpointAllowed, line)) {
+       if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
+                       instructionType, breakpointAllowed, line)) {
                return B_NO_MEMORY;
        }
 

############################################################################

Commit:      dc693e9265707e9e0c470c2ec00106795424b6dc
URL:         http://cgit.haiku-os.org/haiku/commit/?id=dc693e9
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sat Dec 29 03:27:30 2012 UTC

Extend Architecture to help retrieve return values.

- Architecture now has a new function to retrieve the location where
  a return value can be found. Added implementation for x86 and stub
  for x86-64.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/arch/Architecture.h 
b/src/apps/debugger/arch/Architecture.h
index 38409d0..748e9dc 100644
--- a/src/apps/debugger/arch/Architecture.h
+++ b/src/apps/debugger/arch/Architecture.h
@@ -30,6 +30,7 @@ class StackTrace;
 class Statement;
 class Team;
 class TeamMemory;
+class ValueLocation;
 
 
 enum {
@@ -118,6 +119,10 @@ public:
                                                                        int32& 
_maxBytesPerRegister,
                                                                        uint8& 
_watchpointCapabilityFlags) = 0;
 
+       virtual status_t                        GetReturnAddressLocation(
+                                                                       
StackFrame* frame, target_size_t valueSize,
+                                                                       
ValueLocation*& _location) = 0;
+
 
 protected:
                        TeamMemory*                     fTeamMemory;
diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp 
b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
index 5eccb06..c7995d5 100644
--- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp
+++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
@@ -23,6 +23,7 @@
 #include "StackFrame.h"
 #include "Statement.h"
 #include "TeamMemory.h"
+#include "ValueLocation.h"
 #include "X86AssemblyLanguage.h"
 
 #include "disasm/DisassemblerX86.h"
@@ -579,9 +580,8 @@ status_t
 ArchitectureX86::GetInstructionInfo(target_addr_t address,
        InstructionInfo& _info)
 {
-       // read the code
+       // read the code - maximum x86{-64} instruction size = 15 bytes
        uint8 buffer[16];
-               // TODO: What's the maximum instruction size?
        ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
                sizeof(buffer));
        if (bytesRead < 0)
@@ -648,6 +648,52 @@ ArchitectureX86::GetWatchpointDebugCapabilities(int32& 
_maxRegisterCount,
 }
 
 
+status_t
+ArchitectureX86::GetReturnAddressLocation(StackFrame* frame,
+       target_size_t valueSize, ValueLocation*& _location)
+{
+       // for the calling conventions currently in use on Haiku,
+       // the x86 rules for how values are returned are as follows:
+       //
+       // - 32 bits or smaller values are returned directly in EAX.
+       // - 32-64 bit values are returned across EAX:EDX.
+       // - > 64 bit values are returned on the stack.
+       ValueLocation* location = new(std::nothrow) ValueLocation(
+               IsBigEndian());
+       if (location == NULL)
+               return B_NO_MEMORY;
+       BReference<ValueLocation> locationReference(location,
+               true);
+
+       if (valueSize <= 4) {
+               ValuePieceLocation piece;
+               piece.SetSize(valueSize);
+               piece.SetToRegister(X86_REGISTER_EAX);
+               if (!location->AddPiece(piece))
+                       return B_NO_MEMORY;
+       } else if (valueSize <= 8) {
+               ValuePieceLocation piece;
+               piece.SetSize(4);
+               piece.SetToRegister(X86_REGISTER_EAX);
+               if (!location->AddPiece(piece))
+                       return B_NO_MEMORY;
+               piece.SetToRegister(X86_REGISTER_EDX);
+               piece.SetSize(valueSize - 4);
+               if (!location->AddPiece(piece))
+                       return B_NO_MEMORY;
+       } else {
+               ValuePieceLocation piece;
+               piece.SetToMemory(frame->GetCpuState()->StackPointer());
+               piece.SetSize(valueSize);
+               if (!location->AddPiece(piece))
+                       return B_NO_MEMORY;
+       }
+
+       _location = locationReference.Detach();
+       return B_OK;
+}
+
+
 void
 ArchitectureX86::_AddRegister(int32 index, const char* name,
        uint32 bitSize, uint32 valueType, register_type type, bool 
calleePreserved)
diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h 
b/src/apps/debugger/arch/x86/ArchitectureX86.h
index 48e849c..1549f9b 100644
--- a/src/apps/debugger/arch/x86/ArchitectureX86.h
+++ b/src/apps/debugger/arch/x86/ArchitectureX86.h
@@ -66,6 +66,11 @@ public:
                                                                        int32& 
_maxBytesPerRegister,
                                                                        uint8& 
_watchpointCapabilityFlags);
 
+       virtual status_t                        GetReturnAddressLocation(
+                                                                       
StackFrame* frame, target_size_t valueSize,
+                                                                       
ValueLocation*& _location);
+
+
 private:
                        struct ToDwarfRegisterMap;
                        struct FromDwarfRegisterMap;
diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
index f32b820..acf2f93 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
@@ -535,6 +535,13 @@ ArchitectureX8664::GetWatchpointDebugCapabilities(int32& 
_maxRegisterCount,
 }
 
 
+status_t
+ArchitectureX8664::GetReturnAddressLocation(StackFrame* frame,
+       target_size_t valueSize, ValueLocation*& _location) {
+       return B_NOT_SUPPORTED;
+}
+
+
 void
 ArchitectureX8664::_AddRegister(int32 index, const char* name,
        uint32 bitSize, uint32 valueType, register_type type, bool 
calleePreserved)
diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
index ec81448..f61b8f3 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
@@ -67,6 +67,10 @@ public:
                                                                        int32& 
_maxBytesPerRegister,
                                                                        uint8& 
_watchpointCapabilityFlags);
 
+       virtual status_t                        GetReturnAddressLocation(
+                                                                       
StackFrame* frame, target_size_t valueSize,
+                                                                       
ValueLocation*& _location);
+
 private:
                        struct ToDwarfRegisterMap;
                        struct FromDwarfRegisterMap;

############################################################################

Commit:      c7ca91ffd364a32a50b3b563c6978b8a94417ded
URL:         http://cgit.haiku-os.org/haiku/commit/?id=c7ca91f
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sat Dec 29 03:31:28 2012 UTC

Add helper functions for creating return value variables.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp 
b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp
index 99853ae..42cef63 100644
--- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp
+++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx.
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Distributed under the terms of the MIT License.
  */
@@ -23,6 +24,7 @@
 #include "LocalVariableID.h"
 #include "Register.h"
 #include "RegisterMap.h"
+#include "ReturnValueID.h"
 #include "StringUtils.h"
 #include "Tracing.h"
 #include "ValueLocation.h"
@@ -117,6 +119,47 @@ private:
 };
 
 
+// #pragma mark - DwarfReturnValueID
+
+
+struct DwarfStackFrameDebugInfo::DwarfReturnValueID
+       : public ReturnValueID {
+
+       DwarfReturnValueID(FunctionID* functionID)
+               :
+               fFunctionID(functionID),
+               fName("(returned)")
+       {
+               fFunctionID->AcquireReference();
+       }
+
+       virtual ~DwarfReturnValueID()
+       {
+               fFunctionID->ReleaseReference();
+       }
+
+       virtual bool operator==(const ObjectID& other) const
+       {
+               const DwarfReturnValueID* returnValueID
+                       = dynamic_cast<const DwarfReturnValueID*>(&other);
+               return returnValueID != NULL
+                       && *fFunctionID == *returnValueID->fFunctionID
+                       && fName == returnValueID->fName;
+       }
+
+protected:
+       virtual uint32 ComputeHashValue() const
+       {
+               uint32 hash = fFunctionID->HashValue();
+               return hash * 25 + StringUtils::HashValue(fName);
+       }
+
+private:
+       FunctionID*             fFunctionID;
+       const BString   fName;
+};
+
+
 // #pragma mark - DwarfStackFrameDebugInfo
 
 
@@ -235,6 +278,39 @@ DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* 
functionID,
 
 
 status_t
+DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID* functionID,
+       DIEType* returnType, ValueLocation* location, Variable*& _variable)
+{
+       if (returnType == NULL)
+               return B_BAD_VALUE;
+
+       // create the type
+       DwarfType* type;
+       status_t error = fTypeFactory->CreateType(returnType, type);
+       if (error != B_OK)
+               return error;
+       BReference<DwarfType> typeReference(type, true);
+
+       DwarfReturnValueID* id = new(std::nothrow) DwarfReturnValueID(
+               functionID);
+       if (id == NULL)
+               return B_NO_MEMORY;
+
+       BString name;
+       name.SetToFormat("%s returned", functionID->FunctionName().String());
+
+       Variable* variable = new(std::nothrow) Variable(id, name,
+               type, location);
+       if (variable == NULL)
+               return B_NO_MEMORY;
+
+       _variable = variable;
+
+       return B_OK;
+}
+
+
+status_t
 DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name,
        DIEType* typeEntry, LocationDescription* locationDescription,
        Variable*& _variable)
diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h 
b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h
index e55d0d2..3e69130 100644
--- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h
+++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx.
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Distributed under the terms of the MIT License.
  */
@@ -56,10 +57,16 @@ public:
                                                                        
DIEVariable* variableEntry,
                                                                        
Variable*& _variable);
                                                                        // 
returns reference
+                       status_t                        
CreateReturnValue(FunctionID* functionID,
+                                                                       
DIEType* returnType,
+                                                                       
ValueLocation* location,
+                                                                       
Variable*& _variable);
+                                                                       // 
returns reference
 
 private:
                        struct DwarfFunctionParameterID;
                        struct DwarfLocalVariableID;
+                       struct DwarfReturnValueID;
 
 private:
                        status_t                        
_CreateVariable(ObjectID* id,

############################################################################

Commit:      f733c6031a76256d7b6652267b649892a9a849f7
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f733c60
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sat Dec 29 03:31:52 2012 UTC

Initial implementation of _GetReturnValue().

- Look at the destination of the subroutine instruction and try to
  resolve it to a function. Currently only handles functions whose
  destination are within the same image.

- If found, look up debug info for the target function. If available,
  determine if it returns a value. If so, construct an appropriate
  placeholder variable and add it to the frame's variable list.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp 
b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
index c6aa3ca..d8942ff 100644
--- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
+++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
@@ -41,6 +41,8 @@
 #include "FunctionID.h"
 #include "FunctionInstance.h"
 #include "GlobalTypeLookup.h"
+#include "Image.h"
+#include "ImageDebugInfo.h"
 #include "InstructionInfo.h"
 #include "LocatableFile.h"
 #include "Register.h"
@@ -56,6 +58,7 @@
 #include "TypeLookupConstraints.h"
 #include "UnsupportedLanguage.h"
 #include "Variable.h"
+#include "ValueLocation.h"
 
 
 namespace {
@@ -672,7 +675,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
                // call to see if we need to potentially retrieve a return value
                // as well
                if (instructionPointer > functionInstance->Address() - 
fRelocationDelta) {
-                       _CreateReturnValue(functionInstance, function, frame,
+                       _CreateReturnValue(functionInstance, image, function, 
frame,
                                *stackFrameDebugInfo, instructionPointer);
                }
        }
@@ -1085,7 +1088,7 @@ 
DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
 
 status_t
 DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
-       DwarfFunctionDebugInfo* function, StackFrame* frame,
+       Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame,
        DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
 {
        DisassembledCode* sourceCode = NULL;
@@ -1111,16 +1114,60 @@ 
DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
                previousStatementAddress);
        if (statement == NULL)
                return B_BAD_VALUE;
+       previousStatementAddress = statement->CoveringAddressRange().Start() - 
1;
+       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).
+               target_addr_t targetAddress = info.TargetAddress();
+               if (targetAddress == 0)
+                       return B_BAD_VALUE;
+
+               if (image->ContainsAddress(targetAddress)) {
+                       FunctionInstance* targetFunction;
+                       if (targetAddress >= fPLTSectionStart && targetAddress 
< fPLTSectionEnd) {
+                               // TODO: resolve actual target address in the 
PIC case
+                               // and adjust targetAddress accordingly
+                       }
+                       ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
+                       targetFunction = 
imageInfo->FunctionAtAddress(targetAddress);
+                       if (targetFunction != NULL) {
+                               DwarfFunctionDebugInfo* targetInfo =
+                                       dynamic_cast<DwarfFunctionDebugInfo*>(
+                                               
targetFunction->GetFunctionDebugInfo());
+                               if (targetInfo != NULL) {
+                                       DIESubprogram* subProgram = 
targetInfo->SubprogramEntry();
+                                       DIEType* returnType = 
subProgram->ReturnType();
+                                       if (returnType == NULL) {
+                                               // function doesn't return a 
value, we're done.
+                                               return B_OK;
+                                       }
+
+                                       ValueLocation* location;
+                                       result = 
fArchitecture->GetReturnAddressLocation(frame,
+                                               
returnType->ByteSize()->constant, location);
+                                       if (result != B_OK)
+                                               return result;
+                                       BReference<ValueLocation> 
locationReference(location,
+                                               true);
+                                       Variable* variable = NULL;
+                                       BReference<FunctionID> idReference(
+                                               
targetFunction->GetFunctionID(), true);
+                                       result = 
factory.CreateReturnValue(idReference,
+                                               returnType, location, variable);
+                                       if (result != B_OK)
+                                               return result;
+                                       BReference<Variable> 
variableReference(variable, true);
+                                       if (!frame->AddLocalVariable(variable))
+                                               return B_NO_MEMORY;
+                               }
+                       }
+               }
        }
 
        return B_OK;
diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h 
b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
index c03370f..4c9b0c1 100644
--- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
@@ -104,6 +104,7 @@ private:
                                                                        const 
EntryListWrapper& blockEntries);
 
                        status_t                        
_CreateReturnValue(FunctionInstance* instance,
+                                                                       Image* 
image,
                                                                        
DwarfFunctionDebugInfo* info,
                                                                        
StackFrame* frame,
                                                                        
DwarfStackFrameDebugInfo& factory,

############################################################################

Commit:      cf2e209b2d15a1a39560260cfba7355303ef91ac
URL:         http://cgit.haiku-os.org/haiku/commit/?id=cf2e209
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sun Dec 30 03:43:34 2012 UTC

More improvements to return value handling.

- Thread now has a data member indicating if a subroutine was
  executed during the last set of steps.
- ThreadHandler now sets the aforementioned state appropriate during
  Step Over/Step Out.
- Architecture::CreateStackTrace() now takes a parameter indicating
  whether return value retrieval is desired (based on aforementioned
  thread value). Adjust callers accordingly.
- DwarfImageDebugInfo: If return value retrieval is requested, loop
  backwards from the current IP to find the call instruction.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/arch/Architecture.cpp 
b/src/apps/debugger/arch/Architecture.cpp
index 01b3999..4da0641 100644
--- a/src/apps/debugger/arch/Architecture.cpp
+++ b/src/apps/debugger/arch/Architecture.cpp
@@ -94,8 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const
 status_t
 Architecture::CreateStackTrace(Team* team,
        ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
-       StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace,
-       bool getFullFrameInfo)
+       StackTrace*& _stackTrace, bool getReturnValue, int32 maxStackDepth,
+       bool useExistingTrace, bool getFullFrameInfo)
 {
        BReference<CpuState> cpuStateReference(cpuState);
 
@@ -163,7 +163,8 @@ Architecture::CreateStackTrace(Team* team,
                if (function != NULL) {
                        status_t error = 
functionDebugInfo->GetSpecificImageDebugInfo()
                                ->CreateFrame(image, function, cpuState, 
getFullFrameInfo,
-                                       frame, previousCpuState);
+                                       nextFrame == NULL ? getReturnValue : 
false, frame,
+                                       previousCpuState);
                        if (error != B_OK && error != B_UNSUPPORTED)
                                break;
                }
diff --git a/src/apps/debugger/arch/Architecture.h 
b/src/apps/debugger/arch/Architecture.h
index 748e9dc..3ab3f7d 100644
--- a/src/apps/debugger/arch/Architecture.h
+++ b/src/apps/debugger/arch/Architecture.h
@@ -109,6 +109,7 @@ public:
                                                                        
ImageDebugInfoProvider* imageInfoProvider,
                                                                        
CpuState* cpuState,
                                                                        
StackTrace*& _stackTrace,
+                                                                       bool 
getReturnValue,
                                                                        int32 
maxStackDepth = -1,
                                                                        bool 
useExistingTrace = false,
                                                                        bool 
getFullFrameInfo = true);
diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp 
b/src/apps/debugger/controllers/ThreadHandler.cpp
index f916106..7913da9 100644
--- a/src/apps/debugger/controllers/ThreadHandler.cpp
+++ b/src/apps/debugger/controllers/ThreadHandler.cpp
@@ -253,8 +253,8 @@ ThreadHandler::HandleThreadAction(uint32 action)
 
        if (stackTrace == NULL && cpuState != NULL) {
                if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                               fThread->GetTeam(), this, cpuState, stackTrace, 
1, false,
-                               false) == B_OK) {
+                               fThread->GetTeam(), this, cpuState, stackTrace, 
false, 1,
+                               false, false) == B_OK) {
                        stackTraceReference.SetTo(stackTrace, true);
                }
        }
@@ -484,6 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
        TRACE_CONTROL("  subroutine call -- installing breakpoint at address "
                "%#" B_PRIx64 "\n", info.Address() + info.Size());
 
+       fThread->SetExecutedSubroutine();
        if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
                return false;
 
@@ -565,9 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
 
                        if (stackTrace == NULL && cpuState != NULL) {
                                if 
(fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                                               fThread->GetTeam(), this, 
cpuState, stackTrace, 1,
-                                               false, false)
-                                               == B_OK) {
+                                               fThread->GetTeam(), this, 
cpuState, stackTrace, false,
+                                               1, false, false) == B_OK) {
                                        stackTraceReference.SetTo(stackTrace, 
true);
                                }
                        }
@@ -576,7 +576,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
                                // If we're not in the same frame we started in,
                                // keep executing.
                                if (frame != NULL && fPreviousFrameAddress
-                                               != 
stackTrace->FrameAt(0)->FrameAddress()) {
+                                               != frame->FrameAddress()) {
                                        status_t error = 
_InstallTemporaryBreakpoint(
                                                cpuState->InstructionPointer());
                                        if (error != B_OK)
@@ -608,6 +608,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
                        // That's the return address, so we're done in theory,
                        // unless we're a recursive function. Check if we've 
actually
                        // exited the previous stack frame or not.
+                       fThread->SetExecutedSubroutine();
                        target_addr_t framePointer = 
cpuState->StackFramePointer();
                        bool hasExitedFrame = 
fDebuggerInterface->GetArchitecture()
                                ->StackGrowthDirection() == 
STACK_GROWTH_DIRECTION_POSITIVE
@@ -652,9 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
 
                        if (stackTrace == NULL && cpuState != NULL) {
                                if 
(fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                                               fThread->GetTeam(), this, 
cpuState, stackTrace, 1,
-                                               false, false)
-                                               == B_OK) {
+                                               fThread->GetTeam(), this, 
cpuState, stackTrace, false,
+                                               1, false, false) == B_OK) {
                                        stackTraceReference.SetTo(stackTrace, 
true);
                                }
                        }
@@ -680,8 +680,24 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
                case STEP_OVER:
                {
                        // If we have stepped out of the statement, we're done.
-                       if 
(!fStepStatement->ContainsAddress(cpuState->InstructionPointer()))
+                       if 
(!fStepStatement->ContainsAddress(cpuState->InstructionPointer())) {
+                               StackTrace* stackTrace = 
fThread->GetStackTrace();
+                               BReference<StackTrace> 
stackTraceReference(stackTrace);
+                               if (stackTrace == NULL && cpuState != NULL) {
+                                       if 
(fDebuggerInterface->GetArchitecture()->CreateStackTrace(
+                                                       fThread->GetTeam(), 
this, cpuState, stackTrace, false,
+                                                       1, false, false) == 
B_OK) {
+                                               
stackTraceReference.SetTo(stackTrace, true);
+                                       }
+                               }
+
+                               if (stackTrace != NULL && stackTrace->FrameAt(0)
+                                               ->FrameAddress() != 
fPreviousFrameAddress) {
+                                       fThread->SetExecutedSubroutine();
+                               }
+
                                return false;
+                       }
                        return _DoStepOver(cpuState);
                }
 
diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp 
b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
index da467da..1ff7ac8 100644
--- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
+++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
@@ -68,7 +68,7 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t 
address)
 status_t
 DebuggerImageDebugInfo::CreateFrame(Image* image,
        FunctionInstance* functionInstance, CpuState* cpuState,
-       bool getFullFrameInfo, StackFrame*& _previousFrame,
+       bool getFullFrameInfo, bool getReturnValue, StackFrame*& _previousFrame,
        CpuState*& _previousCpuState)
 {
        return B_UNSUPPORTED;
diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h 
b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
index 8c0c520..981dbd8 100644
--- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
@@ -36,6 +36,7 @@ public:
                                                                        
FunctionInstance* functionInstance,
                                                                        
CpuState* cpuState,
                                                                        bool 
getFullFrameInfo,
+                                                                       bool 
getReturnValue,
                                                                        
StackFrame*& _previousFrame,
                                                                        
CpuState*& _previousCpuState);
        virtual status_t                        GetStatement(FunctionDebugInfo* 
function,
diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp 
b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
index d8942ff..c7448e0 100644
--- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
+++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
@@ -53,6 +53,7 @@
 #include "StringUtils.h"
 #include "SymbolInfo.h"
 #include "TargetAddressRangeList.h"
+#include "Team.h"
 #include "TeamMemory.h"
 #include "Tracing.h"
 #include "TypeLookupConstraints.h"
@@ -521,7 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t 
address)
 status_t
 DwarfImageDebugInfo::CreateFrame(Image* image,
        FunctionInstance* functionInstance, CpuState* cpuState,
-       bool getFullFrameInfo, StackFrame*& _frame, CpuState*& 
_previousCpuState)
+       bool getFullFrameInfo, bool getReturnValue, StackFrame*& _frame,
+       CpuState*& _previousCpuState)
 {
        DwarfFunctionDebugInfo* function = 
dynamic_cast<DwarfFunctionDebugInfo*>(
                functionInstance->GetFunctionDebugInfo());
@@ -671,10 +673,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
                        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) {
+               if (getReturnValue) {
                        _CreateReturnValue(functionInstance, image, function, 
frame,
                                *stackFrameDebugInfo, instructionPointer);
                }
@@ -1091,6 +1090,8 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* 
functionInstance,
        Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame,
        DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
 {
+       // the thread just executed a subroutine, look for the last call
+       // instruction.
        DisassembledCode* sourceCode = NULL;
        target_size_t bufferSize = std::min(functionInstance->Size(),
                (target_size_t)64 * 1024);
@@ -1114,59 +1115,74 @@ 
DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
                previousStatementAddress);
        if (statement == NULL)
                return B_BAD_VALUE;
-       previousStatementAddress = statement->CoveringAddressRange().Start() - 
1;
-       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) {
-               target_addr_t targetAddress = info.TargetAddress();
-               if (targetAddress == 0)
+       do {
+               TargetAddressRange range = statement->CoveringAddressRange();
+               result = fArchitecture->GetInstructionInfo(range.Start(), info);
+               if (result != B_OK)
+                       return result;
+
+               if (info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL)
+                       break;
+
+               previousStatementAddress = 
statement->CoveringAddressRange().Start() - 1;
+               statement = sourceCode->StatementAtAddress(
+                       previousStatementAddress);
+       } while (statement != NULL);
+
+       // we weren't able to find a subroutine call by stepping back
+       // so we can't retrieve a return value
+       if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL)
+               return B_OK;
+
+       target_addr_t targetAddress = info.TargetAddress();
+       if (targetAddress == 0)
+               return B_BAD_VALUE;
+
+       if (!image->ContainsAddress(targetAddress)) {
+               // our current image doesn't contain the target function,
+               // locate the one which does.
+               image = image->GetTeam()->ImageByAddress(targetAddress);
+               if (image == NULL)
                        return B_BAD_VALUE;
+       }
 
-               if (image->ContainsAddress(targetAddress)) {
-                       FunctionInstance* targetFunction;
-                       if (targetAddress >= fPLTSectionStart && targetAddress 
< fPLTSectionEnd) {
-                               // TODO: resolve actual target address in the 
PIC case
-                               // and adjust targetAddress accordingly
-                       }
-                       ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
-                       targetFunction = 
imageInfo->FunctionAtAddress(targetAddress);
-                       if (targetFunction != NULL) {
-                               DwarfFunctionDebugInfo* targetInfo =
-                                       dynamic_cast<DwarfFunctionDebugInfo*>(
-                                               
targetFunction->GetFunctionDebugInfo());
-                               if (targetInfo != NULL) {
-                                       DIESubprogram* subProgram = 
targetInfo->SubprogramEntry();
-                                       DIEType* returnType = 
subProgram->ReturnType();
-                                       if (returnType == NULL) {
-                                               // function doesn't return a 
value, we're done.
-                                               return B_OK;
-                                       }
-
-                                       ValueLocation* location;
-                                       result = 
fArchitecture->GetReturnAddressLocation(frame,
-                                               
returnType->ByteSize()->constant, location);
-                                       if (result != B_OK)
-                                               return result;
-                                       BReference<ValueLocation> 
locationReference(location,
-                                               true);
-                                       Variable* variable = NULL;
-                                       BReference<FunctionID> idReference(
-                                               
targetFunction->GetFunctionID(), true);
-                                       result = 
factory.CreateReturnValue(idReference,
-                                               returnType, location, variable);
-                                       if (result != B_OK)
-                                               return result;
-                                       BReference<Variable> 
variableReference(variable, true);
-                                       if (!frame->AddLocalVariable(variable))
-                                               return B_NO_MEMORY;
-                               }
+       FunctionInstance* targetFunction;
+       if (targetAddress >= fPLTSectionStart && targetAddress < 
fPLTSectionEnd) {
+               // TODO: resolve actual target address in the PIC case
+               // and adjust targetAddress accordingly
+       }
+       ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
+       targetFunction = imageInfo->FunctionAtAddress(targetAddress);
+       if (targetFunction != NULL) {
+               DwarfFunctionDebugInfo* targetInfo =
+                       dynamic_cast<DwarfFunctionDebugInfo*>(
+                               targetFunction->GetFunctionDebugInfo());
+               if (targetInfo != NULL) {
+                       DIESubprogram* subProgram = 
targetInfo->SubprogramEntry();
+                       DIEType* returnType = subProgram->ReturnType();
+                       if (returnType == NULL) {
+                               // function doesn't return a value, we're done.
+                               return B_OK;
                        }
+
+                       ValueLocation* location;
+                       result = fArchitecture->GetReturnAddressLocation(frame,
+                               returnType->ByteSize()->constant, location);
+                       if (result != B_OK)
+                               return result;
+                       BReference<ValueLocation> locationReference(location, 
true);
+                       Variable* variable = NULL;
+                       BReference<FunctionID> idReference(
+                               targetFunction->GetFunctionID(), true);
+                       result = factory.CreateReturnValue(idReference, 
returnType,
+                               location, variable);
+                       if (result != B_OK)
+                               return result;
+                       BReference<Variable> variableReference(variable, true);
+                       if (!frame->AddLocalVariable(variable))
+                               return B_NO_MEMORY;
                }
        }
 
diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h 
b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
index 4c9b0c1..56cd1c1 100644
--- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
@@ -64,6 +64,7 @@ public:
                                                                        
FunctionInstance* functionInstance,
                                                                        
CpuState* cpuState,
                                                                        bool 
getFullFrameInfo,
+                                                                       bool 
getReturnValue,
                                                                        
StackFrame*& _frame,
                                                                        
CpuState*& _previousCpuState);
        virtual status_t                        GetStatement(FunctionDebugInfo* 
function,
diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h 
b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h
index 7287964..4d42463 100644
--- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h
@@ -56,6 +56,7 @@ public:
                                                                        
FunctionInstance* functionInstance,
                                                                        
CpuState* cpuState,
                                                                        bool 
getFullFrameInfo,
+                                                                       bool 
getReturnValue,
                                                                        
StackFrame*& _Frame,
                                                                        
CpuState*& _previousCpuState) = 0;
                                                                                
// returns reference to previous frame
diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp 
b/src/apps/debugger/jobs/GetStackTraceJob.cpp
index 61a1c72..2f08190 100644
--- a/src/apps/debugger/jobs/GetStackTraceJob.cpp
+++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp
@@ -58,7 +58,7 @@ GetStackTraceJob::Do()
        // get the stack trace
        StackTrace* stackTrace;
        status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), 
this,
-               fCpuState, stackTrace);
+               fCpuState, stackTrace, fThread->ExecutedSubroutine());
        if (error != B_OK)
                return error;
        BReference<StackTrace> stackTraceReference(stackTrace, true);
diff --git a/src/apps/debugger/model/Thread.cpp 
b/src/apps/debugger/model/Thread.cpp
index c6692f8..f289bca 100644
--- a/src/apps/debugger/model/Thread.cpp
+++ b/src/apps/debugger/model/Thread.cpp
@@ -17,6 +17,7 @@ Thread::Thread(Team* team, thread_id threadID)
        fTeam(team),
        fID(threadID),
        fState(THREAD_STATE_UNKNOWN),
+       fExecutedSubroutine(false),
        fStoppedReason(THREAD_STOPPED_UNKNOWN),
        fCpuState(NULL),
        fStackTrace(NULL)
@@ -68,6 +69,7 @@ Thread::SetState(uint32 state, uint32 reason, const BString& 
info)
        if (fState != THREAD_STATE_STOPPED) {
                SetCpuState(NULL);
                SetStackTrace(NULL);
+               fExecutedSubroutine = false;
        }
 
        fTeam->NotifyThreadStateChanged(this);
@@ -108,3 +110,11 @@ Thread::SetStackTrace(StackTrace* trace)
 
        fTeam->NotifyThreadStackTraceChanged(this);
 }
+
+
+void
+Thread::SetExecutedSubroutine()
+{
+       fExecutedSubroutine = true;
+}
+
diff --git a/src/apps/debugger/model/Thread.h b/src/apps/debugger/model/Thread.h
index e34064f..8ac0861 100644
--- a/src/apps/debugger/model/Thread.h
+++ b/src/apps/debugger/model/Thread.h
@@ -67,11 +67,16 @@ public:
                        StackTrace*                     GetStackTrace() const   
{ return fStackTrace; }
                        void                            
SetStackTrace(StackTrace* trace);
 
+                       bool                            ExecutedSubroutine() 
const
+                                                                       { 
return fExecutedSubroutine; }
+                       void                            SetExecutedSubroutine();
+
 private:
                        Team*                           fTeam;
                        thread_id                       fID;
                        BString                         fName;
                        uint32                          fState;
+                       bool                            fExecutedSubroutine;
                        uint32                          fStoppedReason;
                        BString                         fStoppedReasonInfo;
                        CpuState*                       fCpuState;

############################################################################

Commit:      bdbbc10b44c078b1738588d1a1b62ed1325dcd96
URL:         http://cgit.haiku-os.org/haiku/commit/?id=bdbbc10
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Tue Jan  1 03:52:34 2013 UTC

Thread now also tracks the address of the last executed function.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/model/Thread.cpp 
b/src/apps/debugger/model/Thread.cpp
index f289bca..63d21e0 100644
--- a/src/apps/debugger/model/Thread.cpp
+++ b/src/apps/debugger/model/Thread.cpp
@@ -18,6 +18,7 @@ Thread::Thread(Team* team, thread_id threadID)
        fID(threadID),
        fState(THREAD_STATE_UNKNOWN),
        fExecutedSubroutine(false),
+       fSubroutineAddress(0),
        fStoppedReason(THREAD_STOPPED_UNKNOWN),
        fCpuState(NULL),
        fStackTrace(NULL)
@@ -70,6 +71,7 @@ Thread::SetState(uint32 state, uint32 reason, const BString& 
info)
                SetCpuState(NULL);
                SetStackTrace(NULL);
                fExecutedSubroutine = false;
+               fSubroutineAddress = 0;
        }
 
        fTeam->NotifyThreadStateChanged(this);
@@ -113,8 +115,9 @@ Thread::SetStackTrace(StackTrace* trace)
 
 
 void
-Thread::SetExecutedSubroutine()
+Thread::SetExecutedSubroutine(target_addr_t address)
 {
        fExecutedSubroutine = true;
+       fSubroutineAddress = address;
 }
 
diff --git a/src/apps/debugger/model/Thread.h b/src/apps/debugger/model/Thread.h
index 8ac0861..1cba07f 100644
--- a/src/apps/debugger/model/Thread.h
+++ b/src/apps/debugger/model/Thread.h
@@ -11,6 +11,8 @@
 #include <Referenceable.h>
 #include <util/DoublyLinkedList.h>
 
+#include "types/Types.h"
+
 
 class CpuState;
 class StackTrace;
@@ -69,7 +71,9 @@ public:
 
                        bool                            ExecutedSubroutine() 
const
                                                                        { 
return fExecutedSubroutine; }
-                       void                            SetExecutedSubroutine();
+                       target_addr_t           SubroutineAddress() const
+                                                                       { 
return fSubroutineAddress; }
+                       void                            
SetExecutedSubroutine(target_addr_t address);
 
 private:
                        Team*                           fTeam;
@@ -77,6 +81,7 @@ private:
                        BString                         fName;
                        uint32                          fState;
                        bool                            fExecutedSubroutine;
+                       target_addr_t           fSubroutineAddress;
                        uint32                          fStoppedReason;
                        BString                         fStoppedReasonInfo;
                        CpuState*                       fCpuState;

############################################################################

Revision:    hrev45116
Commit:      5745a40dd1813a745fc4b899862597c3f618ef6c
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5745a40
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Tue Jan  1 03:54:39 2013 UTC

Rework how return values are handled.

- ArchitectureX86 now hands off the work for GetInstructionInfo() to
  DisassemblerX86, since the latter has all the information we need
  to properly classify and evaluate instructions. Correspondingly a
  CpuState is passed down to it in order to perform address calculations
  for the instruction if it's a jump or call instruction. The latter's
  targets are then stored on the thread for later retrieval when
  constructing a stack trace. Adjust X86_64 accordingly for the
  signature changes. This also fixes a bug where Step Over would
  sometimes result in a Step Into instead due to the previous
  implementation of GetInstructionInfo() occasionally failing to
  classify call instructions correctly.

- Architecture::CreateStackTrace() now takes an argument specifying
  the address of the last executed function if applicable. This is used
  to decide who/where to decode a return value from. Adjust callers.

- DwarfImageDebugInfo::_CreateReturnValue() uses the above information
  in order to know directly who the caller it needs to look up a return
  value for is, rather than trying to walk backwards to find them.
  Type resolution is now also a bit more sophisticated due to various
  cases where the subprogram entry didn't directly contain the return
  type but referred to another DIE that did. Retrieving return value
  now appears to work properly in all cases except when position
  independent code is involved. The latter however will require
  resolving the appropriate function address in the PLT, which will
  need some additional work.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/arch/Architecture.cpp 
b/src/apps/debugger/arch/Architecture.cpp
index 4da0641..c1724f7 100644
--- a/src/apps/debugger/arch/Architecture.cpp
+++ b/src/apps/debugger/arch/Architecture.cpp
@@ -94,8 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const
 status_t
 Architecture::CreateStackTrace(Team* team,
        ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
-       StackTrace*& _stackTrace, bool getReturnValue, int32 maxStackDepth,
-       bool useExistingTrace, bool getFullFrameInfo)
+       StackTrace*& _stackTrace, target_addr_t returnFunctionAddress,
+       int32 maxStackDepth, bool useExistingTrace, bool getFullFrameInfo)
 {
        BReference<CpuState> cpuStateReference(cpuState);
 
@@ -163,7 +163,7 @@ Architecture::CreateStackTrace(Team* team,
                if (function != NULL) {
                        status_t error = 
functionDebugInfo->GetSpecificImageDebugInfo()
                                ->CreateFrame(image, function, cpuState, 
getFullFrameInfo,
-                                       nextFrame == NULL ? getReturnValue : 
false, frame,
+                                       nextFrame == NULL ? 
returnFunctionAddress : 0, frame,
                                        previousCpuState);
                        if (error != B_OK && error != B_UNSUPPORTED)
                                break;
diff --git a/src/apps/debugger/arch/Architecture.h 
b/src/apps/debugger/arch/Architecture.h
index 3ab3f7d..d9610ba 100644
--- a/src/apps/debugger/arch/Architecture.h
+++ b/src/apps/debugger/arch/Architecture.h
@@ -103,13 +103,14 @@ public:
                                                                        
target_addr_t address,
                                                                        
Statement*& _statement) = 0;
        virtual status_t                        
GetInstructionInfo(target_addr_t address,
-                                                                       
InstructionInfo& _info) = 0;
+                                                                       
InstructionInfo& _info,
+                                                                       
CpuState* state) = 0;
 
                        status_t                        CreateStackTrace(Team* 
team,
                                                                        
ImageDebugInfoProvider* imageInfoProvider,
                                                                        
CpuState* cpuState,
                                                                        
StackTrace*& _stackTrace,
-                                                                       bool 
getReturnValue,
+                                                                       
target_addr_t returnFunctionAddress,
                                                                        int32 
maxStackDepth = -1,
                                                                        bool 
useExistingTrace = false,
                                                                        bool 
getFullFrameInfo = true);
diff --git a/src/apps/debugger/arch/InstructionInfo.h 
b/src/apps/debugger/arch/InstructionInfo.h
index f130080..25e9e36 100644
--- a/src/apps/debugger/arch/InstructionInfo.h
+++ b/src/apps/debugger/arch/InstructionInfo.h
@@ -12,6 +12,7 @@
 
 enum instruction_type {
        INSTRUCTION_TYPE_SUBROUTINE_CALL,
+       INSTRUCTION_TYPE_JUMP,
        INSTRUCTION_TYPE_OTHER
 };
 
diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp 
b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
index c7995d5..39e5c7f 100644
--- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp
+++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
@@ -561,7 +561,7 @@ ArchitectureX86::GetStatement(FunctionDebugInfo* function,
 // TODO: This is not architecture dependent anymore!
        // get the instruction info
        InstructionInfo info;
-       status_t error = GetInstructionInfo(address, info);
+       status_t error = GetInstructionInfo(address, info, NULL);
        if (error != B_OK)
                return error;
 
@@ -578,7 +578,7 @@ ArchitectureX86::GetStatement(FunctionDebugInfo* function,
 
 status_t
 ArchitectureX86::GetInstructionInfo(target_addr_t address,
-       InstructionInfo& _info)
+       InstructionInfo& _info, CpuState* state)
 {
        // read the code - maximum x86{-64} instruction size = 15 bytes
        uint8 buffer[16];
@@ -593,40 +593,7 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address,
        if (error != B_OK)
                return error;
 
-       // disassemble the instruction
-       BString line;
-       target_addr_t instructionAddress;
-       target_addr_t targetAddress = 0;
-       target_size_t instructionSize;
-       bool breakpointAllowed;
-       error = disassembler.GetNextInstruction(line, instructionAddress,
-               instructionSize, breakpointAllowed);
-       if (error != B_OK)
-               return error;
-
-       instruction_type instructionType = INSTRUCTION_TYPE_OTHER;
-       if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
-               // absolute call with r/m32
-               instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
-               // TODO: retrieve target address (might be in a register)
-       } else if (buffer[0] == 0xe8 && instructionSize == 5) {
-               // relative call with rel32 -- don't categorize the call with 0 
as
-               // subroutine call, since it is only used to get the address of 
the GOT
-               if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
-                       || buffer[4] != 0) {
-                       instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
-                       int32 offset;
-                       memcpy(&offset, &buffer[1], 4);
-                       targetAddress = instructionAddress + instructionSize + 
offset;
-               }
-       }
-
-       if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
-                       instructionType, breakpointAllowed, line)) {
-               return B_NO_MEMORY;
-       }
-
-       return B_OK;
+       return disassembler.GetNextInstructionInfo(_info, state);
 }
 
 
diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h 
b/src/apps/debugger/arch/x86/ArchitectureX86.h
index 1549f9b..1a6120c 100644
--- a/src/apps/debugger/arch/x86/ArchitectureX86.h
+++ b/src/apps/debugger/arch/x86/ArchitectureX86.h
@@ -59,7 +59,7 @@ public:
                                                                        
target_addr_t address,
                                                                        
Statement*& _statement);
        virtual status_t                        
GetInstructionInfo(target_addr_t address,
-                                                                       
InstructionInfo& _info);
+                                                                       
InstructionInfo& _info, CpuState* state);
 
        virtual status_t                        GetWatchpointDebugCapabilities(
                                                                        int32& 
_maxRegisterCount,
diff --git a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp 
b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp
index f20838e..e686d7e 100644
--- a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp
+++ b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp
@@ -12,6 +12,36 @@
 
 #include <OS.h>
 
+#include "CpuStateX86.h"
+#include "InstructionInfo.h"
+
+
+static uint8 RegisterNumberFromUdisIndex(int32 udisIndex)
+{
+       switch (udisIndex) {
+               case UD_R_RIP: return X86_REGISTER_EIP;
+               case UD_R_ESP: return X86_REGISTER_ESP;
+               case UD_R_EBP: return X86_REGISTER_EBP;
+
+               case UD_R_EAX: return X86_REGISTER_EAX;
+               case UD_R_EBX: return X86_REGISTER_EBX;
+               case UD_R_ECX: return X86_REGISTER_ECX;
+               case UD_R_EDX: return X86_REGISTER_EDX;
+
+               case UD_R_ESI: return X86_REGISTER_ESI;
+               case UD_R_EDI: return X86_REGISTER_EDI;
+
+               case UD_R_CS: return X86_REGISTER_CS;
+               case UD_R_DS: return X86_REGISTER_DS;
+               case UD_R_ES: return X86_REGISTER_ES;
+               case UD_R_FS: return X86_REGISTER_FS;
+               case UD_R_GS: return X86_REGISTER_GS;
+               case UD_R_SS: return X86_REGISTER_SS;
+       }
+
+       return X86_INT_REGISTER_END;
+}
+
 
 struct DisassemblerX86::UdisData : ud_t {
 };
@@ -108,3 +138,85 @@ DisassemblerX86::GetPreviousInstruction(target_addr_t 
nextAddress,
                }
        }
 }
+
+
+status_t
+DisassemblerX86::GetNextInstructionInfo(InstructionInfo& _info,
+       CpuState* state)
+{
+       unsigned int size = ud_disassemble(fUdisData);
+       if (size < 1)
+               return B_ENTRY_NOT_FOUND;
+
+       uint32 address = (uint32)ud_insn_off(fUdisData);
+
+       instruction_type type = INSTRUCTION_TYPE_OTHER;
+       target_addr_t targetAddress = 0;
+
+       if (fUdisData->mnemonic == UD_Icall)
+               type = INSTRUCTION_TYPE_SUBROUTINE_CALL;
+       else if (fUdisData->mnemonic == UD_Ijmp)
+               type = INSTRUCTION_TYPE_JUMP;
+       if (state != NULL)
+               targetAddress = GetInstructionTargetAddress(state);
+
+       char buffer[256];
+       snprintf(buffer, sizeof(buffer), "0x%08" B_PRIx32 ": %16.16s  %s", 
address,
+               ud_insn_hex(fUdisData), ud_insn_asm(fUdisData));
+                       // TODO: Resolve symbols!
+
+       if (!_info.SetTo(address, targetAddress, size, type, true, buffer))
+               return B_NO_MEMORY;
+
+       return B_OK;
+}
+
+
+target_addr_t
+DisassemblerX86::GetInstructionTargetAddress(CpuState* state) const
+{
+       if (fUdisData->mnemonic != UD_Icall && fUdisData->mnemonic != UD_Ijmp)
+               return 0;
+
+       CpuStateX86* x86State = dynamic_cast<CpuStateX86*>(state);
+       if (x86State == NULL)
+               return 0;
+
+       target_addr_t targetAddress = 0;
+       switch (fUdisData->operand[0].type) {
+               case UD_OP_REG:
+               {
+                       targetAddress = x86State->IntRegisterValue(
+                               
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
+                       targetAddress += fUdisData->operand[0].offset;
+               }
+               break;
+               case UD_OP_MEM:
+               {
+                       targetAddress = x86State->IntRegisterValue(
+                               
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
+                       targetAddress += x86State->IntRegisterValue(
+                               
RegisterNumberFromUdisIndex(fUdisData->operand[0].index))
+                               * fUdisData->operand[0].scale;
+               }
+               break;
+               case UD_OP_JIMM:
+               {
+                       targetAddress = ud_insn_off(fUdisData)
+                               + fUdisData->operand[0].lval.sdword + 
ud_insn_len(fUdisData);
+               }
+               break;
+
+               case UD_OP_IMM:
+               case UD_OP_CONST:
+               {
+                       targetAddress = fUdisData->operand[0].lval.udword;
+               }
+               break;
+
+               default:
+               break;
+       }
+
+       return targetAddress;
+}
diff --git a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h 
b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h
index b66a0ad..9d49525 100644
--- a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h
+++ b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h
@@ -10,6 +10,10 @@
 #include "Types.h"
 
 
+class CpuState;
+class InstructionInfo;
+
+
 class DisassemblerX86 {
 public:
                                                                
DisassemblerX86();
@@ -27,6 +31,14 @@ public:
                                                                        
target_addr_t& _address,
                                                                        
target_size_t& _size);
 
+       virtual status_t                        GetNextInstructionInfo(
+                                                                       
InstructionInfo& _info,
+                                                                       
CpuState* state);
+
+
+private:
+                       target_addr_t           GetInstructionTargetAddress(
+                                                                       
CpuState* state) const;
 private:
                        struct UdisData;
 
diff --git a/src/apps/debugger/arch/x86/disasm/Jamfile 
b/src/apps/debugger/arch/x86/disasm/Jamfile
index a916ab0..0b40f9f 100644
--- a/src/apps/debugger/arch/x86/disasm/Jamfile
+++ b/src/apps/debugger/arch/x86/disasm/Jamfile
@@ -3,9 +3,12 @@ SubDir HAIKU_TOP src apps debugger arch x86 disasm ;
 CCFLAGS +=  -Werror ;
 C++FLAGS += -Werror ;
 
+UsePrivateHeaders shared ;
+
 UseHeaders [ LibraryHeaders udis86 ] ;
 UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ;
 
+SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
 SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
 SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ;
 
diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
index acf2f93..05ba2a4 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
@@ -451,7 +451,7 @@ ArchitectureX8664::GetStatement(FunctionDebugInfo* function,
 // TODO: This is not architecture dependent anymore!
        // get the instruction info
        InstructionInfo info;
-       status_t error = GetInstructionInfo(address, info);
+       status_t error = GetInstructionInfo(address, info, NULL);
        if (error != B_OK)
                return error;
 
@@ -468,7 +468,7 @@ ArchitectureX8664::GetStatement(FunctionDebugInfo* function,
 
 status_t
 ArchitectureX8664::GetInstructionInfo(target_addr_t address,
-       InstructionInfo& _info)
+       InstructionInfo& _info, CpuState* state)
 {
        // read the code
        uint8 buffer[16];
diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
index f61b8f3..2ff90be 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
@@ -60,7 +60,7 @@ public:
                                                                        
target_addr_t address,
                                                                        
Statement*& _statement);
        virtual status_t                        
GetInstructionInfo(target_addr_t address,
-                                                                       
InstructionInfo& _info);
+                                                                       
InstructionInfo& _info, CpuState* state);
 
        virtual status_t                        GetWatchpointDebugCapabilities(
                                                                        int32& 
_maxRegisterCount,
diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp 
b/src/apps/debugger/controllers/ThreadHandler.cpp
index 7913da9..6a2fe94 100644
--- a/src/apps/debugger/controllers/ThreadHandler.cpp
+++ b/src/apps/debugger/controllers/ThreadHandler.cpp
@@ -253,7 +253,7 @@ ThreadHandler::HandleThreadAction(uint32 action)
 
        if (stackTrace == NULL && cpuState != NULL) {
                if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                               fThread->GetTeam(), this, cpuState, stackTrace, 
false, 1,
+                               fThread->GetTeam(), this, cpuState, stackTrace, 
0, 1,
                                false, false) == B_OK) {
                        stackTraceReference.SetTo(stackTrace, true);
                }
@@ -469,7 +469,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
        // just single-step, otherwise we set a breakpoint after the 
instruction.
        InstructionInfo info;
        if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
-                       cpuState->InstructionPointer(), info) != B_OK) {
+                       cpuState->InstructionPointer(), info, cpuState) != 
B_OK) {
                TRACE_CONTROL("  failed to get instruction info\n");
                return false;
        }
@@ -484,7 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
        TRACE_CONTROL("  subroutine call -- installing breakpoint at address "
                "%#" B_PRIx64 "\n", info.Address() + info.Size());
 
-       fThread->SetExecutedSubroutine();
+       fThread->SetExecutedSubroutine(info.TargetAddress());
        if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
                return false;
 
@@ -566,8 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
 
                        if (stackTrace == NULL && cpuState != NULL) {
                                if 
(fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                                               fThread->GetTeam(), this, 
cpuState, stackTrace, false,
-                                               1, false, false) == B_OK) {
+                                               fThread->GetTeam(), this, 
cpuState, stackTrace, 0, 1,
+                                               false, false) == B_OK) {
                                        stackTraceReference.SetTo(stackTrace, 
true);
                                }
                        }
@@ -608,7 +608,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
                        // That's the return address, so we're done in theory,
                        // unless we're a recursive function. Check if we've 
actually
                        // exited the previous stack frame or not.
-                       fThread->SetExecutedSubroutine();
+                       
fThread->SetExecutedSubroutine(cpuState->InstructionPointer());
                        target_addr_t framePointer = 
cpuState->StackFramePointer();
                        bool hasExitedFrame = 
fDebuggerInterface->GetArchitecture()
                                ->StackGrowthDirection() == 
STACK_GROWTH_DIRECTION_POSITIVE
@@ -653,8 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
 
                        if (stackTrace == NULL && cpuState != NULL) {
                                if 
(fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                                               fThread->GetTeam(), this, 
cpuState, stackTrace, false,
-                                               1, false, false) == B_OK) {
+                                               fThread->GetTeam(), this, 
cpuState, stackTrace, 0, 1,
+                                               false, false) == B_OK) {
                                        stackTraceReference.SetTo(stackTrace, 
true);
                                }
                        }
@@ -685,7 +685,7 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
                                BReference<StackTrace> 
stackTraceReference(stackTrace);
                                if (stackTrace == NULL && cpuState != NULL) {
                                        if 
(fDebuggerInterface->GetArchitecture()->CreateStackTrace(
-                                                       fThread->GetTeam(), 
this, cpuState, stackTrace, false,
+                                                       fThread->GetTeam(), 
this, cpuState, stackTrace, 0,
                                                        1, false, false) == 
B_OK) {
                                                
stackTraceReference.SetTo(stackTrace, true);
                                        }
@@ -693,7 +693,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
 
                                if (stackTrace != NULL && stackTrace->FrameAt(0)
                                                ->FrameAddress() != 
fPreviousFrameAddress) {
-                                       fThread->SetExecutedSubroutine();
+                                       fThread->SetExecutedSubroutine(
+                                               cpuState->InstructionPointer());
                                }
 
                                return false;
diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp 
b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
index 1ff7ac8..b40e08c 100644
--- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
+++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
@@ -68,8 +68,8 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t 
address)
 status_t
 DebuggerImageDebugInfo::CreateFrame(Image* image,
        FunctionInstance* functionInstance, CpuState* cpuState,
-       bool getFullFrameInfo, bool getReturnValue, StackFrame*& _previousFrame,
-       CpuState*& _previousCpuState)
+       bool getFullFrameInfo, target_addr_t returnFunctionAddress,
+       StackFrame*& _previousFrame, CpuState*& _previousCpuState)
 {
        return B_UNSUPPORTED;
 }
diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h 
b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
index 981dbd8..bcafebc 100644
--- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
@@ -36,7 +36,7 @@ public:
                                                                        
FunctionInstance* functionInstance,
                                                                        
CpuState* cpuState,
                                                                        bool 
getFullFrameInfo,
-                                                                       bool 
getReturnValue,
+                                                                       
target_addr_t returnFunctionAddress,
                                                                        
StackFrame*& _previousFrame,
                                                                        
CpuState*& _previousCpuState);
        virtual status_t                        GetStatement(FunctionDebugInfo* 
function,
diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp 
b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
index c7448e0..6d60b1b 100644
--- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
+++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
@@ -522,8 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t 
address)
 status_t
 DwarfImageDebugInfo::CreateFrame(Image* image,
        FunctionInstance* functionInstance, CpuState* cpuState,
-       bool getFullFrameInfo, bool getReturnValue, StackFrame*& _frame,
-       CpuState*& _previousCpuState)
+       bool getFullFrameInfo, target_addr_t returnFunctionAddress,
+       StackFrame*& _frame, CpuState*& _previousCpuState)
 {
        DwarfFunctionDebugInfo* function = 
dynamic_cast<DwarfFunctionDebugInfo*>(
                functionInstance->GetFunctionDebugInfo());
@@ -673,9 +673,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
                        instructionPointer, functionInstance->Address() - 
fRelocationDelta,
                        subprogramEntry->Variables(), 
subprogramEntry->Blocks());
 
-               if (getReturnValue) {
-                       _CreateReturnValue(functionInstance, image, function, 
frame,
-                               *stackFrameDebugInfo, instructionPointer);
+               if (returnFunctionAddress != 0) {
+                       _CreateReturnValue(returnFunctionAddress, image, frame,
+                               *stackFrameDebugInfo);
                }
        }
 
@@ -1086,75 +1086,28 @@ 
DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
 
 
 status_t
-DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
-       Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame,
-       DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
+DwarfImageDebugInfo::_CreateReturnValue(target_addr_t returnFunctionAddress,
+       Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
 {
-       // the thread just executed a subroutine, look for the last call
-       // instruction.
-       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;
-
-       InstructionInfo info;
-       do {
-               TargetAddressRange range = statement->CoveringAddressRange();
-               result = fArchitecture->GetInstructionInfo(range.Start(), info);
-               if (result != B_OK)
-                       return result;
-
-               if (info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL)
-                       break;
-
-               previousStatementAddress = 
statement->CoveringAddressRange().Start() - 1;
-               statement = sourceCode->StatementAtAddress(
-                       previousStatementAddress);
-       } while (statement != NULL);
-
-       // we weren't able to find a subroutine call by stepping back
-       // so we can't retrieve a return value
-       if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL)
-               return B_OK;
-
-       target_addr_t targetAddress = info.TargetAddress();
-       if (targetAddress == 0)
-               return B_BAD_VALUE;
-
-       if (!image->ContainsAddress(targetAddress)) {
+       if (!image->ContainsAddress(returnFunctionAddress)) {
                // our current image doesn't contain the target function,
                // locate the one which does.
-               image = image->GetTeam()->ImageByAddress(targetAddress);
+               image = image->GetTeam()->ImageByAddress(returnFunctionAddress);
                if (image == NULL)
                        return B_BAD_VALUE;
        }
 
+       status_t result = B_OK;
        FunctionInstance* targetFunction;
-       if (targetAddress >= fPLTSectionStart && targetAddress < 
fPLTSectionEnd) {
-               // TODO: resolve actual target address in the PIC case
-               // and adjust targetAddress accordingly
+       if (returnFunctionAddress >= fPLTSectionStart
+               && returnFunctionAddress < fPLTSectionEnd) {
+               // TODO: handle resolving PLT entries
+               // to their target function
+               return B_UNSUPPORTED;
        }
+
        ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
-       targetFunction = imageInfo->FunctionAtAddress(targetAddress);
+       targetFunction = imageInfo->FunctionAtAddress(returnFunctionAddress);
        if (targetFunction != NULL) {
                DwarfFunctionDebugInfo* targetInfo =
                        dynamic_cast<DwarfFunctionDebugInfo*>(
@@ -1163,15 +1116,30 @@ 
DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
                        DIESubprogram* subProgram = 
targetInfo->SubprogramEntry();
                        DIEType* returnType = subProgram->ReturnType();
                        if (returnType == NULL) {
+                               // check if we have a specification, and if so, 
if that has
+                               // a return type
+                               subProgram = 
dynamic_cast<DIESubprogram*>(subProgram->Specification());
+                               if (subProgram != NULL)
+                                       returnType = subProgram->ReturnType();
+
                                // function doesn't return a value, we're done.
-                               return B_OK;
+                               if (returnType == NULL)
+                                       return B_OK;
                        }
 
+                       uint32 byteSize = 0;
+                       if (returnType->ByteSize() == NULL) {
+                               if 
(dynamic_cast<DIEAddressingType*>(returnType) != NULL)
+                                       byteSize = fArchitecture->AddressSize();
+                       } else
+                               byteSize = returnType->ByteSize()->constant;
+
                        ValueLocation* location;
                        result = fArchitecture->GetReturnAddressLocation(frame,
-                               returnType->ByteSize()->constant, location);
+                               byteSize, location);
                        if (result != B_OK)
                                return result;
+
                        BReference<ValueLocation> locationReference(location, 
true);
                        Variable* variable = NULL;
                        BReference<FunctionID> idReference(
@@ -1180,6 +1148,7 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* 
functionInstance,
                                location, variable);
                        if (result != B_OK)
                                return result;
+
                        BReference<Variable> variableReference(variable, true);
                        if (!frame->AddLocalVariable(variable))
                                return B_NO_MEMORY;
diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h 
b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
index 56cd1c1..203920b 100644
--- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
@@ -64,7 +64,7 @@ public:
                                                                        
FunctionInstance* functionInstance,
                                                                        
CpuState* cpuState,
                                                                        bool 
getFullFrameInfo,
-                                                                       bool 
getReturnValue,
+                                                                       
target_addr_t returnFunctionAddress,
                                                                        
StackFrame*& _frame,
                                                                        
CpuState*& _previousCpuState);
        virtual status_t                        GetStatement(FunctionDebugInfo* 
function,
@@ -104,12 +104,11 @@ private:
                                                                        const 
EntryListWrapper& variableEntries,
                                                                        const 
EntryListWrapper& blockEntries);
 
-                       status_t                        
_CreateReturnValue(FunctionInstance* instance,
+                       status_t                        _CreateReturnValue(
+                                                                       
target_addr_t returnFunctionAddress,
                                                                        Image* 
image,
-                                                                       
DwarfFunctionDebugInfo* info,
                                                                        
StackFrame* frame,
-                                                                       
DwarfStackFrameDebugInfo& factory,
-                                                                       
target_addr_t instructionPointer);
+                                                                       
DwarfStackFrameDebugInfo& factory);
 
                        bool                            
_EvaluateBaseTypeConstraints(DIEType* type,
                                                                        const 
TypeLookupConstraints& constraints);
diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h 
b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h
index 4d42463..ac655cd 100644
--- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h
+++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h
@@ -56,7 +56,7 @@ public:
                                                                        
FunctionInstance* functionInstance,
                                                                        
CpuState* cpuState,
                                                                        bool 
getFullFrameInfo,
-                                                                       bool 
getReturnValue,
+                                                                       
target_addr_t returnFunctionAddress,
                                                                        
StackFrame*& _Frame,
                                                                        
CpuState*& _previousCpuState) = 0;
                                                                                
// returns reference to previous frame
diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp 
b/src/apps/debugger/jobs/GetStackTraceJob.cpp
index 2f08190..23ce2fc 100644
--- a/src/apps/debugger/jobs/GetStackTraceJob.cpp
+++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp
@@ -58,7 +58,8 @@ GetStackTraceJob::Do()
        // get the stack trace
        StackTrace* stackTrace;
        status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), 
this,
-               fCpuState, stackTrace, fThread->ExecutedSubroutine());
+               fCpuState, stackTrace, fThread->ExecutedSubroutine()
+                       ? fThread->SubroutineAddress() : 0);
        if (error != B_OK)
                return error;
        BReference<StackTrace> stackTraceReference(stackTrace, true);


Other related posts:

  • » [haiku-commits] haiku: hrev45116 - in src/apps/debugger: debug_info arch/x86/disasm arch/x86 arch controllers - anevilyak