VC编译Release程序,如何在不生成debug信息(pdb文件)情况下处理崩溃
如题,VC编译Release程序,如果生成debug信息,就可以获取dump文件,如何在不生成debug信息(pdb文件)、并进行优化的情况下处理崩溃呢,先说声谢谢!!
[解决办法]
比如最简单的个测试:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define STACK_FRAME_MAXSIZE0x40000
struct i386_stack_frame
{
struct i386_stack_frame*next;
void*fret;
};
int i386_backtrace_( void* sym[] , int n , struct i386_stack_frame* frame )
{
int i = 0;
struct i386_stack_frame *frame_begin = frame , *frame_end = frame_begin + STACK_FRAME_MAXSIZE;
while( 1 )
{
if( i >= n
[解决办法]
NULL == frame
[解决办法]
frame < frame_begin
[解决办法]
frame > frame_end
[解决办法]
((int)frame & 3) != 0 )
break;
sym[i++] = frame->fret;
frame = frame->next;
}
return i;
}
void foobar( int* nil )
{
*nil = 0;
}
int except_filter( PEXCEPTION_RECORD rcd , PCONTEXT ctx , void* callstack[] , int* n , struct _EXCEPTION_POINTERS* info )
{
memcpy( rcd , info->ExceptionRecord , sizeof( *rcd ) );
memcpy( ctx , info->ContextRecord , sizeof( *ctx ) );
*n = i386_backtrace_( callstack , *n , (void*)ctx->Ebp );
return 1;
}
int main()
{
void* callstack[100] = {0} ;
int n = 100;
EXCEPTION_RECORDrcd;
CONTEXTctx;
__try
{
foobar( NULL );
}
__except( except_filter( &rcd , &ctx , callstack , &n , GetExceptionInformation() ) )
{
int i;
printf( "Load addr: %p\n" , GetModuleHandle(NULL) );
printf( "callstack:\n\t%x\n" , ctx.Eip );
for( i = 0; i < n; ++i )
{
printf( "\t%x\n" , callstack[i] );
}
}
return 0;
}
如下编译:
cl -nologo 1.c -link -map
Relase 版本这样子编译 cl -O2 -Oy- -nologo 1.c -link -map
生成的mapfile(部分):
Address Publics by Value Rva+Base Lib:Object
0000:00000000 __except_list 00000000 <absolute>
0000:00000003 ___safe_se_handler_count 00000003 <absolute>
0000:00000000 ___ImageBase 00400000 <linker-defined>
0001:00000000 _i386_backtrace_ 00401000 f 1.obj
0001:00000080 _foobar 00401080 f 1.obj
0001:00000090 _except_filter 00401090 f 1.obj
0001:000000f0 _main 004010f0 f 1.obj
0001:00000230 _memcpy 00401230 f LIBCMT:memcpy.obj
0001:00000591 _printf 00401591 f LIBCMT:printf.obj
0001:00000638 __get_printf_count_output 00401638 f LIBCMT:printf.obj
0001:0000064e @__security_check_cookie@4 0040164e f LIBCMT:secchk.obj
0001:00000660 __except_handler4 00401660 f LIBCMT:chandler4.obj
0001:000007f0 _memset 004017f0 f LIBCMT:memset.obj
运行结果:
Load addr: 01380000
callstack:
1381086
1381161
138199e
746c339a
76fa9ef2
76fa9ec5
0
把这些输出地址 - 01380000 + 00400000 然后到mapfile里去查对应的函数, 得到 callstack 为:
_foobar + 0006
_main + 0071
如果你还想分析出 dll 里的函数名, 先把全部的dll模块枚举出来.
这VS2010咋这么破, mapfile 里有些函数地址咋个是错误的, 与我在IDA里看的对不上.
转储模块信息就是 保存异常时候全部的DLL模块的基址, 不然不好恢复DLL里函数栈帧...
一般有下面的出错信息, 基本就可以恢复异常时候的程序状态:
1: 当前全部的寄存器值
2: 堆栈的转储信息
3: 全部模块加载的基地址
backtrace都可以直接用1,2的信息拿回来以后再做....