Debug是啥?

「DEBUG」是计算机「排除故障」的意思。马克2号(Harvard Mark II)编制程序的格蕾丝·霍珀(Grace Hopper)是一位美国海军准将及计算机科学家,同时也是世界最早的一批程序设计师之一。有一天,她在调试设备时出现故障,拆开继电器后,发现有只飞蛾被夹扁在触点中间,从而“卡”住了机器的运行。于是,霍珀诙谐地把程序故障统称为“臭虫(BUG)”,把排除程序故障叫DEBUG,而这奇怪的“称呼”,竟成为后来计算机领域的专业行话。

Release,英文翻译就是'发布'的意思

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。

「Release」 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。

「对于初学者最疑惑的问题就是:我刚运行没问题,发给我同学在怎么就跑步起来呢,恼火、、」

这个问题就是你给别人 Debug 版本,而 Debug 版本带了一些调试信息,这可能会调用一些 dll 文件动态加载,而直接发送到其他主机结果可想而知,运行报错...

解决办法就是生成 Release 版本。当然如果你想让程序拥有一个安装流程,你可以看下以前的推送。

程序打包教程

Windows 下 debug 和 release 怎么区分,相信用过VS的你已经知道了,那 Linux 下有 debug 和 release 的区别吗?

答案是有的,那我们来实验证明一下:

测试代码:

#include<stdio.h>
int fun(const char *src,const char *dest)
{
    int ret = strcmp(src,dest);
    return ret;
}
int main()
{
    char password[20] = "123456";
    int ret = fun("123456",password);
    if(ret==0)
        printf("logo in\n");
    else
        printf("logo fail\n");
    return 0;
}

代码很简单,一个登陆判断函数 fun() 和主函数 main()

我们用 -g 选项编译一下

gcc -g -o test-debug test.c

去掉 -g 选项再编译一下

gcc -o test-debug-temp test.c

我们来比较一下他们的大小

deroy@ubuntu:~/deroy$ ls -l
total 28
-rw-r--r-- 1 deroy deroy   264 Jan 25 05:57 test.c
-rwxr-xr-x 1 deroy deroy 11120 Jan 25 06:00 test-debug
-rwxr-xr-x 1 deroy deroy  8424 Jan 25 06:01 test-debug-temp

不加 -g 足足少了2696B,少掉的那部分是什么呢,如果你了解过 gdb 那你就知道少掉的那部分是源码调试信息。

你以为不就 -g 选项就是 release 版本了吗?天真

我们用readelf -s命令来查看一下不加 -g 选项能看到什么,这个命令是用来查看二进制信息的,也可以查看符号表。

deroy@ubuntu:~/deroy$ readelf -s test-debug-temp
......
5000000000000006fa    43 FUNC    GLOBAL DEFAULT   14 fun
......
610000000000000725   134 FUNC    GLOBAL DEFAULT   14 main
......
650000000000000580     0 FUNC    GLOBAL DEFAULT   11 _init

「我的fun函数怎么暴露了、」

我们将程序里面的「符号表」去掉,来看下「release」版本

objcopy --strip-debug test-debug-temp test-release

啥也别说,先比「大小」

deroy@ubuntu:~/deroy$ ls -l
total 40
-rw-r--r-- 1 deroy deroy   264 Jan 25 05:57 test.c
-rwxr-xr-x 1 deroy deroy 11120 Jan 25 06:00 test-debug
-rwxr-xr-x 1 deroy deroy  8424 Jan 25 06:01 test-debug-temp
-rwxr-xr-x 1 deroy deroy  8312 Jan 25 06:10 test-release

就只少了112 B,感觉readelf -s还是会暴露我们的函数名称和地址

deroy@ubuntu:~/deroy$ readelf -s test-debug-temp 
......
50: 00000000000006fa    43 FUNC    GLOBAL DEFAULT   14 fun
......
61: 0000000000000725   134 FUNC    GLOBAL DEFAULT   14 main
......
65: 0000000000000580     0 FUNC    GLOBAL DEFAULT   11 _init

果不其然,没关系,我们还有终级绝招

再次strip深度清除符号表

strip test-release

什么都别说先看大小

deroy@ubuntu:~/deroy$ ls -l
total 36
-rw-r--r-- 1 deroy deroy   264 Jan 25 05:57 test.c
-rwxr-xr-x 1 deroy deroy 11120 Jan 25 06:00 test-debug
-rwxr-xr-x 1 deroy deroy  8424 Jan 25 06:01 test-debug-temp
-rwxr-xr-x 1 deroy deroy  6120 Jan 25 06:12 test-release

比 debug 版本足足少了 5k,再次查看符号表

deroy@ubuntu:~/deroy$ readelf -s test-release 

Symbol table '.dynsym' contains 9 entries:
Num:    Value          Size Type    Bind   Vis      Ndx Name
0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)
3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@GLIBC_2.4 (3)
4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@GLIBC_2.2.5 (2)
6: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
7: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
8: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)

你几乎什么都看不到,想破解这个程序难上加难。