破一桩疑案——硬件错误( 三 )


2.3 step3:寻找VCRUNTIME140!__favor的写入点——看看这个变量到底指代什么如何确定这个变量到底在哪里初始化的呢?方法很多 , 比如用内存搜寻软件遍历IDE下的所有文件 , 或许能找到些 , 但作为专业的人应该干专业的事情 , 上调试器吧 , 下一个内存写断点 , 一切搞定 。 对于这个目的 , VS可以做 , 但不专业 , 祭出Windbg吧 , 如下:
0:000> ba r4 VCRUNTIME140D!__favor 0:000> g Breakpoint 0 hit eax=00000000 ebx=029c67af ecx=00000004 edx=00000200 esi=00c0f0e4 edi=0f755720 eip=0f755947 esp=00c0f0bc ebp=00c0f104 iopl=0nv up ei pl nz na pe nc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000206 VCRUNTIME140D!__isa_available_init+0x1f7: 0f755947 83c802oreax,2有两点值得说明:1)此时我们应该用r标志 , 读写都可以断下开;2)此时我们下断点的模块是VCRUNTIME140D而不是VCRUNTIME140 , 应该当前处于调试模式;断下来了 , 多么神奇的操作 , 瞬间定位到感兴趣的地方;看样子是VCRUNTIME140D!__isa_available_init()这个函数里边初始化的;稍微往前看下这个指令的or eax , 2在什么情况下会走到;
破一桩疑案——硬件错误
本文插图
三次ub指令便找到了根源;原来是用的cpuid指令 , 传入的参数是7;当然根据善解人意的Windbg的提示可知 , 这个函数在cpu_disp.c这个文件中实现了 , 那就找下这个文件;
破一桩疑案——硬件错误
本文插图
啥也没有 , 看来微软并不想把这个公开出来 , 没关系;我们先看下栈吧 , 看看什么逻辑走到的这里 , 然后再来深究这个cpuid+7到底干啥的 , 调用栈如下:
0:000> k ChildEBP RetAddr 00c0f104 0f749938 VCRUNTIME140D!__isa_available_init+0x1f7 [d:agent_work3ssrcvctoolscrtvcstartupsrcmisci386cpu_disp.c @ 108] 00c0f10c 0f7556b8 VCRUNTIME140D!__vcrt_initialize+0x8 [d:agent_work3ssrcvctoolscrtvcruntimesrcinternalinitialization.cpp @ 59] 00c0f114 0f755648 VCRUNTIME140D!DllMainProcessAttach+0x8 [d:agent_work3ssrcvctoolscrtvcruntimesrcdllvcruntime_dllmain.cpp @ 17] 00c0f128 0f75573f VCRUNTIME140D!DllMainDispatch+0x28 [d:agent_work3ssrcvctoolscrtvcruntimesrcdllvcruntime_dllmain.cpp @ 49] 00c0f13c 7786a896 VCRUNTIME140D!__vcrt_DllMain+0x1f [d:agent_work3ssrcvctoolscrtvcruntimesrcdllvcruntime_dllmain.cpp @ 88] 00c0f15c 778401a6 ntdll!LdrxCallInitRoutine+0x16 00c0f1a8 77838141 ntdll!LdrpCallInitRoutine+0x55 00c0f230 77837e03 ntdll!LdrpInitializeNode+0x110 00c0f254 77837de6 ntdll!LdrpInitializeGraphRecurse+0x7d 00c0f27c 778a2a2b ntdll!LdrpInitializeGraphRecurse+0x60 00c0f4d8 77863242 ntdll!LdrpInitializeProcess+0x1d0f 00c0f534 7786310c ntdll!_LdrpInitialize+0xe0 00c0f544 00000000 ntdll!LdrInitializeThunk+0x1c很清楚了 , 在进程刚启动时 , 加载VCRUNTIME140D执行其入口函数时 , 执行了初始化的动作;那下边就搜索下cpuid+7这个指令的具体作用了 , 如下:
破一桩疑案——硬件错误
本文插图
破一桩疑案——硬件错误
本文插图
根据搜索到的信息来看 , 这个所谓的ERMS确实是Intel提供的优化新能的指令 , CPUID+7就是来检测当前的CPU是否支持这个性能优化指令的;一切都顺理成章;那下边就要确定下从哪一代Intel的CPU开始 , 这个ERMS特性是支持的了 , 这个要查询Intel的白皮书了;


推荐阅读