使用 objcopy:
1转载出处:
https://unpluggedcoder.me/2014/04/24/%E7%94%9F%E6%88%90%E5%8F%AF%E8%B0%83%E8%AF%95%E7%9A%84Release%E7%89%88%E6%9C%AC%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6--%E8%B0%83%E8%AF%95%E7%AC%A6%E5%8F%B7%E4%BF%A1%E6%81%AF%E6%8F%90%E5%8F%96%E5%92%8C%E9%99%84%E5%8A%A0%E8%B0%83%E8%AF%95%E9%93%BE%E6%8E%A5section/index.html
原文作者:不插电码农
本文讲的是不编译完全release的可执行文件,而是使用cmake的RelWithDebugInfo(附加调试信息的编译,它的效果下面会说明)或者Debug编译也可以生成release版本的可执行文件进行调试. 详细的 cmake 使用会在下一篇文章里讲. 这里先记下Debug, Release 和 RelWithDebugInfo的区别(对比我手上的gcc 4.8.2编译出的不同版本得出的结论) Debug 等同于 -O0 -g 编译选项, 不优化代码, 附加调试信息 Release 等同于 -O3 编译选项, 最大化优化代码, 但不包含调试信息 RelWithDebugInfo 等同于 -O2 -g 编译选项, 中等程度优化代码, 并且包含调试信息. 可以自定义使用-O3 -g 的编译选项,来生成最接近Release的代码(至于-ggdb的选项,加了以后二进制只大了8个字节,目测无所谓) 下面的方法只对-g编译有效,方法有两种. man手册里推荐的方法 objcopy –only-keep-debug foo foo.dbg 把调试信息(即debug section)dump到单独的文件里. objcopy –strip-debug foo 这里只剔除调试信息,符号信息仍保留(用户依然可以用nm查看到各种函数符号,我推荐用–strip-all,连同符号信息一起删除,生成的可执行文件更小,不影响调试) objcopy –add-gnu-debuglink=foo.dbg foo 为foo添加.gnu-debuglink section, 这个会让二进制增加近100字节的样子. 这样分离了Debug Section后,就可以单独分发release版本的foo,调试时只需讲foo.dbg放在和foo同一目录下即可直接gdb foo进行调试. 如果不希望Release的最终二进制文件包含.gnu-debuglink段,那么可以直接省略第三步,且当成另一种方法,方便叙述. 同一 strip foo 这个效果等同于objcopy –strip-all foo,剔除所有符号和调试信息, 即为release版本. 方法二所不同的调试方法是需先加载dbg文件, gdb foo.dbg, 然后attach(或者exec)到foo进程,这样不要求.dbg和执行程序在同一个目录下,并且适合调试已经启动的进程,例如服务器.
2 测试
测试demo:CMakeLists.txt
cmake_minimum_required(VERSION 3.5) # set the project name project(test_EXE) SET(CMAKE_BUILD_TYPE Release) set(CMAKE_CXX_FLAGS_DEBUG "-g") set(CMAKE_C_FLAGS_DEBUG "-g") set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -DNDEBUG") set(CMAKE_C_FLAGS_RELEASE "-g -O3 -DNDEBUG") MESSAGE("Build type: " ${CMAKE_BUILD_TYPE}) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) add_executable(test_EXE test.cpp ) add_custom_command(TARGET test_EXE POST_BUILD COMMAND objcopy --only-keep-debug ${EXECUTABLE_OUTPUT_PATH}/test_EXE ${EXECUTABLE_OUTPUT_PATH}/test_EXE.debug COMMAND objcopy --strip-all ${EXECUTABLE_OUTPUT_PATH}/test_EXE COMMAND objcopy --add-gnu-debuglink=${EXECUTABLE_OUTPUT_PATH}/test_EXE.debug ${EXECUTABLE_OUTPUT_PATH}/test_EXE COMMENT "**** test cmake command: add_custom_command" ) # 添加自定义目标,以便在构建过程中执行自定义命令 install(FILES ${EXECUTABLE_OUTPUT_PATH}/test_EXE.debug DESTINATION ${EXECUTABLE_OUTPUT_PATH})
#include <stdio.h> #include <iostream> #include <chrono> #include <thread> void PrintInfo() { printf("load fun print info..........\n"); } int addfun(int a ,int b) { printf("will run a+b:%d\n",(a+b)); return a+b; } int main(void) { int a=3,b=5; PrintInfo(); int c = addfun(a,b); printf("-----print a+b ok\n"); while(1) { static int c =0; static int d =1; addfun(c,d); c++; d++; std::this_thread::sleep_for(std::chrono::seconds(1)); //Ãë } return 0; }
测试的时候使用cmake -DCMAKE_BUILD_TYPE=Release生成Makefile,然后输入make命令生成exe;注意这些操作要在root下,否则会出现无法调试,如continue的时候出现 the program is not running等;
自测程序如果top 找不到Pid,请用pidof命令查找
编译exe:
sudo 运行:
我们先看没有符号表的,就是在文件夹中只有test_EXE,没有调试debug文件的:
可以看到pidof test_EXE,然后gdb attach pid后,打断点根本不会停;
然后我们把刚刚一起编译的test_EXE.debug放到同一个目录下(不用重启程序,因为实际情况下,一般都是项目运行中如果出错,你重启程序编译debug调试,或者重启添加debug符号,现象有可能就无法出现了,我们就是要在出错的release版本下,添加符号直接调试)
调试:
综上就可以同时编译release以及剥离出来的debug调试信息,如果现场遇到需要调试的情况就可以直接把debug文件放进运行目录,在线调试,而不必停止程序的运行;
标签:EXE,编译,debug,test,调试信息,linux,release,foo From: https://www.cnblogs.com/8335IT/p/18079295