寄生虫网站代做,百度广告怎么收费,电子商务说白了是干嘛的,昆山网站建设需要多少钱一#xff1a;什么是时间旅行 简而言之就是把程序的执行流拍成vlog#xff0c;这样就可以对 vlog 快进或者倒退#xff0c;还可以分享给别人做进一步的分析#xff0c;是不是想都不敢想。很开心的是 windbg preview 版本中已经实现了#xff0c;叫做 时间旅行调试 TTD什么是时间旅行 简而言之就是把程序的执行流拍成vlog这样就可以对 vlog 快进或者倒退还可以分享给别人做进一步的分析是不是想都不敢想。很开心的是 windbg preview 版本中已经实现了叫做 时间旅行调试 TTD相比传统的 静态分析 不知道好多少倍。为了能提起大家兴趣我就举二个例子吧。二二个有趣的例子 1. 查看程序都触发了第几代垃圾回收为了方便说明我就用诱导GC手工触发然后再观察都触发了哪一代的 GC 参考代码如下static void Main(string[] args){Liststring list new Liststring();//1. 第一次触发GCGC.Collect();Console.WriteLine(触发full gc);//2. 第二次触发GCGC.Collect(0);Console.WriteLine(触发 0 代 gc);//3.第二次触发GCGC.Collect(1);Console.WriteLine(触发 1 代 gc);}接下来用 windbg 的 launch executeable (advanced) 来附加程序勾选 Record然后在弹框中将 vlog 保存到指定目录最后点击 Record 就可以啦运行完后windbg 会自动加载我的 D:\test\ConsoleApp104.run 的 vlog 文件因为 gc 触发的底层函数是coreclr!WKS::GCHeap::GarbageCollectGeneration 所以我们用 bp 给它下一个断点运行多次 g 命令。0:000 bp coreclr!WKS::GCHeap::GarbageCollectGeneration
Bp expression coreclr!WKS::GCHeap::GarbageCollectGeneration could not be resolved, adding deferred bp
0:000 g
Time Travel Position: 3079F:63E
eax00000001 ebx00000002 ecx00000002 edx00000008 esi00000002 edi00000002
eip02fc4256 esp0057f204 ebp0057f214 iopl0 nv up ei pl nz na po nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000202
coreclr!WKS::GCHeap::GarbageCollectGeneration:
02fc4256 55 push ebp
0:000 g
Time Travel Position: 34661:AF
eax00000001 ebx00000002 ecx00000000 edx00000008 esi00000000 edi00000002
eip02fc4256 esp0057f1f8 ebp0057f208 iopl0 nv up ei pl nz na po nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000202
coreclr!WKS::GCHeap::GarbageCollectGeneration:
02fc4256 55 push ebp
0:000 g
Breakpoint 0 hit
Time Travel Position: 346A5:2CD
eax00000001 ebx00000002 ecx00000001 edx00000008 esi00000001 edi00000002
eip02fc4256 esp0057f1f8 ebp0057f208 iopl0 nv up ei pl nz na po nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000202
coreclr!WKS::GCHeap::GarbageCollectGeneration:
02fc4256 55 push ebp从输出中可以很清楚的看到命中了三次 GarbageCollectGeneration 回收而且从上面的 ecx 寄存器看依次是 2,0,1对应着 gc 的2代回收0代回收 1代回收 这比只有一个静态的 dump 是不是有优势的多要知道我这里的 ConsoleApp101.run 文件是可以分发给别人分析的哦。2. 查看新生成的线程曾今都执行了什么代码这个例子源自朋友遇到的一个问题他的程序跑着跑着发现 ThreadPool 中有400多待命的工作线程线程栈大概如下0:011 k# ChildEBP RetAddr
00 0564fc6c 7531f0ca ntdll!NtRemoveIoCompletion0xc
01 0564fc6c 78480b69 KERNELBASE!GetQueuedCompletionStatus0x2a
02 0564fcb8 7847d92b coreclr!CLRLifoSemaphore::WaitForSignal0x29 [d:\a\_work\1\s\src\vm\synch.cpp 654]
03 0564fd08 7847cf04 coreclr!CLRLifoSemaphore::Wait0x13b [d:\a\_work\1\s\src\vm\synch.cpp 897]
04 0564fdd4 783f2910 coreclr!ThreadpoolMgr::WorkerThreadStart0x234 [d:\a\_work\1\s\src\vm\win32threadpool.cpp 2121]
05 0564ff70 7703fa29 coreclr!Thread::intermediateThreadProc0x50 [d:\a\_work\1\s\src\vm\threads.cpp 2110]
06 0564ff80 772175f4 KERNEL32!BaseThreadInitThunk0x19
07 0564ffdc 772175c4 ntdll!__RtlUserThreadStart0x2f
08 0564ffec 00000000 ntdll!_RtlUserThreadStart0x1b因为给我的是 静态dump所以我无法寻找 11号线程 曾今执行了什么托管代码因为时间不能倒流但现在有了 TTD真的可以让时间倒流啦。。。太有意思了哈哈既然能倒流那就一定有办法找到破绽。为了方便讲解写一个简单例子。static void Main(string[] args){Task.Factory.StartNew(() {Console.WriteLine(我是 task 线程);});Console.ReadLine();}接下来我们一起探究下最后生成的 Thread WorkThread 曾今都执行了什么深挖思路大概是这样的。先将进度条拉到底然后用 !bpmd System_Private_CoreLib System.Threading.Tasks.Task.InnerInvoke 下一个断点最后将时间倒流看谁命中了这个 task。0:000 g
TTD: End of trace reached.
(4f20.4d0c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 36F51:0
eax00070053 ebx00000000 ecx8a60f857 edx77237170 esi7845e6c0 edi00000000
eip771a7000 esp0602fe90 ebp0602ff70 iopl0 nv up ei pl zr na pe nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000246
771a7000 ea09701a773300 jmp 0033:771A70090:009 !bpmd System_Private_CoreLib System.Threading.Tasks.Task.InnerInvoke
MethodDesc 06A29704
Setting breakpoint: bp 05A915C7 [System.Threading.Tasks.Task.InnerInvoke()]
Adding pending breakpoints...0:009 g-
Breakpoint 1 hit
Time Travel Position: 32DF4:AC
eax05a915c0 ebx00000000 ecx0349a864 edx0349a864 esi0349a864 edi0349a7c8
eip05a915c7 esp066afa14 ebp066afa1c iopl0 nv up ei pl zr na pe nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000246
System_Private_CoreLib!System.Threading.Tasks.Task.InnerInvoke()$##60021850x7:
05a915c7 8b7e04 mov edi,dword ptr [esi4] ds:002b:0349a8680349a8000:008 !clrstack
OS Thread Id: 0x44a8 (8)
Child SP IP Call Site
066AFA14 05a915c7 System.Threading.Tasks.Task.InnerInvoke() [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs 2437]
066AFA24 05a915bb System.Threading.Tasks.Taskc..cctorb__274_0(System.Object) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs 2427]
066AFA2C 05a91567 System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/_/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs 289]
066AFA5C 05a912d1 System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs 2389]
066AFABC 05a911d7
066AFACC 05a9118b System.Threading.Tasks.Task.ExecuteFromThreadPool(System.Threading.Thread) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs 2312]
066AFAD0 05a90e58 System.Threading.ThreadPoolWorkQueue.Dispatch() [/_/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs 663]
066AFB1C 05a90c6f
066AFD10 784fa0ef [DebuggerU2MCatchHandlerFrame: 066afd10]熟悉 Task 的朋友应该知道: System.Threading.Tasks.Task.InnerInvoke 的下一步就是执行我的回调函数而此时 回调函数 还没有被 JIT 编译这时候我们可以在 bp clrjit!CILJit::compileMethod 中去拦截 JIT 对此方法的编译然后从 compileMethod 中提取 mt。0:008 bp clrjit!CILJit::compileMethod
0:008 g
Breakpoint 1 hit
Time Travel Position: 32E36:C18
eax7933ad50 ebx066af5c8 ecx792c8770 edx066af5c8 esi7932d164 edi00cbbf90
eip792c8770 esp066af3ec ebp066af44c iopl0 nv up ei pl zr na pe nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000246
clrjit!CILJit::compileMethod:
792c8770 55 push ebp0:008 kb# ChildEBP RetAddr Args to Child
00 066af44c 78428db2 7933ad50 066af5c8 066af4f0 clrjit!CILJit::compileMethod [d:\a\_work\1\s\src\jit\ee_il_dll.cpp 294]
...0:008 dp 066af4f0 L1
066af4f0 06a2ae040:008 !dumpmd 06a2ae04
Method Name: ConsoleApp1.dll!Unknown
Class: 032fa0dc
MethodTable: 06a2ae14
mdToken: 06000005
Module: 02c5d7d0
IsJitted: no
Current CodeAddr: ffffffff
Version History:ILCodeVersion: 00000000ReJIT ID: 0IL Addr: 00000000CodeAddr: 00000000 (MinOptJitted)NativeCodeVersion: 00000000很奇怪的是提取的 md 目前还不能显示完全名字不过没关系我们继续 g 然后再重复执行一下命令。0:009 g
TTD: End of trace reached.
(4f20.4d0c): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 36F51:0
eax00070053 ebx00000000 ecx8a60f857 edx77237170 esi7845e6c0 edi00000000
eip771a7000 esp0602fe90 ebp0602ff70 iopl0 nv up ei pl zr na pe nc
cs0023 ss002b ds002b es002b fs0053 gs002b efl00000246
771a7000 ea09701a773300 jmp 0033:771A7009
0:009 !dumpmd 06a2ae04
Method Name: ConsoleApp1.Programc.Mainb__0_0()
Class: 032fa0dc
MethodTable: 06a2ae14
mdToken: 06000005
Module: 02c5d7d0
IsJitted: yes
Current CodeAddr: 06133300
Version History:ILCodeVersion: 00000000ReJIT ID: 0IL Addr: 00000000CodeAddr: 06133300 (MinOptJitted)NativeCodeVersion: 00000000当时间线结束的时候我们终于看到了原来 Task 执行的是 ConsoleApp1.Programc.Mainb__0_0() 方法那这个方法逻辑是什么呢可以用 ILSpy 查看。总的来说要复现还是挺考验基本功的。