跳过前面的基础配置和pdb加载。认为你基本的调试都会
第一步:找出崩溃的线程
一般崩溃弹出对话框截取的dump都会以主线程为显示。所以要找出崩溃的线程,
~*kbn #查看所有进程,排除在等待的线程,一般某个线程在执行最后在执行某个函数时最有可能
~69s #切换当前线程
根据崩溃的地方找到代码,及出错的相关数据:
bool ff_video_callback_frame(struct ff_frame*frame, void *opaque)
{
if (player_source && frame&&!player_source->abort){
if (!update_sws_context(player_source, frame->frame)){
Log_Error("update_sws_context failed!\n");
return false;
}
sws_scale(player_source->sws_ctx,
(uint8_t const *const *)frame->frame->data,
frame->frame->linesize,
0,
frame->frame->height,
&player_source->sws_data,
&player_source->sws_linesize
);
....
}
}
以上是我的代码。做一个示例:
sws_scale(player_source->sws_ctx,
(uint8_t const *const *)frame->frame->data,
frame->frame->linesize,
0,
frame->frame->height,
&player_source->sws_data,
&player_source->sws_linesize
);
问题出在sws_scale函数的调用中,,传入的参数和frame、player_source 相关,
但是当使用dv和kp的时候并没有看到frame和player_source的数据,也就是说release的程序把相关的寄存器覆盖了或者优化了。如图:
所以接下来需要从反汇编中相关的寄存器找到frame和player_source的值
首先传入的参数 都存在: rcx rdx r8 r9 和rsp中
so: 先查看调用sws_scale处的汇编代码,即ub sws_scale的RetAddr
- player_source
0:069> ub 00007ff6`c61c01c7 L20
00007ff6`c61c0191 488b17 mov rdx,qword ptr [rdi]
00007ff6`c61c0194 488b4b18 mov rcx,qword ptr [rbx+18h] //这里对应着player_source->sws_ctx,所以rbx就存着player_source
00007ff6`c61c0198 48896c2450 mov qword ptr [rsp+50h],rbp
00007ff6`c61c019d 8b426c mov eax,dword ptr [rdx+6Ch]
00007ff6`c61c01a0 4889742458 mov qword ptr [rsp+58h],rsi
00007ff6`c61c01a5 488d6b28 lea rbp,[rbx+28h]
00007ff6`c61c01a9 48896c2430 mov qword ptr [rsp+30h],rbp
00007ff6`c61c01ae 488d7320 lea rsi,[rbx+20h] //这里对rbx做地址赋值
00007ff6`c61c01b2 4c8d4240 lea r8,[rdx+40h]
00007ff6`c61c01b6 4533c9 xor r9d,r9d
00007ff6`c61c01b9 4889742428 mov qword ptr [rsp+28h],rsi//这里对rsi对rsp地址赋值
00007ff6`c61c01be 89442420 mov dword ptr [rsp+20h],eax
00007ff6`c61c01c2 e83910feff call yExam!sws_scale (00007ff6`c61a1200)
以上的分析可以从rsp栈中推倒出rsi和rbx,
- frame
但是根据上面的信息,无法得出frame的值,因为rdx 会在后续的调用中改变,而r8也会在sws_scale 中改变。
00007ff6`c61c0191 488b17 mov rdx,qword ptr [rdi] //frame->frame
00007ff6`c61c019d 8b426c mov eax,dword ptr [rdx+6Ch]//frame->frame->data,
00007ff6`c61c01b2 4c8d4240 lea r8,[rdx+40h]//frame->frame->height,
so我们网上查看调用者的信息, 找到r14寄存器
:
追寻r14寄存器发现ff_video_callback_frame中没有使用,而在sws_scale中做了push操作
最后可以根据r14 寄存器得出我们 的内容。
总结:windbg这个工具,不用就忘了,很久不用就生疏,所以对一些简单的流程做一下记录。
以上是在堆栈没有被溢出或者破坏的情况进行的,如果堆栈破坏很大的可能是数组越界。