[haiku-commits] haiku: hrev45902 - src/apps/debugger/arch/x86_64

  • From: anevilyak@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 26 Jul 2013 02:16:06 +0200 (CEST)

hrev45902 adds 2 changesets to branch 'master'
old head: 271b27d5a3003bac4e3fdd0c5a170ee33a197566
new head: e94c611961473aa21a9ff162709039f155f89c37
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=e94c611+%5E271b27d

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

edffd6c: Debugger: Add interrupt vector CpuStateX8664.

e94c611: Debugger: Implement ArchitectureX8664::CreateStackFrame().
  
  This is for the most part a direct copy of the equivalent x86 function
  with adjustments to deal with the difference in address sizes and
  registers. This gets architectural (aka unassisted) backtraces working
  on x86-64, assuming the code in question has been built with frame pointers
  enabled.
  
  Thanks to Alex Smith for his assistance in implementing the
  function prologue and syscall iframe detection.

                                      [ Rene Gollent <anevilyak@xxxxxxxxx> ]

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

4 files changed, 167 insertions(+), 4 deletions(-)
.../debugger/arch/x86_64/ArchitectureX8664.cpp   | 160 ++++++++++++++++++-
.../debugger/arch/x86_64/ArchitectureX8664.h     |   2 +
src/apps/debugger/arch/x86_64/CpuStateX8664.cpp  |   5 +-
src/apps/debugger/arch/x86_64/CpuStateX8664.h    |   4 +

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

Commit:      edffd6cde853471c5fd68d9b2841c3983a309a15
URL:         http://cgit.haiku-os.org/haiku/commit/?id=edffd6c
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Fri Jul 26 00:11:28 2013 UTC

Debugger: Add interrupt vector CpuStateX8664.

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

diff --git a/src/apps/debugger/arch/x86_64/CpuStateX8664.cpp 
b/src/apps/debugger/arch/x86_64/CpuStateX8664.cpp
index daa5230..13e45d3 100644
--- a/src/apps/debugger/arch/x86_64/CpuStateX8664.cpp
+++ b/src/apps/debugger/arch/x86_64/CpuStateX8664.cpp
@@ -23,7 +23,8 @@ CpuStateX8664::CpuStateX8664()
 
 CpuStateX8664::CpuStateX8664(const x86_64_debug_cpu_state& state)
        :
-       fSetRegisters()
+       fSetRegisters(),
+       fInterruptVector(0)
 {
        SetIntRegister(X86_64_REGISTER_RIP, state.rip);
        SetIntRegister(X86_64_REGISTER_RSP, state.rsp);
@@ -48,6 +49,8 @@ CpuStateX8664::CpuStateX8664(const x86_64_debug_cpu_state& 
state)
        SetIntRegister(X86_64_REGISTER_FS, state.fs);
        SetIntRegister(X86_64_REGISTER_GS, state.gs);
        SetIntRegister(X86_64_REGISTER_SS, state.ss);
+
+       fInterruptVector = state.vector;
 }
 
 
diff --git a/src/apps/debugger/arch/x86_64/CpuStateX8664.h 
b/src/apps/debugger/arch/x86_64/CpuStateX8664.h
index de3f5b8..e30c588 100644
--- a/src/apps/debugger/arch/x86_64/CpuStateX8664.h
+++ b/src/apps/debugger/arch/x86_64/CpuStateX8664.h
@@ -69,6 +69,9 @@ public:
        virtual bool                            SetRegisterValue(const 
Register* reg,
                                                                        const 
BVariant& value);
 
+                       uint64                          InterruptVector() const
+                                                                       { 
return fInterruptVector; }
+
                        bool                            IsRegisterSet(int32 
index) const;
                        uint64                          IntRegisterValue(int32 
index) const;
                        void                            SetIntRegister(int32 
index, uint64 value);
@@ -80,6 +83,7 @@ private:
 private:
                        uint64                          
fIntRegisters[X86_64_REGISTER_COUNT];
                        RegisterBitSet          fSetRegisters;
+                       uint64                          fInterruptVector;
 };
 
 

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

Revision:    hrev45902
Commit:      e94c611961473aa21a9ff162709039f155f89c37
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e94c611
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Fri Jul 26 00:13:12 2013 UTC

Debugger: Implement ArchitectureX8664::CreateStackFrame().

This is for the most part a direct copy of the equivalent x86 function
with adjustments to deal with the difference in address sizes and
registers. This gets architectural (aka unassisted) backtraces working
on x86-64, assuming the code in question has been built with frame pointers
enabled.

Thanks to Alex Smith for his assistance in implementing the
function prologue and syscall iframe detection.

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

diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
index 3c27c87..4818fcc 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
@@ -1,7 +1,7 @@
 /*
  * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxx.
  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2011-2012, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2011-2013, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -61,6 +61,7 @@ static const int32 kFromDwarfRegisters[] = {
 };
 
 static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4;
+static const uint16 kFunctionPrologueSize = 4;
 
 
 // #pragma mark - ToDwarfRegisterMap
@@ -293,8 +294,140 @@ ArchitectureX8664::CreateStackFrame(Image* image, 
FunctionDebugInfo* function,
        CpuState* _cpuState, bool isTopFrame, StackFrame*& _frame,
        CpuState*& _previousCpuState)
 {
-       fprintf(stderr, "ArchitectureX8664::CreateStackFrame: TODO\n");
-       return B_UNSUPPORTED;
+       CpuStateX8664* cpuState = dynamic_cast<CpuStateX8664*>(_cpuState);
+       uint64 framePointer = cpuState->IntRegisterValue(X86_64_REGISTER_RBP);
+       uint64 rip = cpuState->IntRegisterValue(X86_64_REGISTER_RIP);
+
+       bool readStandardFrame = true;
+       uint64 previousFramePointer = 0;
+       uint64 returnAddress = 0;
+
+       // check for syscall frames
+       stack_frame_type frameType;
+       bool hasPrologue = false;
+       if (isTopFrame && cpuState->InterruptVector() == 99) {
+               // The thread is performing a syscall. So this frame is not 
really the
+               // top-most frame and we need to adjust the rip.
+               frameType = STACK_FRAME_TYPE_SYSCALL;
+               rip -= 2;
+                       // int 99, sysenter, and syscall all are 2 byte 
instructions
+
+               // The syscall stubs are frameless, the return address is on 
top of the
+               // stack.
+               uint32 rsp = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
+               uint32 address;
+               if (fTeamMemory->ReadMemory(rsp, &address, 8) == 8) {
+                       returnAddress = address;
+                       previousFramePointer = framePointer;
+                       framePointer = 0;
+                       readStandardFrame = false;
+               }
+       } else {
+               hasPrologue = _HasFunctionPrologue(function);
+               if (hasPrologue)
+                       frameType = STACK_FRAME_TYPE_STANDARD;
+               else
+                       frameType = STACK_FRAME_TYPE_FRAMELESS;
+               // TODO: Handling for frameless functions. It's not trivial to 
find the
+               // return address on the stack, though.
+
+               // If the function is not frameless and we're at the top frame 
we need
+               // to check whether the prologue has not been executed 
(completely) or
+               // we're already after the epilogue.
+               if (isTopFrame) {
+                       uint64 stack = 0;
+                       if (hasPrologue) {
+                               if (rip < function->Address() + 
kFunctionPrologueSize) {
+                                       // The prologue has not been executed 
yet, i.e. there's no
+                                       // stack frame yet. Get the return 
address from the stack.
+                                       stack = 
cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
+                                       if (rip > function->Address()) {
+                                               // The "push %rbp" has already 
been executed.
+                                               stack += 8;
+                                       }
+                               } else {
+                                       // Not in the function prologue, but 
maybe after the
+                                       // epilogue. The epilogue is a single 
"pop %rbp", so we
+                                       // check whether the current 
instruction is already a
+                                       // "ret".
+                                       uint8 code[1];
+                                       if (fTeamMemory->ReadMemory(rip, &code, 
1) == 1
+                                               && code[0] == 0xc3) {
+                                               stack = 
cpuState->IntRegisterValue(
+                                                       X86_64_REGISTER_RSP);
+                                       }
+                               }
+                       } else {
+                               // Check if the instruction pointer is at a 
readable location.
+                               // If it isn't, then chances are we got here 
via a bogus
+                               // function pointer, and the prologue hasn't 
actually been
+                               // executed. In such a case, what we need is 
right at the top
+                               // of the stack.
+                               uint8 data[1];
+                               if (fTeamMemory->ReadMemory(rip, &data, 1) != 1)
+                                       stack = 
cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
+                       }
+
+                       if (stack != 0) {
+                               uint64 address;
+                               if (fTeamMemory->ReadMemory(stack, &address, 8) 
== 8) {
+                                       returnAddress = address;
+                                       previousFramePointer = framePointer;
+                                       framePointer = 0;
+                                       readStandardFrame = false;
+                                       frameType = STACK_FRAME_TYPE_FRAMELESS;
+                               }
+                       }
+               }
+       }
+
+       // create the stack frame
+       StackFrameDebugInfo* stackFrameDebugInfo
+               = new(std::nothrow) NoOpStackFrameDebugInfo;
+       if (stackFrameDebugInfo == NULL)
+               return B_NO_MEMORY;
+       BReference<StackFrameDebugInfo> stackFrameDebugInfoReference(
+               stackFrameDebugInfo, true);
+
+       StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
+               framePointer, rip, stackFrameDebugInfo);
+       if (frame == NULL)
+               return B_NO_MEMORY;
+       BReference<StackFrame> frameReference(frame, true);
+
+       status_t error = frame->Init();
+       if (error != B_OK)
+               return error;
+
+       // read the previous frame and return address, if this is a standard 
frame
+       if (readStandardFrame) {
+               uint64 frameData[2];
+               if (framePointer != 0
+                       && fTeamMemory->ReadMemory(framePointer, frameData, 16) 
== 16) {
+                       previousFramePointer = frameData[0];
+                       returnAddress = frameData[1];
+               }
+       }
+
+       // create the CPU state, if we have any info
+       CpuStateX8664* previousCpuState = NULL;
+       if (returnAddress != 0) {
+               // prepare the previous CPU state
+               previousCpuState = new(std::nothrow) CpuStateX8664;
+               if (previousCpuState == NULL)
+                       return B_NO_MEMORY;
+
+               previousCpuState->SetIntRegister(X86_64_REGISTER_RBP,
+                       previousFramePointer);
+               previousCpuState->SetIntRegister(X86_64_REGISTER_RIP, 
returnAddress);
+               frame->SetPreviousCpuState(previousCpuState);
+       }
+
+       frame->SetReturnAddress(returnAddress);
+
+       _frame = frameReference.Detach();
+       _previousCpuState = previousCpuState;
+       return B_OK;
 }
 
 
@@ -529,3 +662,24 @@ ArchitectureX8664::_AddIntegerRegister(int32 index, const 
char* name,
        _AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), 
valueType,
                type, calleePreserved);
 }
+
+
+bool
+ArchitectureX8664::_HasFunctionPrologue(FunctionDebugInfo* function) const
+{
+       if (function == NULL)
+               return false;
+
+       // check whether the function has the typical prologue
+       if (function->Size() < kFunctionPrologueSize)
+               return false;
+
+       uint8 buffer[kFunctionPrologueSize];
+       if (fTeamMemory->ReadMemory(function->Address(), buffer,
+                       kFunctionPrologueSize) != kFunctionPrologueSize) {
+               return false;
+       }
+
+       return buffer[0] == 0x55 && buffer[1] == 0x48 && buffer[2] == 0x89
+               && buffer[3] == 0xe5;
+}
diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h 
b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
index 2ff90be..e448ba1 100644
--- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
+++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
@@ -83,6 +83,8 @@ private:
                                                                        const 
char* name, uint32 valueType,
                                                                        
register_type type, bool calleePreserved);
 
+                       bool                            _HasFunctionPrologue(
+                                                                       
FunctionDebugInfo* function) const;
 private:
                        Array<Register>         fRegisters;
                        SourceLanguage*         fAssemblyLanguage;


Other related posts:

  • » [haiku-commits] haiku: hrev45902 - src/apps/debugger/arch/x86_64 - anevilyak