Редактировать:
Я исследовал больше, и описанная ниже проблема, кажется, возникает только тогда, когда я использую Visual Studio 2017, чтобы приостановить процесс.Также кажется, что когда rip указывает на неверное местоположение, это всегда смещение на +1 байт от правильного начала инструкции.
Кроме того, для контекста это большой проект C ++ с большим количеством dll, некоторые скомпилированыс MSVC 2015, остальное с ICC (Intel Compiler 2017).Это выполняется в процессе Python с использованием улучшенных привязок C ++ / 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]
Хорошо, это тот же мусор ... Но потом я попытался разобрать с адреса чуть выше рипа:
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
первые инструкции"add byte ptr" и "or byte ptr" в 000007fe`8b048eb2 не имеют смысла, потому что 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 указывает на середину инструкции.Но почему заявленный разрыв неправильный?Виновник ОС?Я что-то упустил?