Age | Commit message (Collapse) | Author | Files | Lines |
|
This bug fix is a port from the equivalent fix in framework. The
debugger tried performing a stackwalk in the epilog due to the JIT
incorrectly reporting epilogue information. This caused an invalid
GS cookie to be checked and caused the debugger to crash. A flag was
added to allow debug stackwalks to skip the cookie check.
|
|
* Fix ARM/ARM64 hijacking in tail calls
This change fixes an issue that can happen when a function that has tail
calls is hijacked. There are two potential issues:
1. When a function that tail calls another one is hijacked, the LR may be
stored at a different location in the stack frame of the tail call
target.
So just by performing tail call, the hijacked location becomes invalid and
unhijacking would corrupt stack by writing to that location.
2. There is a small window after the caller pops LR from the stack in its
epilog and before the tail called function pushes LR in its prolog when
the hijacked return address would not be not on the stack and so we would
not be able to unhijack.
The fix is to prevent hijacking of functions that contain tail calls.
* Enable the tailcall hijacking test for ARM64
The test JIT/Methodical/tailcall_v4/hijacking should be passing now on
ARM64.
|
|
|
|
condition) (#11253)
* Use relevant define instead of explicit _TARGET_XXX_
m_pvResumableFrameTargetSP-related implementations in the stack walker
are explicitly ifdefed by _TARGET_XXX_.
This commit introduces relevant define (RECORD_RESUMABLE_FRAME_SP) and
uses it to ifdef relevant implementations.
This commit does not introduce any behavior changes.
* Update ifdef condition
|
|
* [x86/Linux] Funclet-based synchronization
* Fix x86/Windows build error
* Revise per feedback
* Fix format error
|
|
Fixes #8683
|
|
The extra Unix specific piece of code in the StackFrameIterator::Filter that
handles the difference in the exception stack unwinding on Unix was not
skipping exception trackers belonging to filter clauses. But that was not
right, since filter funclet stack frames behave the same way on Windows and
Unix. They can be present on the stack when we reach their parent frame if
the filter hasn't finished running yet or they can be gone if the filter
completed running, either succesfully or with unhandled exception.
This change adds skipping of filter funclet related exception trackers at
that place so that the common code processes them.
This fixes the GC hole mentioned in the title that was discovered when
running some tests with GCStress mode 2.
|
|
|
|
|
|
|
|
* [x86/Linux] Do NOT use QuickUnwindStackFrame
* Fix x64 build error
|
|
This commit revises stack walker to process explicit frames before
managed frame as in other architectures that use Win64 EH model.
This commit fixes #9260.
|
|
|
|
* [x86/Linux] (Partially) port RtlVirtualUnwind
* Rewrite x86 Unwinder using UnwindStackFrame
* Extract UnwindStackFrame from EECodeManager
* Port 'InlinedCallFrame::UpdateRegDisplay'
|
|
* Move GetUnwindInfo and GetNumberOfUnwindInfos into the real code header
This commit fixes #8342.
* Use WIN64EXCEPTIONS instead of _TARGET_X86_
* Revise FaultingExceptionFrame
This commit revises FaultingExceptionFrame to support WIN64EXCEPTIONS in
x86/Linux port.
* Add RUNTIME_FUNCTION__EndAddress as NYI
* Revise regdisp.h
* Revise eetwain.h
* Comment out exinfo.cpp if WIN64EXCEPTIONS is defined
* Revises excep.cpp
* Fix mistmatch in ThrowControlForThread defintion
* Revises cgenx86.cpp
* Disable SEH-based exception handlers when WIN64EXCEPTIONS is defined
* Revise stackwalk.cpp
* Revise jitinterface.cpp
* Revise readytorun.h
* Revise dbgipcevents.h
* Revise zapcode.cpp
* Revise clrnt.h
* Fix Windows build error
* Mark FaultingExceptionFrame::UpdateRegDisplay as NYI
* Revise per feedback
* Revert #if defined(..) as #ifdef
* Fix style changes
* Fix style changes
* Remove #undef _TARGET_X86_
* 2nd attempt to fix Windows build error
* Revise per feedback
* Revert the chagnes in clrdefinitions.cmake and add BIT32 in CMakeLists.txt
* Use !BIT64 instead of BIT32
* Include exceptionhandling.cpp and gcinfodecoder.cpp in build
This commit includes exceptionhandling.cpp and gcinfodecoder.cpp in
build, and fixes related compile errors.
* Fix COMPlus_EndCatch undefined reference
* Fix build error
* Fix GcInfoDecoder-related undefined references
* Fix AdjustContextForVirtualStub undefined reference
* Fix GetCallerSP undefined reference
* Fix ResetThreadAbortState undefined reference
* Attempt to fix Windows build error
* Fix CLRNoCatchHandler undefined reference
* Another attemp to fix Windows build error
* Fix GetXXXFromRedirectedStubStackFrame undefined references
* Fix Windows Build Error
* Add RtlpGetFunctionEndAddress and RtlVirtualUnwind as NYI
* Fix undefined references on JIT helpers
* Enable Dummy Application Run with WIN64EXCEPTIONS
* Revert "Move GetUnwindInfo and GetNumberOfUnwindInfos into the real code header"
This reverts commit c2bad85ac1136be3c6fb6ad7eedc5b3814b2ab29.
* Use indirect code header when WIN64EXCEPTIONS is enabled
* Port 'SyncRegDisplayToCurrentContext' and 'FillRegDisplay'
* Revise style 'RUNTIME_FUNCTION__SetUnwindInfoAddress'
* Extract out HandlerData from #ifdef region
* Add UNIXTODO
* Add UNIXTODO
* Port 'GetRegdisplayReturnValue'
* Fix incorrect comment
* Remove messages that mentions WIN32EXCEPTIONS
* Revise AdjustContextForWriteBarrier
* Port 'FaultingExceptionFrame::UpdateRegDisplay'
* Extract out 'AdjustContextForVirtualStub' and 'CLRNoCatchHandler' from #ifdef region
* Merge two #ifdef regions
* Set WIN64EXCEPTIONS as a default for x86/Linux
* Remove unnecessary #ifdef from ThrowControlForThread
* Remove unnecessary stubs
* Add Dependency Check between Compile Flags
* Revise per feedback
|
|
Add UMThunkStub method with logic from that of AMD64
|
|
This change enables build of CoreCLR on Alpine Linux. Here is the list
of changes:
- Disable asserts checking RSP in arbitrary threads against cached stack limit
for the respective thread. The stack on Alpine obviously grows over the limit
reported by the pthread functions.
- Disable using XSTATE. This should be re-enabled after MUSL gets the _xstate,
_fpx_sw_bytes and related data structures added to the signal.h header.
- Disable setting rlimit of RLIMIT_NOFILE to the max value, since it breaks
debugging for some reason.
- Add skipping over the hardware signal trampoline in the PAL_VirtualUnwind.
While we were not trying to walk over it in a simple case, in a case where
an exception was thrown from a catch handler of a hardware exception, we
still attempted to walk over it and it fails on Alpine.
- Fix detection of Alpine Linux in the PAL's CMakeLists.txt so that it works
in Docker containers too.
- Modified PAL_VirtualUnwind to make the check for unwinding past the bottom
of the stack unconditional. We had a long list of platforms where we were
doing this check and it doesn't hurt to do it on platforms where it is not
needed. I have done that rather than adding a check for Alpine Linux as
another platform that needs it.
|
|
This commit includes the following changes:
1) Thread GcInfo version through X86 specific APIs
2) Add ReturnKind and ReversePinvokeOffset fields to InfoHdr structure
GcInfo v1 and v2 use the same InfoHdr structures, because:
InfoHdrSmall: ReturnKind is encoded within previously unused bits.
InfoHdr: revPInvokeOffset will never be written to the image,
since ReversePinvokeOffset==INVALID_REV_PINVOKE_OFFSET for V1.
3) Update the Pre-computed header table to include bits for the above
[The default setting of ReturnKind=RT_Scalar is used for all entries in the table.
Optimizing this table based in most frequent usage scenarios is to be done separately]
4) Change the GC encoder/decoder to handle the above two fields
5) Use the ReturnKind in the GCInfo from thread-suspension code.
GcInfo version is changed for CoreCLR X86 only, not for Desktop JIT
Fixes #4379
|
|
|
|
The filter funclets are not handled correctly during stack walk on Unix. When
the funclet's parent frame is reached, the filter funclet was mistakenly handled
as a non-filter funclet by the Unix specific code that is used to figure out
parent frames of funclets from exception trackers.
The fix is to skip this Unix specific code when we are looking for a parent of
a filter funclet. Filter funclet frame is always on the stack when the stack
walk reaches its parent frame.
|
|
This mainly involved DACizing the VM code.
A bulk edit for changing RUNTIME_FUNCTION to T_RUNTIME_FUNCTION
[tfs-changeset: 1591667]
|
|
Fix stack walking on Unix in case of finally
|
|
The issue is that the code in the StackFrameIterator::Filter that handles cases
when a funclet frame that was already removed from the stack due to native frames
unwinding works for catch funclets only and not for finally ones.
The ExceptionTracker::GetCallerOfActualHandlingFrame is set for catch funclets
only. To make it work for the finally funclets as well, we need to use information
from the ExceptionTracker::m_EnclosingClauseInfoForGCReporting instead.
There was also another problem in the Filter method that caused the function to
spin in an infinite loop when a parent of a funclet was also a funclet. In
such case, the code in the method rechecks the current frame but the special
functionality to check the exception trackers data needs to be skipped for
the recheck.
And finally, when we find that the current frame was a parent of an unwound
funclet from the evidence in the exception trackers, we also need to set
the fSkippingFunclet.
|
|
When unhandled exception happens in a finalizer thread and there are
no managed frames till the bottom of the stack,
the Thread::VirtualUnwindToFirstManagedCallFrame then fails fast.
The fix is to make the Thread::VirtualUnwindToFirstManagedCallFrame to
return even in case no managed frame is called, which is indicated by
its returning 0 as the resulting IP address. The DispatchManagedException
then checks that and rethrows the exception instead of trying to call
UnwindManagedExceptionPass1.
I have also added INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP to the
FinalizerThread::FinalizerThreadStart so that the unhandled exception
doesn't escape the stack.
And I also needed to modify the UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP
to detect case when the unhandled exception filter was already executed so
that it doesn't double-report the unhandled exception.
|
|
This change fixes the stack walker on Unix to properly account for the cases
when funclet frames were reclaimed due to native frames unwinding and so
they are not on the stack anymore. The stack walker needs to know that to
properly skip reporting GC references for the parent frame of the funclet.
While there was already code attempting to do that, it was incorrectly
skipping some exception trackers and not skipping the current tracker
in case the catch handler was not called yet.
This problem was discovered while running stress tests with GCStress 3.
|
|
This change fixes a problem with reporting object on stack for GC when
GC scan is performed right after a funclet is unwound during exception handling.
In such case, the parent of the funclet should report live object references,
but it was not doing so on Unix.
On Unix, the unwound funclet is detected in a different way than on Windows due
to the fact that the stack frames of the funclet are already reclaimed, while on
Windows, they are still there.
When we detect the unwound funclet on Unix, we set state of the stack walker so
that it behaves in the same way as on Windows. But we were missing one state
variable that makes the parent report the references instead of the funclet,
the m_fDidFuncletReportGCReferences.
|
|
Fix an assert failure in GCStress testing
|
|
When GCStress uses redirection, it pushes a
RedirectedThreadFrame (Windows) or
ResumableFrame(Unix) on the stack.
The stack walker, when checking for consistency of frame chain
makes a special case for this redirection when running under
GCStress -- but compares only against `RedirectedThreadFrame'.
This caused the StackWalker to think that certain invoke-s were
not redirected, resulting in the failures in some GCStress tests
on Linux.
This change fixes the problem.
Fixes #2848
|
|
|
|
This change fixes a corner case of GC stack walking during exception handling
that I have missed in my previous fix. When GC suspends a thread while it is
performing second pass of exception handling, in some cases the previous
exception tracker is already collapsed into the current one and so the
evidence on a frame being a parent of an already executed handler funclet
cannot be extracted from previous trackers and stack walker tries to pass
an outdated reference to GC.
Fortunatelly, the information about the parent from the collapsed tracker
is stored in the tracker into which the collapsed one was merged and
so we can test it using that.
|
|
This change fixes two issues that happens in some cases when GC scans stack of
a thread that is handling exception at that moment.
First issue was caused by the fact that the stack walker wasn't modified to
take into account the difference in exception handling on Unix. When an exception
is thrown from a catch handler or finally block (a funclet )on Unix, part of the stack
is unwound immediatelly, while on Windows, the stack is not reclaimed until
the exception is fully handled.
The problem was caused by the fact that when GC happens in the funclet before the exception
is processed, but after a point where GC knows that the lifetime of locals in the caller frame
is over, it doesn't update the references in the caller frame for objects that it has relocated.
On Windows, this is detected just from walking the stack, since the funclet frame is still there
and the stack walker can then skip scanning the parent frame GC references.
On Linux, the funclet is not on stack anymore, so this case was not detected and GC attempted to
scan the stale references and crashed.
The fix was to detect that a frame was a caller to a funclet from the chain of previous exception
trackers that is fortunately preserved and the trackers hold the necessary information.
The second issue was more subtle. During interleaved exception handling, when we unwind a native
portion of the stack and switch back to unwinding a managed block of stack frames, we re-create
the exception tracker and carry over just a few members necessary to continue processing the
same exception. The way it was done was that we have first removed the current tracker from
the list of trackers of the current thread, then we have destroyed it, created a new one and
put it back to the front of the list.
The issue happened when GC started walking the stack of the thread in the small time slot when
the current tracker was removed from the list, but the re-created tracker was not added there yet.
Then the detection necessary for handling the previous issue didn't work and we got a crash.
The fix was to make the whole re-creation of the exception tracker atomic w.r.t. the GC.
|
|
[tfs-changeset: 1466545]
|
|
This change fixes the following warnings:
1) Assignment in a condition should be wrapped in ()
2) Priority of && / || should be indicated by parentheses.
3) Unknown #pragma optimize ifdefed out for non MSVC
4) Unused functions deleted or put under #ifdef
5) Extra tokens warning disabling moved to the CMakeLists.txt in the src/inc
6) Self assignment of a member or local variable
7) Assigning ~0 to a bitfield member that was just 8 bit wide
It also fixes a bug in the STRESS_LOGxx macro invocation in exceptionhandling.cpp and
stackwalk.cpp related to recent adding the DBG_ADDR macro usage. This macro expanded
a single parameter into two expressions to extract high / low 32 bits separately.
But the STRESS_LOGxx parameters are passed to the StressLog::LogMsg method as follows:
(void*)(size_t)(data1)
That means that the expanded pair x, y would be inserted as data 1 and that leads
to ignoring the x due to the comma operator.
|
|
[tfs-changeset: 1434167]
|
|
This change adds printing of unhandled managed exception stack trace to
console before exiting.
|
|
This change fixes issue with exception unwinding in the case when the unwinding
passed through a frame of the CallDescrWorkerInternal function. This function
had personality routine on it, but a windows style personality routine was specified.
The windows one has a completely different signature, so the code was crashing.
When looking into that, I've found that even if I have implemented a proper
Unix style personality routine, it cannot work the same way on Linux as it
used to work on Windows.
This personality routine's goal is to pop Frames from the Frame list in the current
thread so that all frames upto the frame handling the exception are popped.
There are two problems on Linux. First, unlike on Windows, the personality
routine is not passed the RSP of the frame handling the exception in an official
way. Although it can be extracted from the private_2 member of the exception
object during the 2nd pass, it is an implementation detail that we cannot rely on.
Moreover, even if we used that, it would still not be the right frame in all cases
due to the fact that we implement exception filters by catching and rethrowing and
so the frame we would get would be the frame of a filtering catch in case
there was one.
My solution to this problem is to add destructor to the Frame type and let it
pop the frame being destroyed if it is still in the list in the current thread.
That way the native code unwinding automatically takes care of popping the frames.
As an additional changes, I've added handling of the case when the
Thread::VirtualUnwindToFirstManagedCallFrame walks out of stack, fixed a stack
alignment issue in the recently added StartUnwindingNativeFrames function and
a cosmetic change in the UnwindManagedExceptionPass1.
|
|
This change adds support for unwinding exceptions that cross native frames.
These are for example exceptions thrown / rethrown from catch blocks.
The exceptions are unwound in an interleaved manner in this case. First,
all managed frames upto the first native frame are unwound (both the first
and second pass), then the native frames are unwound by standard c++ exception
handling, then the next block of managed frames is unwound etc.
The change also implements RtlCaptureContext and changes the managed exception
handling to use it instead of the GetThreadContext. The difference is that the
RtlCaptureContext gets context of the caller while the GetThreadContext gets
a context somewhere deep in the PAL and so unwinding from such a context to the
first managed frame would be walking old stack frames that can already be corrupted.
As an additional change, I have fixed a problem that prevented unwinding of
assembler functions that use the PROLOG_WITH_TRANSITION_BLOCK macro.
The macro was using CFI annotation for the xmm registers and the libunwind
doesn't support that.
Moreover, the PAL_VirtualUnwind return status was not being checked in the
`Thread::VirtualUnwindToFirstManagedCallFrame`, so the failure resulted in an
infinite loop in there.
Finally, the `debug/di/amd64/floatconversion.S` was including the unixasmmacros.inc
using a relative path, now after I've moved it to a different place, I've removed
the relative path since the new path is in the include paths.
|
|
Implementation of the managed exception handling in this change is by far not yet complete but it is a good starting point that we can build on top of it. Basically this code allows managed exceptions to be thrown and caught. The finally blocks and nested try/catch works too. But re-throwing an exception from a catch block and many other corner cases do not work yet.
In addition, RtlRestoreContext needs to be properly implemented. This change introduces a very simply implementation that works only in those cases where XMM registers are not used in the code that handles the exception so they don’t need to be restored. I have created a separate issue to track it (https://github.com/dotnet/coreclr/issues/360).
This change also fixes an issue in JIT where JIT was incorrectly passing arguments in the RCX and RDX registers to the finally and catch funclets.
|
|
Rename VirtualUnwind in PAL to PAL_VirtualUnwind
Move .cfi annotation inside macros and update PROLOG_WITH_TRANSITION_BLOCK
to use these macros. I've verified that the annotation is correct by
stepping through the asm code and verifying that the stack trace is
correct at every instruction.
|
|
Conflicts:
src/pal/src/config.h.linux
src/pal/src/config.h.osx
src/pal/src/exception/seh-unwind.cpp
|
|
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
|
|
[tfs-changeset: 1415626]
|
|
|
|
Simplify platform ifdefs like #if defined(_WIN64) || defined(_TARGET_ARM_) to #if !defined(_TARGET_X86_) based on @BruceForstall suggestion
|
|
Our native files were more or less encoded in Windows-1252, which
causes problems when we try to compile them on machines where the
current codepage can't represent everything that Windows-1252
can. With this conversion I just moved characters to their ASCII
counterparts (e.g. no smart quotes, the section marker glyph is now
"Section"). There were two places where I couldn't do the straight
forward thing, in object.h we wanted to insert the Per Mille symbol in
a comment so instead I just spelled out the Unicode codepoint. In
morph.cpp, there was a comment pointing to a paper by Torbjörn
Granlund (note the diaeresis above the second o). In this case,
unfortuntely I had to just drop the diaeresis. However, searching for
"Torbjorn Granlund" will lead you to the right person.
Fixes #49
|
|
[tfs-changeset: 1407945]
|