summaryrefslogtreecommitdiff
path: root/src/vm/amd64
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2015-02-16 15:43:50 +0100
committerJan Vorlicek <janvorli@microsoft.com>2015-02-16 15:43:50 +0100
commitfb11bcafc8bae0924b51ed4483ed35d884852dc4 (patch)
treed3433a943bcf8e277cd2618be3e411e17a1db617 /src/vm/amd64
parent0e20a9e34ad2b861460c2772865653082ca06dfd (diff)
downloadcoreclr-fb11bcafc8bae0924b51ed4483ed35d884852dc4.tar.gz
coreclr-fb11bcafc8bae0924b51ed4483ed35d884852dc4.tar.bz2
coreclr-fb11bcafc8bae0924b51ed4483ed35d884852dc4.zip
Implement native stack unwinding for Linux
This change implements native stack unwinding using the libunwind on Linux. I have also fixed bunch of issues / details in the related code: 1) 0x in front of %p inside format string 2) Subtraction of -1 from dl_info.dli_sname 3) Added .cfi_xxxx annotation to the CallDescrWorkerInternal and the LEAF_ENTRY / LEAF_END macros. 4) Changed local labels in the CallDescrWorkerInternal to be prefixed by .L to see the CallDescrWorkerInternal in the stack trace 5) Changed moveOWord to use movdqu - it was being called with one of the parameters unaligned
Diffstat (limited to 'src/vm/amd64')
-rw-r--r--src/vm/amd64/calldescrworkeramd64.S43
-rw-r--r--src/vm/amd64/excepamd64.cpp9
-rw-r--r--src/vm/amd64/gmsamd64.cpp14
-rw-r--r--src/vm/amd64/unixasmhelpers.S4
-rw-r--r--src/vm/amd64/unixasmmacros.inc6
5 files changed, 46 insertions, 30 deletions
diff --git a/src/vm/amd64/calldescrworkeramd64.S b/src/vm/amd64/calldescrworkeramd64.S
index a126ad18d7..7b108dc402 100644
--- a/src/vm/amd64/calldescrworkeramd64.S
+++ b/src/vm/amd64/calldescrworkeramd64.S
@@ -42,8 +42,12 @@ NESTED_END FastCallFinalizeWorker, _TEXT
NESTED_ENTRY CallDescrWorkerInternal, _TEXT, CallDescrWorkerUnwindFrameChainHandler
push_nonvol_reg rbx // save nonvolatile registers
+ .cfi_def_cfa_offset 16 //
push_nonvol_reg rbp //
+ .cfi_adjust_cfa_offset 8 //
+ .cfi_offset rbp, -24 //
set_frame rbp, 0 // set frame pointer
+ .cfi_def_cfa_register rbp //
lea rsp, [rsp - 8] // ensure proper alignment of the rsp
END_PROLOGUE
@@ -53,22 +57,22 @@ NESTED_ENTRY CallDescrWorkerInternal, _TEXT, CallDescrWorkerUnwindFrameChainHand
mov ecx, dword ptr [rbx + CallDescrData__numStackSlots]
and ecx, ecx
- jz NoStackArguments
+ jz .LNoStackArguments
test ecx, 1
- jz StackAligned
+ jz .LStackAligned
push rax
-StackAligned:
+.LStackAligned:
mov rsi, [rbx + CallDescrData__pSrc] // set source argument list address
lea rsi, [rsi + 8 * rcx]
-StackCopyLoop: // copy the arguments to stack top-down to carefully probe for sufficient stack space
+.LStackCopyLoop: // copy the arguments to stack top-down to carefully probe for sufficient stack space
sub rsi, 8
push qword ptr [rsi]
dec ecx
- jnz StackCopyLoop
-NoStackArguments:
+ jnz .LStackCopyLoop
+.LNoStackArguments:
// All argument registers are loaded regardless of the actual number
// of arguments.
@@ -85,7 +89,7 @@ NoStackArguments:
mov rax, [rbx + CallDescrData__pFloatArgumentRegisters]
and rax, rax
- jz NoFloatArguments
+ jz .LNoFloatArguments
movsd xmm0, [rax + 0]
movsd xmm1, [rax + 16]
movsd xmm2, [rax + 32]
@@ -94,38 +98,41 @@ NoStackArguments:
movsd xmm5, [rax + 80]
movsd xmm6, [rax + 96]
movsd xmm7, [rax + 112]
-NoFloatArguments:
+.LNoFloatArguments:
call qword ptr [rbx + CallDescrData__pTarget] // call target function
// Save FP return value
mov ecx, dword ptr [rbx + CallDescrData__fpReturnSize]
test ecx, ecx
- jz ReturnsInt
+ jz .LReturnsInt
cmp ecx, 4
- je ReturnsFloat
+ je .LReturnsFloat
cmp ecx, 8
- je ReturnsDouble
+ je .LReturnsDouble
// unexpected
- jmp Epilog
+ jmp .LEpilog
-ReturnsInt:
+.LReturnsInt:
mov [rbx+CallDescrData__returnValue], rax
-Epilog:
+.LEpilog:
lea rsp, 0[rbp] // deallocate argument list
+ .cfi_def_cfa_register rsp
pop rbp // restore nonvolatile register
+ .cfi_adjust_cfa_offset -8 //
pop rbx //
+ .cfi_adjust_cfa_offset -8 //
ret
-ReturnsFloat:
+.LReturnsFloat:
movss real4 ptr [rbx+CallDescrData__returnValue], xmm0
- jmp Epilog
+ jmp .LEpilog
-ReturnsDouble:
+.LReturnsDouble:
movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0
- jmp Epilog
+ jmp .LEpilog
NESTED_END CallDescrWorkerInternal, _TEXT
diff --git a/src/vm/amd64/excepamd64.cpp b/src/vm/amd64/excepamd64.cpp
index b69645dbbf..e8042d8172 100644
--- a/src/vm/amd64/excepamd64.cpp
+++ b/src/vm/amd64/excepamd64.cpp
@@ -170,8 +170,6 @@ RtlVirtualUnwind (
// The indirection should be taken care of by the caller
_ASSERTE((FunctionEntry->UnwindData & RUNTIME_FUNCTION_INDIRECT) == 0);
-#ifndef FEATURE_PAL
-
#ifdef DEBUGGING_SUPPORTED
if (CORDebuggerAttached())
{
@@ -182,14 +180,8 @@ RtlVirtualUnwind (
{
return RtlVirtualUnwind_Unsafe(HandlerType, ImageBase, ControlPc, FunctionEntry, ContextRecord, HandlerData, EstablisherFrame, ContextPointers);
}
-
-#else // !FEATURE_PAL
- PORTABILITY_ASSERT("UNIXTODO: Implement unwinding for PAL");
- return NULL;
-#endif // !FEATURE_PAL
}
-#ifndef FEATURE_PAL
#ifdef DEBUGGING_SUPPORTED
PEXCEPTION_ROUTINE
RtlVirtualUnwind_Worker (
@@ -561,7 +553,6 @@ NORMAL_UNWIND:
return RtlVirtualUnwind_Unsafe(HandlerType, ImageBase, ControlPc, FunctionEntry, ContextRecord, HandlerData, EstablisherFrame, ContextPointers);
}
#endif // DEBUGGING_SUPPORTED
-#endif // !FEATURE_PAL
#undef FAKE_PROLOG_SIZE
#undef FAKE_FUNCTION_CODE_SIZE
diff --git a/src/vm/amd64/gmsamd64.cpp b/src/vm/amd64/gmsamd64.cpp
index 8f59388410..6b0fd3aa9c 100644
--- a/src/vm/amd64/gmsamd64.cpp
+++ b/src/vm/amd64/gmsamd64.cpp
@@ -30,8 +30,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
ctx.Rip = baseState->m_CaptureRip;
ctx.Rsp = baseState->m_CaptureRsp + 8; // +8 for return addr pushed before calling LazyMachStateCaptureState
+#ifndef UNIX_AMD64_ABI
ctx.Rdi = unwoundState->m_CaptureRdi = baseState->m_CaptureRdi;
ctx.Rsi = unwoundState->m_CaptureRsi = baseState->m_CaptureRsi;
+#endif
ctx.Rbx = unwoundState->m_CaptureRbx = baseState->m_CaptureRbx;
ctx.Rbp = unwoundState->m_CaptureRbp = baseState->m_CaptureRbp;
ctx.R12 = unwoundState->m_CaptureR12 = baseState->m_CaptureR12;
@@ -42,8 +44,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
#if !defined(DACCESS_COMPILE)
// For DAC, if we get here, it means that the LazyMachState is uninitialized and we have to unwind it.
// The API we use to unwind in DAC is StackWalk64(), which does not support the context pointers.
+#ifndef UNIX_AMD64_ABI
nonVolRegPtrs.Rdi = &unwoundState->m_CaptureRdi;
nonVolRegPtrs.Rsi = &unwoundState->m_CaptureRsi;
+#endif
nonVolRegPtrs.Rbx = &unwoundState->m_CaptureRbx;
nonVolRegPtrs.Rbp = &unwoundState->m_CaptureRbp;
nonVolRegPtrs.R12 = &unwoundState->m_CaptureR12;
@@ -58,7 +62,13 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
do
{
+
+#ifndef FEATURE_PAL
pvControlPc = Thread::VirtualUnwindCallFrame(&ctx, &nonVolRegPtrs);
+#else // !FEATURE_PAL
+ VirtualUnwind(&ctx, &nonVolRegPtrs);
+ pvControlPc = GetIP(&ctx);
+#endif // !FEATURE_PAL
if (funCallDepth > 0)
{
@@ -105,8 +115,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
#if defined(DACCESS_COMPILE)
// For DAC, we have to update the registers directly, since we don't have context pointers.
+#ifndef UNIX_AMD64_ABI
unwoundState->m_CaptureRdi = ctx.Rdi;
unwoundState->m_CaptureRsi = ctx.Rsi;
+#endif
unwoundState->m_CaptureRbx = ctx.Rbx;
unwoundState->m_CaptureRbp = ctx.Rbp;
unwoundState->m_CaptureR12 = ctx.R12;
@@ -115,8 +127,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
unwoundState->m_CaptureR15 = ctx.R15;
#else // !DACCESS_COMPILE
+#ifndef UNIX_AMD64_ABI
unwoundState->m_pRdi = PTR_ULONG64(nonVolRegPtrs.Rdi);
unwoundState->m_pRsi = PTR_ULONG64(nonVolRegPtrs.Rsi);
+#endif
unwoundState->m_pRbx = PTR_ULONG64(nonVolRegPtrs.Rbx);
unwoundState->m_pRbp = PTR_ULONG64(nonVolRegPtrs.Rbp);
unwoundState->m_pR12 = PTR_ULONG64(nonVolRegPtrs.R12);
diff --git a/src/vm/amd64/unixasmhelpers.S b/src/vm/amd64/unixasmhelpers.S
index b5c0ba6787..873db7ad1e 100644
--- a/src/vm/amd64/unixasmhelpers.S
+++ b/src/vm/amd64/unixasmhelpers.S
@@ -139,8 +139,8 @@ NESTED_END NDirectImportThunk, _TEXT
// MOVDQA is not an atomic operation. You need to call this function in a crst.
// </NOTE>
LEAF_ENTRY moveOWord, _TEXT
- movdqa xmm0, [rdi]
- movdqa [rsi], xmm0
+ movdqu xmm0, [rdi]
+ movdqu [rsi], xmm0
ret
LEAF_END moveOWord, _TEXT
diff --git a/src/vm/amd64/unixasmmacros.inc b/src/vm/amd64/unixasmmacros.inc
index 3b8ad52ea0..0c6e1f0991 100644
--- a/src/vm/amd64/unixasmmacros.inc
+++ b/src/vm/amd64/unixasmmacros.inc
@@ -47,6 +47,7 @@ C_FUNC(\Name):
.text
#else
.type \Name, %function
+ .cfi_startproc
#endif
C_FUNC(\Name):
.endm
@@ -55,6 +56,7 @@ C_FUNC(\Name):
C_FUNC(\Name\()_End):
.global C_FUNC(\Name\()_End)
#if !defined(__APPLE__)
+ .cfi_endproc
.size \Name, .-\Name
#endif
.endm
@@ -74,6 +76,9 @@ C_FUNC(\Name\()_End):
.macro NESTED_ENTRY Name, Section, Handler
LEAF_ENTRY \Name, \Section
+ .ifnc \Handler, NoHandler
+ .cfi_personality 0, \Handler // 4 == DW_EH_PE_udata8 0 == DW_EH_PE_absptr
+ .endif
.endm
.macro NESTED_END Name, Section
@@ -298,4 +303,3 @@ C_FUNC(\Name\()_End):
POP_CALLEE_SAVED_REGISTERS
.endm
-