首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

VC编译Release程序,怎么在不生成debug信息(pdb文件)情况下处理崩溃

2013-03-26 
VC编译Release程序,如何在不生成debug信息(pdb文件)情况下处理崩溃如题,VC编译Release程序,如果生成debug

VC编译Release程序,如何在不生成debug信息(pdb文件)情况下处理崩溃
如题,VC编译Release程序,如果生成debug信息,就可以获取dump文件,如何在不生成debug信息(pdb文件)、并进行优化的情况下处理崩溃呢,先说声谢谢!!
[解决办法]

引用:
引用:
引用:

不生成pdb?

那么要看反汇编猜

为啥不用pdb,想不通你要干啥


其他用手动传统调试亦可,比如用printf/cout输出信息来判断


喔,我不想生成pdb是想防止程序被别人反编译,有没其他更好的办法?

生成pdb,你别把pdb文件给最终用户不就行了?


即使给最终用户,也很难反编译

Windows的dll的pdb可都是公开的
[解决办法]
一个最简单的例子, linux下的就不写了, 比这个方便一些..

比如最简单的个测试:

#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里看的对不上.



[解决办法]
加上VMP,加大破解难度。
[解决办法]
转储堆栈就是把 异常时 ESP 附近的内容全保存下来, 比如保存 [ ESP , ESP + 64K ] 的内容, 有这些东西, 找保存下异常时后的 CONTEXT, 即使编译的时候木有用 -Oy- 选项, 也可以手工恢复栈帧, 就是比较麻烦的说, 也可以恢复出异常时各个局部变量的值...



转储模块信息就是 保存异常时候全部的DLL模块的基址, 不然不好恢复DLL里函数栈帧...

一般有下面的出错信息, 基本就可以恢复异常时候的程序状态:

1: 当前全部的寄存器值
2: 堆栈的转储信息
3: 全部模块加载的基地址

backtrace都可以直接用1,2的信息拿回来以后再做....

热点排行