linux程序分析工具
ldd和nm是Linux下两个非常实用的程序分析工具。ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具,objdump用来查看源代码与汇编代码,-d只查看汇编代码,-S查看c和汇编代码。
1 1 #include <stdio.h> 2 2 #include <stdlib.h> 3 3 #include <unistd.h> 4 4 5 5 int global = 1; 6 6 7 7 int main(int argc, char **argv) 8 8 { 9 9 pid_t pid; 10 10 int stack = 1; 11 11 int *heap; 12 12 13 13 heap = (int*)malloc(sizeof(int)); 14 14 *heap = 2; 15 15 16 16 pid = fork(); 17 17 if(pid < 0){ 18 18 perror("fail to fork"); 19 19 exit(-1); 20 20 }else{ 21 21 if(0 == pid){ 22 22 global++; 23 23 stack++; 24 24 (*heap)++; 25 25 26 26 printf("In sub-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap); 27 27 exit(0); 28 28 }else{ 29 29 sleep(2); 30 30 printf("In parent-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap); 31 31 } 32 32 } 33 33 34 34 return 0; 35 35 }
源代码如上边所示,偷懒,直接使用了别人的代码。
1、使用命令:gcc -g tooltest.c -o tooltest 编译源码生成可执行文件tooltest
2、使用命令:ldd tooltest 其中ldd工具用来分析程序运行时需要依赖的动态链接库
3、使用命令:nm tooltest 其中nm工具用来查看指定程序中的符号表信息
4、使用命令:objdump -S tooltest 其中objdump工具用来查看C源代码与汇编代码
补充如下:
1、ldd
格式:ldd [options] file
功能:列出file运行所需的共享库
参数:
-d 执行重定位并报告所有丢失的函数
-r 执行对函数和对象的重定位并报告丢失的任何函数或对象
1 munication ~ ldd tooltest 2 linux-gate.so.1 (0xb77c5000) 3 libc.so.6 => /usr/lib/libc.so.6 (0xb75b2000) 4 /lib/ld-linux.so.2 (0xb77c7000)
上边是ldd的输出结果,将其分为3列来看:
■ 第一列:程序需要依赖什么库
■ 第二列:系统提供的与程序需要的库对应的库名称
■ 第三列:依赖库加载的开始地址
通过上面的这些信息,我们可以总结出下面的用途:
(1) 通过对比第一列和第二列,我们可以知道程序需要的动态链接库和系统实际提供的是否相比配。
(2) 通过第三列,我们可以知道当前动态链接库中的符号在进程地址空间中的起始位置。
2、nm
格式:nm [options] file
功能:列出file中的所有符号
参数:
-C 将符号转化为用户级的名字
-s 当用于.a文件即静态库时,输出把符号名映射到定义该符号的模块或成员名的索引
-u 显示在file外定义的符号或没有定义的符号
-l 显示每个符号的行号,或为定义符号的重定义项
1 munication ~ nm tooltest 2 00002034 B __bss_start 3 00002034 b completed.6576 4 w __cxa_finalize@@GLIBC_2.1.3 5 00002028 D __data_start 6 00002028 W data_start 7 00000540 t deregister_tm_clones 8 000005d0 t __do_global_dtors_aux 9 00001ef8 t __do_global_dtors_aux_fini_array_entry 10 0000202c D __dso_handle 11 00001efc d _DYNAMIC 12 00002034 D _edata 13 00002038 B _end 14 U exit@@GLIBC_2.0 15 00000788 T _fini 16 U fork@@GLIBC_2.0 17 0000079c R _fp_hw 18 00000620 t frame_dummy 19 00001ef4 t __frame_dummy_init_array_entry 20 00000950 r __FRAME_END__ 21 00002030 D global 22 00002000 d _GLOBAL_OFFSET_TABLE_ 23 w __gmon_start__ 24 0000081c r __GNU_EH_FRAME_HDR 25 00000430 T _init 26 00001ef8 t __init_array_end 27 00001ef4 t __init_array_start 28 000007a0 R _IO_stdin_used 29 w _ITM_deregisterTMCloneTable 30 w _ITM_registerTMCloneTable 31 00000780 T __libc_csu_fini 32 00000720 T __libc_csu_init 33 U __libc_start_main@@GLIBC_2.0 34 0000062d T main 35 U malloc@@GLIBC_2.0 36 U perror@@GLIBC_2.0 37 U printf@@GLIBC_2.0 38 00000580 t register_tm_clones 39 U sleep@@GLIBC_2.0 40 000004f0 T _start 41 00002034 D __TMC_END__ 42 00000530 T __x86.get_pc_thunk.bx 43 00000629 T __x86.get_pc_thunk.dx 44 00000782 T __x86.get_pc_thunk.si
上面便是tooltest这个程序中所有的符号,首先介绍一下上面输出内容的格式:
■ 第一列:当前符号的地址。
■ 第二列:当前符号的类型(关于类型的说明,可以查看手册页man nm详细阅读)。
■ 第三列:当前符号的名称。
使用nm主要有一下几个方面的帮助:
(1) 判断指定的程序中有没有指定的符号,比较常用的方式为:nm –C program | grep symbol
(2) 解决程序编译时undefined reference的错误,以及multiple definition的错误。
(3) 查看某个符号的地址,以及在进程空间的大概位置(.bss, .data, .text段,具体可以通过第二列的类型来判断)。
显示结果的符号如下:
部分符号类型说明
A : 该符号的值是绝对的,在以后的链接过程中,不允许进行改变。这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。
B : 该符号的值出现在非初始化数据段(.bss)中。例如,在一个文件中定义全局static int test。则该符号test的类型为b,位于bss section中。其值表示该符号在bss段中的偏移。一般而言,bss段分配于RAM中 。
C : 该符号为common。common symbol是未初始话数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示该符号需要的字节数。例如在一个c文件中,定义int test,并且该符号在别的地方会被引用,则该符号类型即为C。否则其类型为B。
D : 该符号位于初始化数据段中。一般来说,分配到.data section中。例如定义全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},则会分配于初始化数据段中。
G : 该符号也位于初始化数据段中。主要用于small object提高访问small data object的一种方式。
I : 该符号是对另一个符号的间接引用。
N : 该符号是一个debugging符号。
R : 该符号位于只读数据段。例如定义全局const int test[] = {123, 123};则test就是一个只读数据区的符号。注意在cygwin下如果使用gcc直接编译成MZ格式时,源文件中的test对应_test,并且其符号类型为D,即初始化数据段中。但是如果使用m6812-elf-gcc这样的交叉编译工具,源文件中的test对应目标文件的test,即没有添加下划线,并且其符号类型为R。一般而言,位于rodata section。值得注意的是,如果在一个函数中定义const char *test = “abc”, const char test_int = 3。使用nm都不会得到符号信息,但是字符串“abc”分配于只读存储器中,test在rodata section中,大小为4。
S : 符号位于非初始化数据段,用于small object。
T : 该符号位于代码段text section。
U : 该符号在当前文件中是未定义的,即该符号的定义在别的文件中。例如,当前文件调用另一个文件中定义的函数,在这个被调用的函数在当前就是未定义的;但是在定义它的文件中类型是T。但是对于全局变量来说,在定义它的文件中,其符号类型为C,在使用它的文件中,其类型为U。
V : 该符号是一个weak object。
W : The symbol is a weak symbol that has not been specifically tagged as a weak object symbol.
- : 该符号是a.out格式文件中的stabs symbol。
? : 该符号类型没有定义。
3、objdump
格式:objdump [options] file
功能:列出file运行所需的共享库
参数:
-s 只是显示汇编源码
-S 同时显示汇编和C语言代码
1 munication ~ objdump -S tooltest 2 3 tooltest: 文件格式 elf32-i386 4 5 6 Disassembly of section .init: 7 8 00000430 <_init>: 9 430: 53 push %ebx 10 431: 83 ec 08 sub $0x8,%esp 11 434: e8 f7 00 00 00 call 530 <__x86.get_pc_thunk.bx> 12 439: 81 c3 c7 1b 00 00 add $0x1bc7,%ebx 13 43f: 8b 83 f4 ff ff ff mov -0xc(%ebx),%eax 14 445: 85 c0 test %eax,%eax 15 447: 74 05 je 44e <_init+0x1e> 16 449: e8 9a 00 00 00 call 4e8 <.plt.got+0x8> 17 44e: 83 c4 08 add $0x8,%esp 18 451: 5b pop %ebx 19 452: c3 ret 20 21 Disassembly of section .plt: 22 23 00000460 <.plt>: 24 460: ff b3 04 00 00 00 pushl 0x4(%ebx) 25 466: ff a3 08 00 00 00 jmp *0x8(%ebx) 26 46c: 00 00 add %al,(%eax) 27 ... 28 29 00000470 <printf@plt>: 30 470: ff a3 0c 00 00 00 jmp *0xc(%ebx) 31 476: 68 00 00 00 00 push $0x0 32 47b: e9 e0 ff ff ff jmp 460 <.plt> 33 34 00000480 <sleep@plt>: 35 480: ff a3 10 00 00 00 jmp *0x10(%ebx) 36 486: 68 08 00 00 00 push $0x8 37 48b: e9 d0 ff ff ff jmp 460 <.plt> 38 39 00000490 <perror@plt>: 40 490: ff a3 14 00 00 00 jmp *0x14(%ebx) 41 496: 68 10 00 00 00 push $0x10 42 49b: e9 c0 ff ff ff jmp 460 <.plt> 43 44 000004a0 <malloc@plt>: 45 4a0: ff a3 18 00 00 00 jmp *0x18(%ebx) 46 4a6: 68 18 00 00 00 push $0x18 47 4ab: e9 b0 ff ff ff jmp 460 <.plt> 48 49 000004b0 <exit@plt>: 50 4b0: ff a3 1c 00 00 00 jmp *0x1c(%ebx) 51 4b6: 68 20 00 00 00 push $0x20 52 4bb: e9 a0 ff ff ff jmp 460 <.plt> 53 54 000004c0 <__libc_start_main@plt>: 55 4c0: ff a3 20 00 00 00 jmp *0x20(%ebx) 56 4c6: 68 28 00 00 00 push $0x28 57 4cb: e9 90 ff ff ff jmp 460 <.plt> 58 59 000004d0 <fork@plt>: 60 4d0: ff a3 24 00 00 00 jmp *0x24(%ebx) 61 4d6: 68 30 00 00 00 push $0x30 62 4db: e9 80 ff ff ff jmp 460 <.plt> 63 64 Disassembly of section .plt.got: 65 66 000004e0 <.plt.got>: 67 4e0: ff a3 f0 ff ff ff jmp *-0x10(%ebx) 68 4e6: 66 90 xchg %ax,%ax 69 4e8: ff a3 f4 ff ff ff jmp *-0xc(%ebx) 70 4ee: 66 90 xchg %ax,%ax 71 72 Disassembly of section .text: 73 74 000004f0 <_start>: 75 4f0: 31 ed xor %ebp,%ebp 76 4f2: 5e pop %esi 77 4f3: 89 e1 mov %esp,%ecx 78 4f5: 83 e4 f0 and $0xfffffff0,%esp 79 4f8: 50 push %eax 80 4f9: 54 push %esp 81 4fa: 52 push %edx 82 4fb: e8 22 00 00 00 call 522 <_start+0x32> 83 500: 81 c3 00 1b 00 00 add $0x1b00,%ebx 84 506: 8d 83 80 e7 ff ff lea -0x1880(%ebx),%eax 85 50c: 50 push %eax 86 50d: 8d 83 20 e7 ff ff lea -0x18e0(%ebx),%eax 87 513: 50 push %eax 88 514: 51 push %ecx 89 515: 56 push %esi 90 516: ff b3 f8 ff ff ff pushl -0x8(%ebx) 91 51c: e8 9f ff ff ff call 4c0 <__libc_start_main@plt> 92 521: f4 hlt 93 522: 8b 1c 24 mov (%esp),%ebx 94 525: c3 ret 95 526: 66 90 xchg %ax,%ax 96 528: 66 90 xchg %ax,%ax 97 52a: 66 90 xchg %ax,%ax 98 52c: 66 90 xchg %ax,%ax 99 52e: 66 90 xchg %ax,%ax 100 101 00000530 <__x86.get_pc_thunk.bx>: 102 530: 8b 1c 24 mov (%esp),%ebx 103 533: c3 ret 104 534: 66 90 xchg %ax,%ax 105 536: 66 90 xchg %ax,%ax 106 538: 66 90 xchg %ax,%ax 107 53a: 66 90 xchg %ax,%ax 108 53c: 66 90 xchg %ax,%ax 109 53e: 66 90 xchg %ax,%ax 110 111 00000540 <deregister_tm_clones>: 112 540: e8 e4 00 00 00 call 629 <__x86.get_pc_thunk.dx> 113 545: 81 c2 bb 1a 00 00 add $0x1abb,%edx 114 54b: 8d 8a 34 00 00 00 lea 0x34(%edx),%ecx 115 551: 8d 82 34 00 00 00 lea 0x34(%edx),%eax 116 557: 39 c8 cmp %ecx,%eax 117 559: 74 1d je 578 <deregister_tm_clones+0x38> 118 55b: 8b 82 ec ff ff ff mov -0x14(%edx),%eax 119 561: 85 c0 test %eax,%eax 120 563: 74 13 je 578 <deregister_tm_clones+0x38> 121 565: 55 push %ebp 122 566: 89 e5 mov %esp,%ebp 123 568: 83 ec 14 sub $0x14,%esp 124 56b: 51 push %ecx 125 56c: ff d0 call *%eax 126 56e: 83 c4 10 add $0x10,%esp 127 571: c9 leave 128 572: c3 ret 129 573: 90 nop 130 574: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi 131 578: f3 c3 repz ret 132 57a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi 133 134 00000580 <register_tm_clones>: 135 580: e8 a4 00 00 00 call 629 <__x86.get_pc_thunk.dx> 136 585: 81 c2 7b 1a 00 00 add $0x1a7b,%edx 137 58b: 55 push %ebp 138 58c: 8d 8a 34 00 00 00 lea 0x34(%edx),%ecx 139 592: 8d 82 34 00 00 00 lea 0x34(%edx),%eax 140 598: 29 c8 sub %ecx,%eax 141 59a: 89 e5 mov %esp,%ebp 142 59c: 53 push %ebx 143 59d: c1 f8 02 sar $0x2,%eax 144 5a0: 89 c3 mov %eax,%ebx 145 5a2: 83 ec 04 sub $0x4,%esp 146 5a5: c1 eb 1f shr $0x1f,%ebx 147 5a8: 01 d8 add %ebx,%eax 148 5aa: d1 f8 sar %eax 149 5ac: 74 14 je 5c2 <register_tm_clones+0x42> 150 5ae: 8b 92 fc ff ff ff mov -0x4(%edx),%edx 151 5b4: 85 d2 test %edx,%edx 152 5b6: 74 0a je 5c2 <register_tm_clones+0x42> 153 5b8: 83 ec 08 sub $0x8,%esp 154 5bb: 50 push %eax 155 5bc: 51 push %ecx 156 5bd: ff d2 call *%edx 157 5bf: 83 c4 10 add $0x10,%esp 158 5c2: 8b 5d fc mov -0x4(%ebp),%ebx 159 5c5: c9 leave 160 5c6: c3 ret 161 5c7: 89 f6 mov %esi,%esi 162 5c9: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi 163 164 000005d0 <__do_global_dtors_aux>: 165 5d0: 55 push %ebp 166 5d1: 89 e5 mov %esp,%ebp 167 5d3: 53 push %ebx 168 5d4: e8 57 ff ff ff call 530 <__x86.get_pc_thunk.bx> 169 5d9: 81 c3 27 1a 00 00 add $0x1a27,%ebx 170 5df: 83 ec 04 sub $0x4,%esp 171 5e2: 80 bb 34 00 00 00 00 cmpb $0x0,0x34(%ebx) 172 5e9: 75 27 jne 612 <__do_global_dtors_aux+0x42> 173 5eb: 8b 83 f0 ff ff ff mov -0x10(%ebx),%eax 174 5f1: 85 c0 test %eax,%eax 175 5f3: 74 11 je 606 <__do_global_dtors_aux+0x36> 176 5f5: 83 ec 0c sub $0xc,%esp 177 5f8: ff b3 2c 00 00 00 pushl 0x2c(%ebx) 178 5fe: e8 dd fe ff ff call 4e0 <.plt.got> 179 603: 83 c4 10 add $0x10,%esp 180 606: e8 35 ff ff ff call 540 <deregister_tm_clones> 181 60b: c6 83 34 00 00 00 01 movb $0x1,0x34(%ebx) 182 612: 8b 5d fc mov -0x4(%ebp),%ebx 183 615: c9 leave 184 616: c3 ret 185 617: 89 f6 mov %esi,%esi 186 619: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi 187 188 00000620 <frame_dummy>: 189 620: 55 push %ebp 190 621: 89 e5 mov %esp,%ebp 191 623: 5d pop %ebp 192 624: e9 57 ff ff ff jmp 580 <register_tm_clones> 193 194 00000629 <__x86.get_pc_thunk.dx>: 195 629: 8b 14 24 mov (%esp),%edx 196 62c: c3 ret 197 198 0000062d <main>: 199 #include <unistd.h> 200 201 int global = 1; 202 203 int main(int argc, char **argv) 204 { 205 62d: 8d 4c 24 04 lea 0x4(%esp),%ecx 206 631: 83 e4 f0 and $0xfffffff0,%esp 207 634: ff 71 fc pushl -0x4(%ecx) 208 637: 55 push %ebp 209 638: 89 e5 mov %esp,%ebp 210 63a: 53 push %ebx 211 63b: 51 push %ecx 212 63c: 83 ec 10 sub $0x10,%esp 213 63f: e8 ec fe ff ff call 530 <__x86.get_pc_thunk.bx> 214 644: 81 c3 bc 19 00 00 add $0x19bc,%ebx 215 pid_t pid; 216 int stack = 1; 217 64a: c7 45 ec 01 00 00 00 movl $0x1,-0x14(%ebp) 218 int *heap; 219 220 heap = (int*)malloc(sizeof(int)); 221 651: 83 ec 0c sub $0xc,%esp 222 654: 6a 04 push $0x4 223 656: e8 45 fe ff ff call 4a0 <malloc@plt> 224 65b: 83 c4 10 add $0x10,%esp 225 65e: 89 45 f0 mov %eax,-0x10(%ebp) 226 *heap = 2; 227 661: 8b 45 f0 mov -0x10(%ebp),%eax 228 664: c7 00 02 00 00 00 movl $0x2,(%eax) 229 230 pid = fork(); 231 66a: e8 61 fe ff ff call 4d0 <fork@plt> 232 66f: 89 45 f4 mov %eax,-0xc(%ebp) 233 if(pid < 0){ 234 672: 83 7d f4 00 cmpl $0x0,-0xc(%ebp) 235 676: 79 1c jns 694 <main+0x67> 236 perror("fail to fork"); 237 678: 83 ec 0c sub $0xc,%esp 238 67b: 8d 83 a4 e7 ff ff lea -0x185c(%ebx),%eax 239 681: 50 push %eax 240 682: e8 09 fe ff ff call 490 <perror@plt> 241 687: 83 c4 10 add $0x10,%esp 242 exit(-1); 243 68a: 83 ec 0c sub $0xc,%esp 244 68d: 6a ff push $0xffffffff 245 68f: e8 1c fe ff ff call 4b0 <exit@plt> 246 }else{ 247 if(0 == pid){ 248 694: 83 7d f4 00 cmpl $0x0,-0xc(%ebp) 249 698: 75 49 jne 6e3 <main+0xb6> 250 global++; 251 69a: 8b 83 30 00 00 00 mov 0x30(%ebx),%eax 252 6a0: 83 c0 01 add $0x1,%eax 253 6a3: 89 83 30 00 00 00 mov %eax,0x30(%ebx) 254 stack++; 255 6a9: 83 45 ec 01 addl $0x1,-0x14(%ebp) 256 (*heap)++; 257 6ad: 8b 45 f0 mov -0x10(%ebp),%eax 258 6b0: 8b 00 mov (%eax),%eax 259 6b2: 8d 50 01 lea 0x1(%eax),%edx 260 6b5: 8b 45 f0 mov -0x10(%ebp),%eax 261 6b8: 89 10 mov %edx,(%eax) 262 263 printf("In sub-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap); 264 6ba: 8b 45 f0 mov -0x10(%ebp),%eax 265 6bd: 8b 10 mov (%eax),%edx 266 6bf: 8b 83 30 00 00 00 mov 0x30(%ebx),%eax 267 6c5: 52 push %edx 268 6c6: ff 75 ec pushl -0x14(%ebp) 269 6c9: 50 push %eax 270 6ca: 8d 83 b4 e7 ff ff lea -0x184c(%ebx),%eax 271 6d0: 50 push %eax 272 6d1: e8 9a fd ff ff call 470 <printf@plt> 273 6d6: 83 c4 10 add $0x10,%esp 274 exit(0); 275 6d9: 83 ec 0c sub $0xc,%esp 276 6dc: 6a 00 push $0x0 277 6de: e8 cd fd ff ff call 4b0 <exit@plt> 278 }else{ 279 sleep(2); 280 6e3: 83 ec 0c sub $0xc,%esp 281 6e6: 6a 02 push $0x2 282 6e8: e8 93 fd ff ff call 480 <sleep@plt> 283 6ed: 83 c4 10 add $0x10,%esp 284 printf("In parent-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap); 285 6f0: 8b 45 f0 mov -0x10(%ebp),%eax 286 6f3: 8b 10 mov (%eax),%edx 287 6f5: 8b 83 30 00 00 00 mov 0x30(%ebx),%eax 288 6fb: 52 push %edx 289 6fc: ff 75 ec pushl -0x14(%ebp) 290 6ff: 50 push %eax 291 700: 8d 83 e8 e7 ff ff lea -0x1818(%ebx),%eax 292 706: 50 push %eax 293 707: e8 64 fd ff ff call 470 <printf@plt> 294 70c: 83 c4 10 add $0x10,%esp 295 } 296 } 297 298 return 0; 299 70f: b8 00 00 00 00 mov $0x0,%eax 300 } 301 714: 8d 65 f8 lea -0x8(%ebp),%esp 302 717: 59 pop %ecx 303 718: 5b pop %ebx 304 719: 5d pop %ebp 305 71a: 8d 61 fc lea -0x4(%ecx),%esp 306 71d: c3 ret 307 71e: 66 90 xchg %ax,%ax 308 309 00000720 <__libc_csu_init>: 310 720: 55 push %ebp 311 721: 57 push %edi 312 722: 56 push %esi 313 723: 53 push %ebx 314 724: e8 59 00 00 00 call 782 <__x86.get_pc_thunk.si> 315 729: 81 c6 d7 18 00 00 add $0x18d7,%esi 316 72f: 83 ec 0c sub $0xc,%esp 317 732: 8b 6c 24 28 mov 0x28(%esp),%ebp 318 736: 8d 9e f8 fe ff ff lea -0x108(%esi),%ebx 319 73c: 67 e8 ee fc ff ff addr16 call 430 <_init> 320 742: 8d 86 f4 fe ff ff lea -0x10c(%esi),%eax 321 748: 29 c3 sub %eax,%ebx 322 74a: c1 fb 02 sar $0x2,%ebx 323 74d: 85 db test %ebx,%ebx 324 74f: 74 24 je 775 <__libc_csu_init+0x55> 325 751: 31 ff xor %edi,%edi 326 753: 90 nop 327 754: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi 328 758: 83 ec 04 sub $0x4,%esp 329 75b: 55 push %ebp 330 75c: ff 74 24 2c pushl 0x2c(%esp) 331 760: ff 74 24 2c pushl 0x2c(%esp) 332 764: ff 94 be f4 fe ff ff call *-0x10c(%esi,%edi,4) 333 76b: 83 c7 01 add $0x1,%edi 334 76e: 83 c4 10 add $0x10,%esp 335 771: 39 fb cmp %edi,%ebx 336 773: 75 e3 jne 758 <__libc_csu_init+0x38> 337 775: 83 c4 0c add $0xc,%esp 338 778: 5b pop %ebx 339 779: 5e pop %esi 340 77a: 5f pop %edi 341 77b: 5d pop %ebp 342 77c: c3 ret 343 77d: 8d 76 00 lea 0x0(%esi),%esi 344 345 00000780 <__libc_csu_fini>: 346 780: f3 c3 repz ret 347 348 00000782 <__x86.get_pc_thunk.si>: 349 782: 8b 34 24 mov (%esp),%esi 350 785: c3 ret 351 352 Disassembly of section .fini: 353 354 00000788 <_fini>: 355 788: 53 push %ebx 356 789: 83 ec 08 sub $0x8,%esp 357 78c: e8 9f fd ff ff call 530 <__x86.get_pc_thunk.bx> 358 791: 81 c3 6f 18 00 00 add $0x186f,%ebx 359 797: 83 c4 08 add $0x8,%esp 360 79a: 5b pop %ebx 361 79b: c3 ret
都见到源代码了,想怎么折腾都可以,尽情发挥吧
4、splint
格式:splint [options] file.c
功能:列出file.c代码的缺陷
1 [guochaoxxl@opensource chapter01]$ splint p5_01.c
2 Splint 3.1.2 --- 23 Apr 2014
3
4 p5_01.c: (in function main)
5 p5_01.c:11:17: Variable num used before definition
6 An rvalue is used that may not be initialized to a value on some execution
7 path. (Use -usedef to inhibit warning)
8 p5_01.c:12:17: Value *ptrNum used before definition
9 p5_01.c:3:14: Parameter argc not used
10 A function parameter is not used in the body of the function. If the argument
11 is needed for type compatibility or future plans, use /*@unused@*/ in the
12 argument declaration. (Use -paramuse to inhibit warning)
13 p5_01.c:3:27: Parameter argv not used
14
15 Finished checking --- 4 code warnings
容易看出有4个代码警告,也可以在代码编辑时使用-Wall选项来完成同样的工作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具