读书人

VC编译Release程序怎么在不生成debu

发布时间: 2012-08-28 12:37:01 作者: rapoo

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

[解决办法]

探讨

引用:
引用:

不生成pdb?

那么要看反汇编猜

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


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


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

生成pdb,你别把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的信息拿回来以后再做....

读书人网 >C++

热点推荐