diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index 30df0681e3..b9af4d0f80 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -4649,6 +4649,88 @@ GetClrMethodInstance( return (Status == S_OK || FAILED(Status)) ? Status : E_NOINTERFACE; } +// +// Searches the IL address map for the entry containing the given native offset. +// Fallback for older runtimes where GetILOffsetsByAddress is buggy or unsupported. +HRESULT +GetILOffsetFromAddressMap( + ___in IXCLRDataMethodInstance* Method, + ___in ULONG64 nativeOffset, + ___out PULONG32 MethodOffs) +{ + HRESULT Status; + CLRDATA_IL_ADDRESS_MAP MapLocal[16]; + CLRDATA_IL_ADDRESS_MAP* Map = MapLocal; + ULONG32 MapCount = ARRAY_SIZE(MapLocal); + ULONG32 MapNeeded; + + for (;;) + { + if ((Status = Method->GetILAddressMap(MapCount, &MapNeeded, Map)) != S_OK) + { + if (Map != MapLocal) + { + delete[] Map; + } + return Status; + } + + if (MapNeeded <= MapCount) + { + break; + } + + // Need more map entries. + if (Map != MapLocal) + { + delete[] Map; + return E_UNEXPECTED; + } + + Map = new CLRDATA_IL_ADDRESS_MAP[MapNeeded]; + if (!Map) + { + return E_OUTOFMEMORY; + } + + MapCount = MapNeeded; + } + + // Search for the entry whose native address range contains nativeOffset. + // The last map entry sometimes has a bogus endAddress (e.g., wrapping back to + // the method start). Handle this by treating any entry where endAddress <= + // startAddress as extending to infinity (the end of the method code). + Status = E_FAIL; + for (size_t i = 0; i < MapNeeded; i++) + { + bool inRange; + if (Map[i].endAddress > Map[i].startAddress) + { + // Normal range. + inRange = (Map[i].startAddress <= nativeOffset && nativeOffset < Map[i].endAddress); + } + else + { + // Malformed/last entry: endAddress <= startAddress. Treat as open-ended. + inRange = (Map[i].startAddress <= nativeOffset); + } + + if (inRange) + { + *MethodOffs = Map[i].ilOffset; + Status = S_OK; + break; + } + } + + if (Map != MapLocal) + { + delete[] Map; + } + + return Status; +} + // // Enumerates over the IL address map associated with the passed in // managed method, and returns the highest non-epilog offset. @@ -4749,33 +4831,39 @@ ConvertNativeToIlOffset( } } - if ((Status = pMethodInst->GetILOffsetsByAddress(nativeOffset, 1, NULL, methodOffs)) != S_OK) + // Try the IL address map first. On older runtimes (pre-.NET 5.0), GetILOffsetsByAddress + // has a bug where it returns incorrect IL offsets. GetILAddressMap returns the raw mapping + // table which we can search correctly ourselves. + Status = GetILOffsetFromAddressMap(pMethodInst, nativeOffset, methodOffs); + if (Status != S_OK) { - ExtDbgOut("ConvertNativeToIlOffset(%p): GetILOffsetsByAddress FAILED %08x\n", nativeOffset, Status); - *methodOffs = 0; + // Fallback to GetILOffsetsByAddress if the map is unavailable. + if ((Status = pMethodInst->GetILOffsetsByAddress(nativeOffset, 1, NULL, methodOffs)) != S_OK) + { + ExtDbgOut("ConvertNativeToIlOffset(%p): GetILOffsetsByAddress FAILED %08x\n", nativeOffset, Status); + *methodOffs = 0; + } } - else + + switch((LONG)*methodOffs) { - switch((LONG)*methodOffs) - { - case CLRDATA_IL_OFFSET_NO_MAPPING: - return E_NOINTERFACE; + case CLRDATA_IL_OFFSET_NO_MAPPING: + return E_NOINTERFACE; - case CLRDATA_IL_OFFSET_PROLOG: - // Treat all of the prologue as part of - // the first source line. - *methodOffs = 0; - break; + case CLRDATA_IL_OFFSET_PROLOG: + // Treat all of the prologue as part of + // the first source line. + *methodOffs = 0; + break; - case CLRDATA_IL_OFFSET_EPILOG: - // Back up until we find the last real - // IL offset. - if ((Status = GetLastMethodIlOffset(pMethodInst, methodOffs)) != S_OK) - { - return Status; - } - break; + case CLRDATA_IL_OFFSET_EPILOG: + // Back up until we find the last real + // IL offset. + if ((Status = GetLastMethodIlOffset(pMethodInst, methodOffs)) != S_OK) + { + return Status; } + break; } return pMethodInst->GetTokenAndScope(methodToken, ppModule); diff --git a/src/tests/SOS.UnitTests/Scripts/DivZero.script b/src/tests/SOS.UnitTests/Scripts/DivZero.script index 456b10790d..579e590ede 100644 --- a/src/tests/SOS.UnitTests/Scripts/DivZero.script +++ b/src/tests/SOS.UnitTests/Scripts/DivZero.script @@ -37,7 +37,7 @@ VERIFY:\[.*[\\|/]Debuggees[\\|/].*DivZero[\\|/]DivZero\.cs @ 24\s*\]\s* VERIFY:\s+\s+\s+[Dd]iv[Zz]ero.*!C\.F2(\(.*\))?\+0x\s+ VERIFY:\[.*[\\|/]Debuggees[\\|/].*DivZero[\\|/]DivZero\.cs @ 36\s*\]\s* VERIFY:\s+\s+\s+[Dd]iv[Zz]ero.*!C\.Main(\(.*\))?\+0x\s+ -VERIFY:\[.*[\\|/]Debuggees[\\|/].*DivZero[\\|/]DivZero\.cs @ (57|56)\s*\]\s* +VERIFY:\[.*[\\|/]Debuggees[\\|/].*DivZero[\\|/]DivZero\.cs @ 57\s*\]\s* # Verify that Threads (clrthreads) works SOSCOMMAND:clrthreads @@ -57,4 +57,4 @@ VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ VERIFY:\s+\s+\s+(\*\*\* WARNING: Unable to verify checksum for DivZero.exe\s*)?C\.DivideByZero(\(.*\))?\s+\[(?i:.*[\\|/]DivZero\.cs) @ 15\s*\]\s+ VERIFY:\s+\s+\s+C\.F3(\(.*\))?\s+\[(?i:.*[\\|/]DivZero\.cs) @ 24\s*\]\s+ VERIFY:\s+\s+\s+C\.F2(\(.*\))?\s+\[(?i:.*[\\|/]DivZero\.cs) @ 36\s*\]\s+ -VERIFY:\s+\s+\s+C\.Main(\(.*\))?\s+\[(?i:.*[\\|/]DivZero\.cs) @ (57|56)\s*\]\s+ +VERIFY:\s+\s+\s+C\.Main(\(.*\))?\s+\[(?i:.*[\\|/]DivZero\.cs) @ 57\s*\]\s+ diff --git a/src/tests/SOS.UnitTests/Scripts/NestedExceptionTest.script b/src/tests/SOS.UnitTests/Scripts/NestedExceptionTest.script index d44f0d7ca9..cd8130f4b5 100644 --- a/src/tests/SOS.UnitTests/Scripts/NestedExceptionTest.script +++ b/src/tests/SOS.UnitTests/Scripts/NestedExceptionTest.script @@ -93,7 +93,12 @@ VERIFY:InnerException:\s+System\.FormatException, Use !?printexception VERIFY:StackTrace \(generated\): VERIFY:\s+SP\s+IP\s+Function\s+ VERIFY:\s+\s+\s+[Nn]ested[Ee]xception[Tt]est.*!NestedExceptionTest\.Program\.Main(\(.*\))?\+0x\s* +IFDEF:DESKTOP VERIFY:\[.*[\\|/]Debuggees[\\|/].*[Nn]ested[Ee]xception[Tt]est[\\|/][Nn]ested[Ee]xception[Tt]est\.cs @ (11|20)\s*\]\s* +ENDIF:DESKTOP +!IFDEF:DESKTOP +VERIFY:\[.*[\\|/]Debuggees[\\|/].*[Nn]ested[Ee]xception[Tt]est[\\|/][Nn]ested[Ee]xception[Tt]est\.cs @ 20\s*\]\s* +ENDIF:DESKTOP VERIFY:(StackTraceString: \s+)? VERIFY:HResult:\s+80131509\s+ VERIFY:There are nested exceptions on this thread. Run with -nested for details @@ -114,4 +119,9 @@ SOSCOMMAND:ClrStack VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ VERIFY:\s+\s+\s+NestedExceptionTest\.Program\.Main(\(.*\))?\s* +IFDEF:DESKTOP VERIFY:\[.*[\\|/]Debuggees[\\|/].*[Nn]ested[Ee]xception[Tt]est[\\|/][Nn]ested[Ee]xception[Tt]est\.cs @ (11|20)\s*\]\s* +ENDIF:DESKTOP +!IFDEF:DESKTOP +VERIFY:\[.*[\\|/]Debuggees[\\|/].*[Nn]ested[Ee]xception[Tt]est[\\|/][Nn]ested[Ee]xception[Tt]est\.cs @ 20\s*\]\s* +ENDIF:DESKTOP diff --git a/src/tests/SOS.UnitTests/Scripts/OtherCommands.script b/src/tests/SOS.UnitTests/Scripts/OtherCommands.script index 86f950c084..b1a242f404 100644 --- a/src/tests/SOS.UnitTests/Scripts/OtherCommands.script +++ b/src/tests/SOS.UnitTests/Scripts/OtherCommands.script @@ -43,7 +43,7 @@ VERIFY:\s+\s+\s+SymbolTestApp\.Program\.Foo2\(.*\)\s+\[(?i:.*[\\ CONTINUE SOSCOMMAND:ClrStack -VERIFY:\s+\s+\s+SymbolTestApp\.Program\.Foo4\(.*\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ (37|57)\]\s* +VERIFY:\s+\s+\s+SymbolTestApp\.Program\.Foo4\(.*\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 37\]\s* ENDIF:UNIX_SINGLE_FILE_APP ENDIF:ALPINE diff --git a/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script b/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script index bde504aeaa..c784cda141 100644 --- a/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script +++ b/src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.script @@ -67,7 +67,7 @@ SOSCOMMAND:SOSStatus SOSCOMMAND:ClrStack VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ -VERIFY:.*\s+\s+.*\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57)\]\s* +VERIFY:.*\s+\s+.*\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 57\]\s* VERIFY:\s+\s+\s+SymbolTestApp\.Program\.Foo2\(.*\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 32\]\s* VERIFY:\s+\s+\s+SymbolTestApp\.Program\.Foo1\(.*\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 27\]\s* VERIFY:\s+\s+\s+SymbolTestApp\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 22\]\s* @@ -93,7 +93,7 @@ ENDIF:MAJOR_RUNTIME_VERSION_GE_7 SOSCOMMAND:ClrStack -f VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ -VERIFY:\s+\s+\s+SymbolTestApp\.(dll|exe)!SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\+\s+\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57)\]\s* +VERIFY:\s+\s+\s+SymbolTestApp\.(dll|exe)!SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\+\s+\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 57\]\s* VERIFY:\s+\s+\s+SymbolTestApp\.(dll|exe)!SymbolTestApp\.Program\.Foo2\(.*\)\s+\+\s+\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 32\]\s* VERIFY:\s+\s+\s+SymbolTestApp\.(dll|exe)!SymbolTestApp\.Program\.Foo1\(.*\)\s+\+\s+\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 27\]\s* VERIFY:\s+\s+\s+SymbolTestApp\.(dll|exe)!SymbolTestApp\.Program\.Main\(.*\)\s+\+\s+\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 22\]\s* @@ -102,7 +102,7 @@ VERIFY:\s+\s+\s+SymbolTestApp\.(dll|exe)!SymbolTestApp\.Program\ SOSCOMMAND:ClrStack -a VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ -VERIFY:.*\s+\s+\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57)\]\s* +VERIFY:.*\s+\s+\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 57\]\s* VERIFY:\s+PARAMETERS:\s+ VERIFY:\s+dllPath \(0x\) = 0x\s+ VERIFY:.*\s+LOCALS:\s+ @@ -116,7 +116,7 @@ SOSCOMMAND:ClrStack -r VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ -VERIFY:.*\s+\s+\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57)\]\s* +VERIFY:.*\s+\s+\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+\[(?i:.*[\\|/]SymbolTestApp\.cs) @ 57\]\s* IFDEF:ARM VERIFY:\s+r0=\s+r1=\s+r2=\s+ ENDIF:ARM @@ -234,7 +234,7 @@ ENDIF:DOTNETDUMP SOSCOMMAND:ClrStack SOSCOMMAND:IP2MD .*\s+()\s+SymbolTestApp\.Program\.Foo4.*\s+ VERIFY:.*\s+Method Name:\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+ -VERIFY:.*\s+Source file:\s+(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57)\s+ +VERIFY:.*\s+Source file:\s+(?i:.*[\\|/]SymbolTestApp\.cs) @ 57\s+ # Verify that DumpIL works (depends on the IP2MD right above) SOSCOMMAND:DumpIL \s*MethodDesc:\s+()\s* @@ -254,7 +254,7 @@ SOSCOMMAND:clru \s*MethodDesc:\s+()\s* VERIFY:\s*Normal JIT generated code\s+ VERIFY:\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+ VERIFY:\s+Begin\s+,\s+size\s+\s+ -VERIFY:\s+(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57):\s+ +VERIFY:\s+(?i:.*[\\|/]SymbolTestApp\.cs) @ 57:\s+ # Verify that "u" with no line info works SOSCOMMAND:clru -n @@ -267,7 +267,7 @@ SOSCOMMAND:clru -o VERIFY:\s*Normal JIT generated code\s+ VERIFY:\s+SymbolTestApp\.Program\.Foo4\(System\.String\)\s+ VERIFY:\s+Begin\s+,\s+size\s+\s+ -VERIFY:\s+(?i:.*[\\|/]SymbolTestApp\.cs) @ (53|57):\s+ +VERIFY:\s+(?i:.*[\\|/]SymbolTestApp\.cs) @ 57:\s+ ENDIF:DOTNETDUMP diff --git a/src/tests/SOS.UnitTests/Scripts/StackTests.script b/src/tests/SOS.UnitTests/Scripts/StackTests.script index 485774da01..430d7a7ab3 100644 --- a/src/tests/SOS.UnitTests/Scripts/StackTests.script +++ b/src/tests/SOS.UnitTests/Scripts/StackTests.script @@ -20,7 +20,12 @@ ENDIF:ALPINE SOSCOMMAND:ClrStack VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ +IFDEF:DESKTOP VERIFY:\s+\s+.*\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ (11|20)\s*\]\s+ +ENDIF:DESKTOP +!IFDEF:DESKTOP +VERIFY:\s+\s+.*\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ 20\s*\]\s+ +ENDIF:DESKTOP IFDEF:64BIT VERIFY:.*\s+\s+\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ 16\s*\]\s+ ENDIF:64BIT @@ -42,7 +47,12 @@ ENDIF:DOTNETDUMP SOSCOMMAND:ClrStack -f VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ +IFDEF:DESKTOP VERIFY:.*\s+\s+\s+(?i:NestedExceptionTest.*)!NestedExceptionTest\.Program\.Main\(.*\)\s+\+\s+\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ (11|20)\s*\]\s+ +ENDIF:DESKTOP +!IFDEF:DESKTOP +VERIFY:.*\s+\s+\s+(?i:NestedExceptionTest.*)!NestedExceptionTest\.Program\.Main\(.*\)\s+\+\s+\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ 20\s*\]\s+ +ENDIF:DESKTOP IFDEF:64BIT VERIFY:.*\s+\s+\s+(?i:NestedExceptionTest.*)!NestedExceptionTest\.Program\.Main\(.*\)\s+\+\s+\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ 16\s*\]\s+ ENDIF:64BIT @@ -51,7 +61,12 @@ ENDIF:64BIT SOSCOMMAND:ClrStack -a VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ +IFDEF:DESKTOP VERIFY:\s+\s+\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ (11|20)\s*\]\s+ +ENDIF:DESKTOP +!IFDEF:DESKTOP +VERIFY:\s+\s+\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ 20\s*\]\s+ +ENDIF:DESKTOP VERIFY:\s+PARAMETERS:\s+ VERIFY:\s+args \(0x\) = 0x\s+ VERIFY:\s+LOCALS:\s+ @@ -69,7 +84,12 @@ SOSCOMMAND:ClrStack -r VERIFY:.*OS Thread Id:\s+0x\s+.* VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ +IFDEF:DESKTOP VERIFY:\s+\s+\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ (11|20)\s*\]\s+ +ENDIF:DESKTOP +!IFDEF:DESKTOP +VERIFY:\s+\s+\s+NestedExceptionTest\.Program\.Main\(.*\)\s+\[(?i:.*[\\|/]NestedExceptionTest\.cs) @ 20\s*\]\s+ +ENDIF:DESKTOP IFDEF:ARM VERIFY:\s+r0=\s+r1=\s+r2=\s+ ENDIF:ARM diff --git a/src/tests/SOS.UnitTests/Scripts/TaskNestedException.script b/src/tests/SOS.UnitTests/Scripts/TaskNestedException.script index a0aedfc317..92e73eb4f7 100644 --- a/src/tests/SOS.UnitTests/Scripts/TaskNestedException.script +++ b/src/tests/SOS.UnitTests/Scripts/TaskNestedException.script @@ -30,7 +30,7 @@ VERIFY:\s+SP\s+IP\s+Function\s+ VERIFY:\s+\s+.+RandomTest(::|\.)RandomUserTask\.<\.ctor>.+\+0x\s* !IFDEF:DESKTOP !IFDEF:TRIAGE_DUMP -VERIFY:[.+[\\|/]Debuggees[\\|/].*[Tt]ask[Nn]ested[Ee]xception[\\|/][Rr]andom[Uu]ser[Ll]ibrary[\\|/][Rr]andom[Uu]ser[Tt]ask\.cs @ (19|26)\] +VERIFY:[.+[\\|/]Debuggees[\\|/].*[Tt]ask[Nn]ested[Ee]xception[\\|/][Rr]andom[Uu]ser[Ll]ibrary[\\|/][Rr]andom[Uu]ser[Tt]ask\.cs @ 26\] ENDIF:TRIAGE_DUMP ENDIF:DESKTOP @@ -44,7 +44,7 @@ VERIFY:\s+SP\s+IP\s+Function\s+ VERIFY:\s+\s+.+RandomTest(::|\.)RandomUserTask\.InnerException(\(\))?\+0x\s* !IFDEF:DESKTOP !IFDEF:TRIAGE_DUMP -VERIFY:[.+[\\|/]Debuggees[\\|/].*[Tt]ask[Nn]ested[Ee]xception[\\|/][Rr]andom[Uu]ser[Ll]ibrary[\\|/][Rr]andom[Uu]ser[Tt]ask\.cs @ (37|38)\] +VERIFY:[.+[\\|/]Debuggees[\\|/].*[Tt]ask[Nn]ested[Ee]xception[\\|/][Rr]andom[Uu]ser[Ll]ibrary[\\|/][Rr]andom[Uu]ser[Tt]ask\.cs @ 38\] ENDIF:TRIAGE_DUMP ENDIF:DESKTOP VERIFY:\s+\s+.+RandomTest(::|\.)RandomUserTask\.<\.ctor>.+\+0x\s*