From: Jan Vorlicek Date: Mon, 3 Jun 2024 21:38:11 +0000 (+0200) Subject: Add support for new exception trace storage format (#4635) X-Git-Tag: accepted/tizen/unified/20241231.014852~40^2~34 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=05f88f687a02aa865384beda97a8910d4d57b17b;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Add support for new exception trace storage format (#4635) To eliminate global spinlock in stack trace saving to exceptions, the format of the stack trace storage has changed. The `_stackTrace` array can now be either a `byte[]` with the actual stack trace as before or an `object[]` where the first element references the byte[] with the actual stack trace and the following elements contain references to `System.Resolver` or `System.Reflection.LoaderAllocator` instances that keep code of methods that can be collected alive. This change modifies SOS to handle the `object[]` case properly, while staying compatible with the old way. Since the same code to get the stack trace was duplicated at two places, I have taken this opportunity to refactor it into a separate function. --- diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 136a78c01..4dbb74da9 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -2607,6 +2607,46 @@ void SosExtOutLargeString(__inout_z __inout_ecount_opt(len) WCHAR * pwszLargeStr ExtOut("%S", pwsz); } +DWORD_PTR GetFirstArrayElementPointer(TADDR taArray) +{ +#ifdef _TARGET_WIN64_ + return taArray + sizeof(DWORD_PTR) + sizeof(DWORD) + sizeof(DWORD); +#else + return taArray + sizeof(DWORD_PTR) + sizeof(DWORD); +#endif // _TARGET_WIN64_ +} + +TADDR GetStackTraceArray(CLRDATA_ADDRESS taExceptionObj, DacpObjectData *pExceptionObjData, DacpExceptionObjectData *pExcData) +{ + TADDR taStackTrace = 0; + if (pExcData) + { + taStackTrace = TO_TADDR(pExcData->StackTrace); + } + else + { + int iOffset = GetObjFieldOffset (taExceptionObj, pExceptionObjData->MethodTable, W("_stackTrace")); + if (iOffset > 0) + { + MOVE(taStackTrace, taExceptionObj + iOffset); + } + } + + if (taStackTrace) + { + // If the stack trace is object[], the stack trace array is actually referenced by its first element + sos::Object objStackTrace(taStackTrace); + TADDR stackTraceComponentMT = objStackTrace.GetComponentMT(); + if (stackTraceComponentMT == g_special_usefulGlobals.ObjectMethodTable) + { + DWORD_PTR arrayDataPtr = GetFirstArrayElementPointer(taStackTrace); + MOVE(taStackTrace, arrayDataPtr); + } + } + + return taStackTrace; +} + HRESULT FormatException(CLRDATA_ADDRESS taObj, BOOL bLineNumbers = FALSE) { HRESULT Status = S_OK; @@ -2718,19 +2758,7 @@ HRESULT FormatException(CLRDATA_ADDRESS taObj, BOOL bLineNumbers = FALSE) : IsAsyncException(taObj, objData.MethodTable); { - TADDR taStackTrace = 0; - if (bGotExcData) - { - taStackTrace = TO_TADDR(excData.StackTrace); - } - else - { - int iOffset = GetObjFieldOffset (taObj, objData.MethodTable, W("_stackTrace")); - if (iOffset > 0) - { - MOVE(taStackTrace, taObj + iOffset); - } - } + TADDR taStackTrace = GetStackTraceArray(taObj, &objData, bGotExcData ? &excData : NULL); ExtOut("StackTrace (generated):\n"); if (taStackTrace) @@ -2740,13 +2768,7 @@ HRESULT FormatException(CLRDATA_ADDRESS taObj, BOOL bLineNumbers = FALSE) if (arrayLen != 0 && hr == S_OK) { - // This code is accessing the StackTraceInfo class in the runtime. - // See: https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/clrex.h -#ifdef _TARGET_WIN64_ - DWORD_PTR dataPtr = taStackTrace + sizeof(DWORD_PTR) + sizeof(DWORD) + sizeof(DWORD); -#else - DWORD_PTR dataPtr = taStackTrace + sizeof(DWORD_PTR) + sizeof(DWORD); -#endif // _TARGET_WIN64_ + DWORD_PTR dataPtr = GetFirstArrayElementPointer(taStackTrace); size_t stackTraceSize = 0; MOVE (stackTraceSize, dataPtr); @@ -12508,16 +12530,7 @@ HRESULT AppendExceptionInfo(CLRDATA_ADDRESS cdaObj, BOOL bAsync = bGotExcData ? IsAsyncException(excData) : IsAsyncException(cdaObj, objData.MethodTable); - DWORD_PTR arrayPtr; - if (bGotExcData) - { - arrayPtr = TO_TADDR(excData.StackTrace); - } - else - { - iOffset = GetObjFieldOffset (cdaObj, objData.MethodTable, W("_stackTrace")); - MOVE (arrayPtr, TO_TADDR(cdaObj) + iOffset); - } + DWORD_PTR arrayPtr = GetStackTraceArray(cdaObj, &objData, bGotExcData ? &excData : NULL); if (arrayPtr) { @@ -12526,13 +12539,7 @@ HRESULT AppendExceptionInfo(CLRDATA_ADDRESS cdaObj, if (arrayLen) { - // This code is accessing the StackTraceInfo class in the runtime. - // See: https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/clrex.h -#ifdef _TARGET_WIN64_ - DWORD_PTR dataPtr = arrayPtr + sizeof(DWORD_PTR) + sizeof(DWORD) + sizeof(DWORD); -#else - DWORD_PTR dataPtr = arrayPtr + sizeof(DWORD_PTR) + sizeof(DWORD); -#endif // _TARGET_WIN64_ + DWORD_PTR dataPtr = GetFirstArrayElementPointer(arrayPtr); size_t stackTraceSize = 0; MOVE (stackTraceSize, dataPtr); // data length is stored at the beginning of the array in this case