VC编译Release程序,如何在不生成debug信息(pdb文件)情况下处理崩溃
如题,VC编译Release程序,如果生成debug信息,就可以获取dump文件,如何在不生成debug信息(pdb文件)、并进行优化的情况下处理崩溃呢,先说声谢谢!!
[解决办法]
[解决办法]
一个最简单的例子, linux下的就不写了, 比这个方便一些..
- C/C++ code
比如最简单的个测试:#include <windows.h>#include <stdio.h>#include <stdlib.h>#define STACK_FRAME_MAXSIZE 0x40000struct 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_RECORD rcd; CONTEXT ctx; __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: 01380000callstack: 1381086 1381161 138199e 746c339a 76fa9ef2 76fa9ec5 0 把这些输出地址 - 01380000 + 00400000 然后到mapfile里去查对应的函数, 得到 callstack 为: _foobar + 0006 _main + 0071如果你还想分析出 dll 里的函数名, 先把全部的dll模块枚举出来.这VS2010咋这么破, mapfile 里有些函数地址咋个是错误的, 与我在IDA里看的对不上.
[解决办法]
加上VMP,加大破解难度。
[解决办法]
转储堆栈就是把 异常时 ESP 附近的内容全保存下来, 比如保存 [ ESP , ESP + 64K ] 的内容, 有这些东西, 找保存下异常时后的 CONTEXT, 即使编译的时候木有用 -Oy- 选项, 也可以手工恢复栈帧, 就是比较麻烦的说, 也可以恢复出异常时各个局部变量的值...
转储模块信息就是 保存异常时候全部的DLL模块的基址, 不然不好恢复DLL里函数栈帧...
一般有下面的出错信息, 基本就可以恢复异常时候的程序状态:
1: 当前全部的寄存器值
2: 堆栈的转储信息
3: 全部模块加载的基地址
backtrace都可以直接用1,2的信息拿回来以后再做....