VS2017报告的看似错误的指令指针

时间:2019-05-10 19:11:24

标签: windows visual-studio-2017 x86-64 visual-studio-debugging disassembly

编辑:

我已经进行了更多研究,并且以下所报告的问题似乎仅在我使用Visual Studio 2017暂停该过程时发生。似乎当rip指向无效位置时,它总是从正确的指令开始起+1个字节的偏移量。

此外,就上下文而言,这是一个大型C ++项目,其中包含许多dll,一些使用MSVC 2015编译,其余使用icc(英特尔编译器2017)进行编译。这是在使用Boost C ++ / python绑定的python进程中运行的。

原始帖子:

我正在随机暂停程序,以查看在进行大量计算时线程在做什么。 请注意,我不是在调试崩溃,请恢复程序正常运行。

但是,VS调试器有时无法反汇编机器代码。 例如,在rip = 000007FE8B048EE2的一个线程上,它显示如下:

000007FE8B048EDE  ?? ?? 
000007FE8B048EDF  ?? ?? 
000007FE8B048EE0  ?? ?? 
000007FE8B048EE1  ?? ?? 
                    }

                    if (params.derandomize) {
000007FE8B048EE2  adc         ebp,eax  
                        GetRNG().Seed(id);
000007FE8B048EE4  pop         rax  
000007FE8B048EE5  wait  
000007FE8B048EE6  adc         byte ptr [rax],al  
000007FE8B048EE8  mov         rcx,rax  

解码的x86指令似乎也出错(adc,pop,wait,adc ??),所以我也尝试附加WinDBG(非侵入模式):

0:019> u rip
somedll!<lambda239>::operator()+0x132:
000007fe`8b048ee2 13e8            adc     ebp,eax
000007fe`8b048ee4 58              pop     rax
000007fe`8b048ee5 9b              wait
000007fe`8b048ee6 1000            adc     byte ptr [rax],al
000007fe`8b048ee8 4889c1          mov     rcx,rax
000007fe`8b048eeb 8b9570080000    mov     edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000      call    somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000  mov     r12,qword ptr [rbp+8B0h]

好吧,这是一样的垃圾... 但是后来我试图从略高于rip的地址处反汇编:

0:019> u rip-30
somedll!<lambda239>::operator()+0x102:
000007fe`8b048eb2 00488b          add     byte ptr [rax-75h],cl
000007fe`8b048eb5 084863          or      byte ptr [rax+63h],cl
000007fe`8b048eb8 81d003000048    adc     eax,48000003h
000007fe`8b048ebe 83f8ff          cmp     eax,0FFFFFFFFh
000007fe`8b048ec1 740a            je      somedll!<lambda239>::operator()+0x11d (000007fe`8b048ecd)
000007fe`8b048ec3 4889c2          mov     rdx,rax
000007fe`8b048ec6 48899570080000  mov     qword ptr [rbp+870h],rdx
000007fe`8b048ecd 486381e0030000  movsxd  rax,dword ptr [rcx+3E0h]
0:019> u
somedll!<lambda239>::operator()+0x124:
000007fe`8b048ed4 483bd0          cmp     rdx,rax
000007fe`8b048ed7 7501            jne     somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc              int     3
000007fe`8b048eda 80b96303000000  cmp     byte ptr [rcx+363h],0
000007fe`8b048ee1 7413            je      somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000      call    somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1          mov     rcx,rax
000007fe`8b048eeb 8b9570080000    mov     edx,dword ptr [rbp+870h]
0:019> u
somedll!<lambda239>::operator()+0x141:
000007fe`8b048ef1 e8fa911000      call    somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000  mov     r12,qword ptr [rbp+8B0h]
000007fe`8b048efd 488d95f0070000  lea     rdx,[rbp+7F0h]
000007fe`8b048f04 488d8dc0070000  lea     rcx,[rbp+7C0h]
000007fe`8b048f0b 498b0424        mov     rax,qword ptr [r12]
000007fe`8b048f0f 4c8da570080000  lea     r12,[rbp+870h]
000007fe`8b048f16 488942d0        mov     qword ptr [rdx-30h],rax
000007fe`8b048f1a 4c8962d8        mov     qword ptr [rdx-28h],r12

000007fe`8b048eb2处的第一条指令“ add byte ptr”和“ or byte ptr”没有意义,因为rip-30可能落在一条指令的中间,但之后似乎重新同步,因为它对应于源代码:

if (id == params.dbgbreak_id) {
    __debugbreak();
}

if (params.derandomize) {
    GetRNG().Seed(id);
}

000007fe`8b048ecd 486381e0030000  movsxd  rax,dword ptr [rcx+3E0h]
000007fe`8b048ed4 483bd0          cmp     rdx,rax                  // if (id == params.dbgbreak_id) {
000007fe`8b048ed7 7501            jne     somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc              int     3                        // __debugbreak(); }
000007fe`8b048eda 80b96303000000  cmp     byte ptr [rcx+363h],0    // if (params.derandomize)
000007fe`8b048ee1 7413            je      somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000      call    somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1          mov     rcx,rax
000007fe`8b048eeb 8b9570080000    mov     edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000      call    somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)

很显然,没有任何指令以000007fe8b048ee2开头! 在000007fe8b048ee1处有je,在000007fe8b048ee3处有电话

所以...我想,嗯,调试器中有一个错误...让我们检查一下寄存器:

0:019> r
rax=ffffffffffffffff rbx=000000000021d420 rcx=000000000021d5d0
rdx=0000000002696568 rsi=0000000000005d38 rdi=0000000056eefc40
rip=000007fe8b048ee2 rsp=0000000056eef5b0 rbp=0000000056eef5e0
 r8=0000000000000006  r9=000000000021d0b8 r10=0000000006456570
r11=0000000000000006 r12=0000000056eefe50 r13=00000000069a8820
r14=000000000021d1a8 r15=0000000056eefe60
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246

什么? rip = 000007fe8b048ee2 ??那怎么可能?

它解释了调试器为何显示垃圾的原因:它试图从rip开始反汇编,但是rip指向指令的中间。 但是,为什么报告的撕裂是错误的?是操作系统的罪魁祸首吗? 我想念什么吗?

0 个答案:

没有答案