01概述编译阶段nm获取二进制文件包含的符号信息strings获取二进制文件包含的字符串常量strip去除二进制文件包含的符号readelf显示目标文件的详细信息objdump反汇编源码aspossiblecodeaddr2line根据地址找到代码行。gdb强大的调试工具ldd在运行阶段显示程序需要使用的动态库和实际使用的动态库。strace跟踪程序当前系统调用时间,内核态时间gprof显示用户态下各个函数的执行时间valgrind检查内存错误mtrace检查内存错误其他proc文件系统系统日志02编译阶段nm(获取包含的符号在二进制文件中)符号:函数,变量参数:-Cput将C++函数签名转换为可读形式-A列出符号名称时,还会显示它来自哪个文件。-a列出所有符号(这也会列出调试符号,默认情况下不会列出调试符号)-l列出源代码中符号对应的行号(指定该参数后,nm将使用调试信息找出文件名和符号的行号,对于已定义的符号,会找到符号定义的行号,对于未定义的符号,会显示为空)-n根据文件的地址排序symbol(默认是按符号名的字母顺序)-u只列出未定义的符号字符串(获取二进制文件中的字符串常量)功能:获取二进制文件中的字符串常量目的:检查KEY泄漏比较重要eg:strings|grep'^.\{16\}$'找出中是否有16个字符的行,并显示出来。选项:-a不仅扫描目标文件初始化和加载部分,还扫描整个文件。-f在显示字符串之前显示文件名。-nmin-len打印至少min-len个字符长的字符串。默认值为4。#字符串/lib/tls/libc.so.6|grepGLIBCGLIBC_2.0GLIBC_2.1GLIBC_2.1.1...这样就可以看到glibc支持的版本了。strip(去掉二进制文件中包含的符号)用途:可执行程序减肥(一般只在已经调试测试过的生成模块上,因为不能调试)反编译,反跟踪readelf(显示目标的详细信息file)nmprogram可用于枚举符号及其类型和值,但是,要更仔细地研究目标文件中这些命名部分的内容,需要更强大的工具。其中两个强大的工具是objdump和readelf。readelf工具是一种GNU工具,用于显示有关一个或多个ELF格式文件的信息。使用不同的参数查看ELF文件的不同信息。readelf-a显示所有ELF文件的信息-h显示ELF文件的文件头-l显示程序头(program-header)和程序段(segment)及段下面的部分-S显示更详细的部分information(section)-s显示符号信息,-n显示标识信息(如果有)-r显示重定位信息(如果有)-u显示扩展函数信息(如果有)-d显示动态段信息,一般为动态库信息objdump(虽然可以反汇编源码)objdump–S尽量反汇编源码,尤其是编译时指定了-g参数,效果更明显。addr2line(findcodelinebasedonaddress)当进程崩溃时,会在日志文件(/var/log/messages)中给出额外的信息,包括程序终止的原因、故障地址、程序状态字(PSW),通用寄存器和访问寄存器的简短寄存器转储。例如:Mar3111:34:28l02kernel:failingaddress:0如果可执行文件包含调试符号(使用-g编译),使用addr2line确定哪一行代码导致了问题。eg:addr2line–eexeaddr其实gdb也有这个功能,但是addr2line的好处是很多时候bug很难重现,我们只有一个crashlog。这样就可以通过addr2line找到对应的代码行,非常方便。注意:可执行程序用-g编译带调试信息。如果crash在so中,那么addr2line不能直接给出代码行。参数:-a显示函数名或文件行号前的地址-b指定二进制文件格式-C将C++符号解析为用户级名称,可以指定解析方式-e指定二进制文件-f并同时显示函数名-s仅显示文件的基名而不是完整路径-i展开内联函数-j读取相对于指定部分的偏移量而不是绝对地址-p在一行上显示每个位置03运行的常用步骤-timedebuggers:1、判断运行时间主要花在用户态还是内核态(比较土的方法:程序暂时屏蔽daemon()调用,hardcode收到n个请求后退出(0),计时程序...)。2、如果是用户态,使用gprof进行性能分析。3、如果是内核态,使用strace进行性能分析,也可以使用其他工具(如ltrace等)辅助。ldd(显示程序需要使用的动态库和实际使用的动态库)#ldd/bin/lslinux-gate.so.1=>(0xbfffe000)librt.so.1=>/lib/librt.so。1(0xb7f0a000)libacl.so.1=>/lib/libacl.so.1(0xb7f04000)libc.so.6=>/lib/libc.so.6(0xb7dc3000)libpthread.so.0=>/lib/libpthread.so.0(0xb7dab000)/lib/ld-linux.so.2(0xb7f1d000)libattr.so.1=>/lib/libattr.so.1(0xb7da6000)第一栏:需要使用什么库;第二列:实际使用哪个库文件;第三列:库文件的加载地址。如果缺少动态库,则不会有第二列。strace(跟踪当前系统调用)结果默认输出到2。-p``附加到一个进程-c最后统计每次系统调用的调用-T打印系统调用的调用时间-t/-tt/-ttt时间格式-f/-F跟踪fork/产生的调用vforksubprocess-o``,将strace的输出定向到文件。例如:strace-f-o~/-eexpr指定一个表达式来控制如何trace,格式如下:-eopen等同于-etrace=open,表示只有traceopen调用使用strace–e打开./prg可以很方便的查看程序使用了哪些配置文件或者日志文件。-etrace=``只跟踪指定的系统调用例如:-etrace=open,close,rean,write表示只跟踪这四个系统调用。-etrace=fileonly跟踪与文件操作相关的系统调用-etrace=process仅跟踪与进程控制相关的系统调用-etrace=network跟踪所有与网络相关的系统调用-estrace=signal跟踪所有与系统相关的系统调用signals-etrace=ipc跟踪所有与进程通信相关的系统调用ltrace(跟踪当前库函数)参数和strace时间很接近(查看程序执行时间,用户态时间,内核态时间)#timepsaux|grep'hi'1020218040.00.01888664pts/6S+17:460:00grephireal0m0.009suser0m0.000ssys0m0.004s注意:time只跟踪父进程,所以不能forkgprof(显示执行时间用户模式下的每个函数)gprof原理:在编译和链接程序时(使用-pg编译和链接选项),gcc为你的应用程序的每个函数添加一个名为mcount(或“_mcount”,或“__mcount”)的函数,也就是说-pg编译出的应用程序中的每一个函数都会调用mcount,mcount会在内存中保存一个函数调用图,通过函数调用栈找到子函数和父函数的地址。这个调用图还保存了所有与函数相关的调用时间、调用次数等信息。使用步骤:1.使用-pg编译链接应用程序gcc-pg-oexecexec.c如果需要库函数调用:gcc-lc_p-gp-oexecexec.c2.执行应用程序生成供gprof分析的gmon.out的数据3.使用gprof程序分析应用程序生成的数据gprofexecgmon.out>profile.txt注意:程序必须通过正常方式退出(exit(),主回归),击杀无效。后台驻留程序调试——我比较土的方法是屏蔽daemon()调用,程序硬编码收到n个请求后exit(0)。有时不太对。它只关心用户态的时间消耗,不关心内核态的消耗。gdbcoreexec(gdb查看core文件)准备生成core:启动程序前,ulimit-cunlimited,将core文件设置为无限大小。(反之,ulimit-c0可以阻止core文件的生成)默认情况下,在可执行程序的路径下,会生成一个名为core的文件,新的core会覆盖旧的。设置core文件名:/proc/sys/kernel/core_uses_pid可以控制生成的core文件的文件名是否加上pid作为扩展名,1为扩展名,否则为0。proc/sys/kernel/core_pattern可以设置格式化后的core文件的存放位置或文件名。例如原文件内容为core,修改为:echo"/data/core/core-%e-%p-%t">core_pattern下面是参数列表:%p-insertpidintofilenameaddpid%u-将当前uid插入文件名addcurrentuid%g-将当前gid插入文件名addcurrentgid%s-将导致核心转储的信号插入文件名add导致生成核心的信号%t-插入coredump发生的UNIX时间写入filename添加core文件生成的unix时间%h-inserthostnamewherethecoredumphappenedintofilename添加主机名%e-insertcoredumpingexecutablenameintofilename添加命令使用gdb查看core:gdbopprofile(查看CPU消耗在哪里)常用命令使用oprofile检测cpu使用情况,需要经过初始化、启动检测、导出检测数据、查看检测结果等步骤。以下是常用的oprofile命令。初始化opcontrol--no-vmlinux:指示oprofile开始检测后,不记录内核模块和内核代码相关统计信息opcontrol--init:加载oprofile模块,oprofile驱动检测控制opcontrol--start:指示oprofile开始检测opcontrol--dump:指示将oprofile检测到的数据写入文件opcontrol--reset:清除之前检测到的数据记录opcontrol-h:关闭oprofile进程查看检测结果opreport:从镜像角度显示检测结果(image),process,dynamiclibrary,kernelmodule属于镜像类别opreport-l:从函数的角度显示测试结果opreport-ltest:从函数的角度显示测试进程opannotate的测试结果functionopannotate-stest:从代码的角度显示测试过程opannotate的测试结果-s/lib64/libc-2.4.so:从代码的角度,显示libc-2.4.so库linux的测试结果#opreportCPU:核心2,速度2128.07MHz(估计)计数CPU_CLK_UNHALTED事件(未暂停时的时钟周期),单位掩码为0x00(未暂停的核心周期)计数100000CPU_CLK_UNHALT......|样品|%|----------------------3164571987.6453no-vmlinux436111310.3592libend.so76830.1367libpython2.4.so.1.070460.1253op_testvalgrind(检查内存错误)使用步骤:1.从官网下载并安装valgrind。2、所有用-g编译的程序都可以使用。官网的示例代码test.c#includevoidf(void){int*x=malloc(10*sizeof(int));x[10]=0;//问题1:堆块溢出}//问题2:内存泄漏--xnotfreedintmain(void){f();return0;}编译程序gcc-Wall-g-otesttest.c3,用valgrind启动程序,在屏幕上输出结果。valgrind--tool=memcheck--leak-check=full./test注意:valgrind只能查找堆内存中的访问错误,而不能对堆栈上的对象和静态对象做任何事情。Valgrind会影响进程的性能。据说可能会慢20倍。因此,在性能要求较高的情况下,只能使用mtrace这样的轻量级工具(但mtrace只能识别简单的内存错误)。如果程序生成的core的栈乱了,那基本就是stackoverflow了。这种情况可以通过在编译时加上-fstack-protector-all和-D_FORTIFY_SOURCE=2来检测。stack-protector-all会给每个函数加上栈保护代码,并在栈上留下指纹。(记录,没用过)因为valgrind无法检查stack和staticobject的内存访问是否越界,所以这类问题可以使用gcc的-fmudflap–lmudflap来检测。(记录,没用过)全局变量类型不一致的问题,现在找到了更好的方法,从另一个方面说明全局对象不是一个好的设计,给调试带来麻烦。mtrace(checkmemoryerrors)mtrace是glibc中提供的一个工具,原理很简单,就是去掉你程序中所有malloc()和free()的位置,最后两个成对出现,没有配对是内存泄漏。使用步骤如下:1.添加mtrace()#include#includeintmain(void){int*p;inti;#ifdefDEBUGsetenv("MALLOC_TRACE","./memleak.log",1);mtrace();#endifp=(int*)malloc(1000);return0;}这段代码分配了一个空间,但没有释放它。我们在第9-12行添加mtrace调用。2、编译gcc-g-DDEBUG-otest1test1.c3,执行./test1,会在目录下找到./memleak.log。4.使用mtracememleak.log查看信息。#mtracetest1memleak.log-0x0804a008Free3wasneveralloc'd0xb7e31cbe-0x0804a100Free4wasneveralloc'd0xb7ec3e3f-0x0804a120Free5wasneveralloc'd0xb7ec3e47Memory-not-----释放:------AddressSizeCaller0x0804a4a80x3e8at/home/illidanliu/test1.c:14可以看到test1.c没有对应的free()。04Windows用于其他proc文件系统内核。proc文件系统是一个伪文件系统,存在于内存中,不占用外存空间。用户和应用程序可以通过proc获取系统信息,可以改变内核的一些参数。proc/directorystructure(part):cmdline内核命令行cpuinfo关于CPU信息devicesavailabledevices(blockdevice/characterdevice)filesystemssupportedfilesysteminterruptsuseofinterruptsioportsuseofI/Oportskcore内核镜像kmsg内核信息meminfo 内存信息mounts加载的文件系统stat综合统计状态表swapsswap空间利用率version内核版本uptimeSystemuptimenet网络信息sys可写,可以通过它访问或修改内核参数proc//目录结构(部分):cmdline命令行parameterenviron环境变量值fd包含所有文件描述符的目录mem进程的内存使用情况stat进程状态status链接到本进程根目录systemlog/var/log/下的日志文件:/var/log/messages系统整体信息,其中还包括系统启动时的日志。另外,var/log/messages日志中还记录了mail、cron、daemon、kern、auth等内容。/var/log/auth.log系统授权信息,包括用户登录和使用的权限机制。/var/log/boot.log系统启动时的日志。/var/log/daemon.log各种系统后台守护进程日志信息。/var/log/lastlog记录所有用户的最新信息。这不是一个ASCII文件,所以你需要使用lastlog命令来查看内容。/var/log/user.log记录各级用户信息的日志。/var/log/cron每当cron进程启动一个作业时,相关信息就会记录在这个文件中。/var/log/wtmp或utmp登录信息。/var/log/faillog用户登录失败信息。此外,错误的登录命令也会记录在该文件中。以上就是良虚教程网为各位小伙伴分享的Linux后台开发常用调试工具。以上就是良序教程网为各位小伙伴们分享的Linux相关知识。