2015-05-11 34 views
5

Mam zrzut awaryjny x64 aplikacji zarządzanej (C#), która p/wywołuje do natywnego kodu. Zrzut został wykonany po tym, jak kod natywny próbował usunąć błędne położenie pamięci, a po tym, jak platforma .NET zmieniła ją w AccessViolationException. W wyniku tego, ramka stos, w którym wystąpił błąd nie jest dostępny, i wątek, w których wyjątek jest już porwane przez procedurę obsługi wyjątków clr:Jak odzyskać kontekst rejestru z AccessViolationException?

0:017> kb 
# RetAddr   : Args to Child               : Call Site 
00 000007fe`fd3b10dc : 00000000`0402958b 00000000`20000002 00000000`00000e54 00000000`00000e4c : ntdll!NtWaitForSingleObject+0xa 
01 000007fe`ea9291eb : 00000000`00000000 00000000`00000cdc 00000000`00000000 00000000`00000cdc : KERNELBASE!WaitForSingleObjectEx+0x79 
02 000007fe`ea929197 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!CLREventWaitHelper2+0x38 
03 000007fe`ea929120 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!CLREventWaitHelper+0x1f 
04 000007fe`ead8cae5 : 00000000`29cbc7c0 00000000`3213ce40 00000000`00000000 00000000`ffffffff : clr!CLREventBase::WaitEx+0x70 
05 000007fe`ead8c9d0 : 00000000`29cbc7c0 00000000`00000000 00000000`0002b228 00000000`0002b228 : clr!Thread::WaitSuspendEventsHelper+0xf5 
06 000007fe`eacf2145 : 00000000`007ea060 000007fe`ea924676 00000000`00000000 000007fe`fd3b18da : clr!Thread::WaitSuspendEvents+0x11 
07 000007fe`eaccc00c : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!Thread::RareEnablePreemptiveGC+0x33a905 
08 000007fe`eae2c762 : 00000000`00000000 00000000`007cbce0 00000000`29cbc7c0 00000000`00000001 : clr!Thread::RareDisablePreemptiveGC+0x31b40c 
09 000007fe`eaf662d4 : 00000000`00000000 00000000`007cbce0 00000000`29cbc7c0 00000000`00000000 : clr!EEDbgInterfaceImpl::DisablePreemptiveGC+0x22 
0a 000007fe`eaf66103 : 00000000`29cb0100 00000000`00000000 00000000`3213cf80 00000000`29cbca20 : clr!Debugger::SendExceptionHelperAndBlock+0x174 
0b 000007fe`eaf65d0d : ffffffff`ffffffff 00000000`29cbca20 00000000`29cbc700 000007fe`eaf62100 : clr!Debugger::SendExceptionEventsWorker+0x343 
0c 000007fe`eaf61bd8 : 00000000`00000100 00000000`00000000 00000000`00000019 00000000`3213dd01 : clr!Debugger::SendException+0x15d 
0d 000007fe`eadac75d : 00000000`007cbce0 00000000`3213d258 00000000`3213d1e8 00000000`00000001 : clr!Debugger::LastChanceManagedException+0x1f8 
0e 000007fe`eaf698c7 : 000075ce`2b30e018 00000000`00000000 00000000`00000001 00000000`00000000 : clr!NotifyDebuggerLastChance+0x6d 
0f 000007fe`eaf6af20 : 00000000`00000000 000007fe`8cf40020 000007fe`8cfa200c 4328fffe`43e0fffe : clr!Debugger::UnhandledHijackWorker+0x1a7 
10 000007fe`eaaacbf0 : 00000000`0000000a 00000000`2ab23e30 00000000`00000001 00000000`00000000 : clr!ExceptionHijackWorker+0xc0 
11 00000000`3213d8c0 : 00000000`3213ddb0 00000000`00000001 00000000`00000000 00000000`0000000b : clr!ExceptionHijack+0x30 
12 00000000`3213ddb0 : 00000000`00000001 00000000`00000000 00000000`0000000b 00000000`0035578c : 0x3213d8c0 
13 00000000`00000001 : 00000000`00000000 00000000`0000000b 00000000`0035578c ffffffff`00000002 : 0x3213ddb0 
14 00000000`00000000 : 00000000`0000000b 00000000`0035578c ffffffff`00000002 00000000`00350268 : 0x1 

I .exr -1 (wyświetlanie Najnowsze wyjątku) zwrócone:

0:017> .exr -1 
ExceptionAddress: 00000000771d685a (user32!ZwUserMessageCall+0x000000000000000a) 
    ExceptionCode: 80000004 (Single step exception) 
    ExceptionFlags: 00000000 
NumberParameters: 0 

wezwanie do user32!ZwUserMessageCall jest na szczycie stosu wątku 0, a nie 17, gdzie nastąpiło rodzimy wyjątek, więc mogę tylko przypuszczać, to nie wskazując na moim wyjątku.

mogę zrzucić wyjątek naruszenia zasad dostępu, aby uzyskać pewne informacje o natywnej błędu:

0:017> !DumpObj /d 0000000012175640 
Name:  System.AccessViolationException 
MethodTable: 000007fee9a61fe8 
EEClass:  000007fee9528300 
Size:  176(0xb0) bytes 
File:  C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 
Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
000007fee9a50e08 4000002  8  System.String 0 instance 000000001217b538 _className 
000007fee9a5b218 4000003  10 ...ection.MethodBase 0 instance 0000000000000000 _exceptionMethod 
000007fee9a50e08 4000004  18  System.String 0 instance 0000000000000000 _exceptionMethodString 
000007fee9a50e08 4000005  20  System.String 0 instance 0000000012179818 _message 
000007fee9a61f18 4000006  28 ...tions.IDictionary 0 instance 0000000000000000 _data 
000007fee9a51038 4000007  30  System.Exception 0 instance 0000000000000000 _innerException 
000007fee9a50e08 4000008  38  System.String 0 instance 0000000000000000 _helpURL 
000007fee9a513e8 4000009  40  System.Object 0 instance 0000000012179ad0 _stackTrace 
000007fee9a513e8 400000a  48  System.Object 0 instance 0000000012179c68 _watsonBuckets 
000007fee9a50e08 400000b  50  System.String 0 instance 0000000000000000 _stackTraceString 
000007fee9a50e08 400000c  58  System.String 0 instance 0000000000000000 _remoteStackTraceString 
000007fee9a53980 400000d  88   System.Int32 1 instance    0 _remoteStackIndex 
000007fee9a513e8 400000e  60  System.Object 0 instance 0000000000000000 _dynamicMethods 
000007fee9a53980 400000f  8c   System.Int32 1 instance  -2147467261 _HResult 
000007fee9a50e08 4000010  68  System.String 0 instance 0000000000000000 _source 
000007fee9a54a00 4000011  78  System.IntPtr 1 instance    0 _xptrs 
000007fee9a53980 4000012  90   System.Int32 1 instance  -532462766 _xcode 
000007fee9a02d50 4000013  80  System.UIntPtr 1 instance    0 _ipForWatsonBuckets 
000007fee9a3d210 4000014  70 ...ializationManager 0 instance 0000000012179900 _safeSerializationManager 
000007fee9a513e8 4000001  0  System.Object 0 shared   static s_EDILock 
           >> Domain:Value 00000000007e09b0:NotInit << 
000007fee9a54a00 400018a  98  System.IntPtr 1 instance  7fedad179f4 _ip 
000007fee9a54a00 400018b  a0  System.IntPtr 1 instance fffffffc2ab22078 _target 
000007fee9a53980 400018c  94   System.Int32 1 instance    0 _accessType 

Z tego widzę adresu instrukcji, które nie powiodło się (7fedad179f4) i adresem, że kod próbuje dereference (fffffffc2ab22078). Wygląda na to, że w pewnym sensie jest to rozszerzenie znaku lub błąd przepełnienia, ale w kodzie nie jest oczywiste, jak to się mogło stać. Dyspozycja odwołania wynosi:

0:017> u 7fedad179f4 
MYDLL!_interpolate+0x174 [c:\my\source\file.c @ 85]: 
000007fe`dad179f4 f3450f59548404 mulss xmm10,dword ptr [r12+rax*4+4] 

W tym celu debugowania dalej, muszę kontekst Rejestry od kiedy rozbił natywny kod, aby zobaczyć, co było w r12 i rax. Czy można to odzyskać?


Edit: starałem się uzyskać informacje na temat parametrów ExceptionHijackWorker, ale wartości nie ma sensu do mnie. Podpis funkcja według @ linku S.t. jest

void STDCALL ExceptionHijackWorker(T_CONTEXT * pContext, 
            EXCEPTION_RECORD * pRecord, 
            EHijackReason::EHijackReason reason, 
            void * pData); 

Więc pierwszy parametr nie ma sensu jako wskaźnik. I dumping drugi parametr 000000002ab23e30 daje bezsensowne dane dla EXCEPTION_RECORD:

0:017> dd 000000002ab23e30 
00000000`2ab23e30 00000019 00000019 2ab23e40 00000000 
00000000`2ab23e40 42b8f800 42b8de00 42b89b00 42b85000 
00000000`2ab23e50 42b81b00 42b7a000 42b72600 42b6fa00 
00000000`2ab23e60 42b6a000 42b67a00 42b63600 42b59c00 
00000000`2ab23e70 42b4fc00 42b4da00 42b49e00 42b46a00 
00000000`2ab23e80 42b38e00 42b31c00 42b2d600 42b29000 
00000000`2ab23e90 42b2ec00 42b2fa00 42b2a000 42b27a00 
00000000`2ab23ea0 42b23e00 42b6e800 42b6ab00 42b66c80 

0x19 i 0x19 dla ExceptionCode i ExceptionFlags nie ma sensu; nie ma kodu o tej wartości i flaga jest dokumentowana jako zero lub EXCEPTION_NONCONTINUABLE, która jest zdefiniowana jako 1.

Czy źle interpretuję cokolwiek tutaj?

+0

Więc '.exr -1' już odnosi się do wyjątku .NET? Sądzę, że będzie to trudne na x64, ponieważ rejestry są używane do wielu celów w konwencji wywołania x64. Może mógłbyś dodać do postu, który znasz o 'r' i' .frame', tak jak wspomniano w komentarzach usuniętej odpowiedzi. –

+1

Czy znalazłeś http://blogs.msdn.com/b/ntdebugging/archive/2010/05/12/x64-manual-stack-reconstruction-and-stack-walking.aspx? –

+0

@ThomasWeller Dzięki za link. Myślę, że powinienem móc użyć tych informacji, aby się oderwać od 'clr! ExceptionHijack' chociaż nie widzę jak; nie wciska żadnych rejestrów zgodnie z '.fnent'. Wierzę, że ".exr -1" już wskazuje na AVE, ale nie jest to oczywiste. Opublikowaliśmy również jego wyniki. –

Odpowiedz

3

Po uzyskaniu porady od @S.T., zacząłem sondować wokół stosu wywołań, aby sprawdzić, czy mogę znaleźć rekord wyjątku lub rekord kontekstu.Zacząłem wokół dziwności na dnie stosu, a mianowicie:

0:017> k 
# Child-SP   RetAddr   Call Site 
... 
0f 00000000`3213d210 000007fe`eaf6af20 clr!Debugger::UnhandledHijackWorker+0x1a7 
10 00000000`3213d850 000007fe`eaaacbf0 clr!ExceptionHijackWorker+0xc0 
11 00000000`3213d880 00000000`3213d8c0 clr!ExceptionHijack+0x30 
12 00000000`3213d8a8 00000000`3213ddb0 0x3213d8c0 
13 00000000`3213d8b0 00000000`00000001 0x3213ddb0 
14 00000000`3213d8b8 00000000`00000000 0x1 

zdarzyło mi się znaleźć zapis wyjątek:

0:017> .exr 00000000`3213ddb0 
ExceptionAddress: 000007fedad179f4 (SMTCV!_interpolate+0x0000000000000174) 
    ExceptionCode: c0000005 (Access violation) 
    ExceptionFlags: 00000000 
NumberParameters: 2 
    Parameter[0]: 0000000000000000 
    Parameter[1]: fffffffc2ab22078 
Attempt to read from address fffffffc2ab22078 

I wtedy stało się znaleźć zapis kontekstowe (czego szukałem for):

0:017> .cxr 00000000`3213d8c0 
rax=0000000000000019 rbx=000000000000000a rcx=00000000709c7c88 
rdx=0000000000000002 rsi=000000002ab23e30 rdi=0000000080000000 
rip=000007fedad179f4 rsp=000000003213dff0 rbp=0000000000000019 
r8=000007ffffe22000 r9=0000000070910000 r10=0000000000000000 
r11=000000003213e0a0 r12=fffffffc2ab22010 r13=000000002b50ae40 
r14=000000002ab241ec r15=0000000000000003 
iopl=0   nv up ei pl nz na pe nc 
cs=0033 ss=002b ds=0000 es=0000 fs=0000 gs=0000    efl=00010200 
MYDLL!_interpolate+0x174: 
000007fe`dad179f4 f3450f59548404 mulss xmm10,dword ptr [r12+rax*4+4] ds:fffffffc`2ab22078=???????? 

Teraz mogę zobaczyć mój zły wskaźnik w r12!

Nie rozumiem, czym są te klatki stosów lub dlaczego zapisy wyjątku i kontekstu były przechowywane jako adres zwrotny dla nich. Wszelkie komentarze na ten temat byłyby wspaniałe, zarówno dla mnie, jak i dla przyszłych czytelników.

+1

Czy jest jakiś sposób, aby uzyskać dostęp do tego dump, chciałbym zbadać więcej lub fragment kodu repro? – Addy

+1

Niestety nie mogłem zwolnić zrzutów, a bez symboli byłoby to zupełnie bezwartościowe do analizy. Utworzenie fragmentu kodu repro jest dość łatwe. Potrzebujesz tylko metody C, która usuwa wadliwą pamięć, a następnie p/wywołać tę metodę z C#. –

+1

Którą ramową wersję masz na 4.o lub 4.5 nie oczekuję dużej różnicy, ale na wszelki wypadek. – Addy