Linux Debugging 3 – Compile and Debug

來源:互聯網
上載者:User

1. Build的四個階段

1) 預先處理:gcc -E (cpp)

選項:-D -U -I -M -g3 (output macro info for debugger)

2) 編譯:   gcc -S (cc1)

最佳化選項:-O0, -O1, -O2, -O3, -Os

一個關於最佳化層級選項的對比例子,

#include <stdio.h><br />int main()<br />{<br /> char *c = malloc(8);<br /> memset(c, 's', 8);<br /> return 0;<br />}

不最佳化編譯

>gcc -g2 memset.c

查看產生的彙編代碼,

>objdump -dS a.out

#include <stdio.h><br />int main()<br />{<br /> 4004e8: 55 push %rbp<br /> 4004e9: 48 89 e5 mov %rsp,%rbp<br /> 4004ec: 48 83 ec 10 sub $0x10,%rsp<br /> char *c = malloc(8);<br /> 4004f0: bf 08 00 00 00 mov $0x8,%edi<br /> 4004f5: e8 0e ff ff ff callq 400408 <malloc@plt><br /> 4004fa: 48 89 45 f8 mov %rax,-0x8(%rbp)<br /> memset(c, 's', 8);<br /> 4004fe: 48 8b 7d f8 mov -0x8(%rbp),%rdi<br /> 400502: ba 08 00 00 00 mov $0x8,%edx<br /> 400507: be 73 00 00 00 mov $0x73,%esi<br /> 40050c: e8 e7 fe ff ff callq 4003f8 <memset@plt><br /> return 0;<br /> 400511: b8 00 00 00 00 mov $0x0,%eax<br />}<br /> 400516: c9 leaveq<br /> 400517: c3 retq

最佳化編譯

>gcc -g2 -O3 memset.c

#include <stdio.h><br />int main()<br />{<br /> 4004a0: 48 83 ec 08 sub $0x8,%rsp<br /> char *c = malloc(8);<br /> 4004a4: bf 08 00 00 00 mov $0x8,%edi<br /> 4004a9: e8 12 ff ff ff callq 4003c0 <malloc@plt><br /> memset(c, 's', 8);<br /> 4004ae: 48 ba 73 73 73 73 73 mov $0x7373737373737373,%rdx<br /> 4004b5: 73 73 73<br /> 4004b8: 48 89 10 mov %rdx,(%rax)<br /> return 0;<br />}<br /> 4004bb: 31 c0 xor %eax,%eax<br /> 4004bd: 48 83 c4 08 add $0x8,%rsp

建議不要在測試階段開啟最佳化。

 

gdb資訊選項:

-g == -g2

-g3 include symbols and extra.

下面顯示了不同的層級產生的代碼的大小。

/home/a/j/nomad2:cat hello.c<br />#include <stdio.h><br />int main()<br />{<br /> printf("hello world!/n");<br /> return 0;<br />}<br />/home/a/j/nomad2:cc hello.c -o hg0<br />/home/a/j/nomad2:cc -g1 hello.c -o hg1<br />/home/a/j/nomad2:cc -g2 hello.c -o hg2<br />/home/a/j/nomad2:cc -g3 hello.c -o hg3<br />/home/a/j/nomad2:ls -lrt hg*<br />-rwxr-xr-x 1 nomad2 member 8828 Dec 11 20:02 hg0<br />-rwxr-xr-x 1 nomad2 member 9444 Dec 11 20:02 hg1<br />-rwxr-xr-x 1 nomad2 member 9636 Dec 11 20:02 hg2<br />-rwxr-xr-x 1 nomad2 member 22468 Dec 11 20:03 hg3<br />

在產生的ELF(Executable & Library Format, magic is /x7FELF, man 5 elf)檔案中,debug資訊佔到若干個section,

/home/a/j/nomad2:objdump -h hg1|grep debug<br /> 26 .debug_aranges 000000c0 0000000000000000 0000000000000000 000009b0 2**4<br /> 27 .debug_pubnames 00000040 0000000000000000 0000000000000000 00000a70 2**0<br /> 28 .debug_info 00000221 0000000000000000 0000000000000000 00000ab0 2**0<br /> 29 .debug_abbrev 00000094 0000000000000000 0000000000000000 00000cd1 2**0<br /> 30 .debug_line 00000167 0000000000000000 0000000000000000 00000d65 2**0<br /> 31 .debug_frame 00000040 0000000000000000 0000000000000000 00000ed0 2**3<br /> 32 .debug_str 000000b1 0000000000000000 0000000000000000 00000f10 2**0<br /> 33 .debug_loc 0000004c 0000000000000000 0000000000000000 00000fc1 2**0<br /> 34 .debug_ranges 00000090 0000000000000000 0000000000000000 00001010 2**4<br />/home/a/j/nomad2:objdump -h hg3|grep debug<br /> 26 .debug_aranges 000000c0 0000000000000000 0000000000000000 000009b0 2**4<br /> 27 .debug_pubnames 00000040 0000000000000000 0000000000000000 00000a70 2**0<br /> 28 .debug_info 000002b3 0000000000000000 0000000000000000 00000ab0 2**0<br /> 29 .debug_abbrev 000000ae 0000000000000000 0000000000000000 00000d63 2**0<br /> 30 .debug_line 000002aa 0000000000000000 0000000000000000 00000e11 2**0<br /> 31 .debug_frame 00000040 0000000000000000 0000000000000000 000010c0 2**3<br /> 32 .debug_str 000000b1 0000000000000000 0000000000000000 00001100 2**0<br /> 33 .debug_loc 0000004c 0000000000000000 0000000000000000 000011b1 2**0<br /> 34 .debug_macinfo 00003085 0000000000000000 0000000000000000 000011fd 2**0<br /> 35 .debug_ranges 00000090 0000000000000000 0000000000000000 00004290 2**4

使用objdump -W可以查看具體的debug段資訊。

 

3) 彙編:   gcc -c (as)

可以使用-m(achine)選項指定產生目標平台的代碼。

4) 連結:   ld

insertion of libraries(static) or reference(dynamic).

選項:

-l -L -shared -static

 

在release階段,可以strip掉debug資訊, “-d”選項只刪除掉偵錯符號資訊。

/home/a/j/nomad2:strip -d hg3<br />/home/a/j/nomad2:strip -d hg2<br />/home/a/j/nomad2:strip -d hg1<br />/home/a/j/nomad2:strip -d hg0<br />/home/a/j/nomad2:ls -lrt hg*<br />-rwxr-xr-x 1 nomad2 member 6575 Dec 11 20:09 hg3<br />-rwxr-xr-x 1 nomad2 member 6575 Dec 11 20:10 hg2<br />-rwxr-xr-x 1 nomad2 member 6575 Dec 11 20:10 hg1<br />-rwxr-xr-x 1 nomad2 member 6575 Dec 11 20:10 hg0<br />/home/a/j/nomad2:strip hg3<br />/home/a/j/nomad2:strip hg2<br />/home/a/j/nomad2:strip hg1<br />/home/a/j/nomad2:strip hg0<br />/home/a/j/nomad2:ls -lrt hg*<br />-rwxr-xr-x 1 nomad2 member 4496 Dec 11 20:10 hg3<br />-rwxr-xr-x 1 nomad2 member 4496 Dec 11 20:11 hg2<br />-rwxr-xr-x 1 nomad2 member 4496 Dec 11 20:11 hg1<br />-rwxr-xr-x 1 nomad2 member 4496 Dec 11 20:11 hg0

 

2. Parse ELF tools

1) objdump

常用選項: -d(反組譯碼程式碼片段),-g -W (顯示調試資訊), -S(同-d,顯示源檔案),-s(以十六進位格式顯示所有段) ,-t(顯示符號表),-x(顯示所有頭部資訊)

2) readelf

3) nm: 顯示符號表,要求不能被strip過

/home/a/j/nomad2:nm hg3<br />nm: hg3: no symbols

4) ldd: resolve shared library dependencies

 

舉例說明,

/home/a/j/nomad2:file /lib/librt-2.7.so<br />/lib/librt-2.7.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), for GNU/Linux 2.6.8, stripped<br />/home/a/j/nomad2:file a.out<br />a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), not stripped

動態庫的load可以分為裝載時和運行時(dl_open),下面是運行時裝載動態庫的例子。

nomad2@ubuntu:~/c$ cat d.c<br />#include <dlfcn.h><br />#include <stdio.h><br />int main(int argc, char**argv)<br />{<br /> void *so = dlopen("/lib/libc.so.6", RTLD_NOW);<br /> void *f = dlsym(so, argv[1]);<br /> if (f)<br /> {<br /> printf("find %s in libc/n", argv[1]);<br /> }<br /> else<br /> {<br /> printf("can't find %s in libc/n", argv[1]);<br /> }<br />}<br />nomad2@ubuntu:~/c$ cc -ldl -g2 d.c<br />nomad2@ubuntu:~/c$ ./a.out printf<br />find printf in libc<br />nomad2@ubuntu:~/c$ ./a.out printfa<br />can't find printfa in libc

 

3. gdb

3種使用模式:

1) start a binary in the debugger, gdb a.out

2) running process attachment, gdb a.out PID

3) post-mortem, core file analysis, gdb a.out core

常用命令總結:

break, bt(backtrack of stack call of current thread), disass, i r, stepi, info threads, r, c, p, x(dump memory from address)

 

關於core檔案

1) ulimit -c -s -t

注意編譯器在編譯器時,本身也是需要棧空間的。可以使用函數getrlimit, setrlimit來get/set resource limits。

/home/a/j/nomad2:ulimit -a<br />core file size (blocks, -c) 0<br />data seg size (kbytes, -d) 100000<br />scheduling priority (-e) 0<br />file size (blocks, -f) unlimited<br />pending signals (-i) 69632<br />max locked memory (kbytes, -l) 32<br />max memory size (kbytes, -m) 100000<br />open files (-n) 1024<br />pipe size (512 bytes, -p) 8<br />POSIX message queues (bytes, -q) 819200<br />real-time priority (-r) 0<br />stack size (kbytes, -s) 8192<br />cpu time (seconds, -t) 1000<br />max user processes (-u) 64<br />virtual memory (kbytes, -v) unlimited<br />file locks (-x) unlimited

2) core檔案的格式

/home/a/j/nomad2:cat /proc/sys/kernel/core_pattern<br />core

man 5 core to reference the naming rule of core dump files.

 

注意:如果發生了core,但是gdb backtrace找不到在哪個函數core了,可以先ldd這個程式,看依賴於哪些動態連結程式庫,然後nm動態連結程式庫並且搜尋core的地址的前幾位,基本就可確定在哪個函數core了。一般的text段以0x8***開始。

 

對於正在啟動並執行程式,可以通過檢查maps檔案來確定so的位址範圍, 例如

nomad2@ubuntu:/proc/26847$ pwd<br />/proc/26847<br />nomad2@ubuntu:/proc/26847$ cat maps<br />00400000-004be000 r-xp 00000000 08:01 17694722 /bin/bash<br />006bd000-006c7000 rw-p 000bd000 08:01 17694722 /bin/bash<br />006c7000-0097a000 rw-p 006c7000 00:00 0 [heap]<br />7fbad9edb000-7fbadbedb000 r--s 00000000 08:01 8323249 /var/cache/nscd/passwd<br />7fbadbedb000-7fbadc033000 r-xp 00000000 08:01 17825953 /lib/libc-2.7.so<br />7fbadc033000-7fbadc233000 ---p 00158000 08:01 17825953 /lib/libc-2.7.so<br />7fbadc233000-7fbadc236000 r--p 00158000 08:01 17825953 /lib/libc-2.7.so<br />7fbadc236000-7fbadc238000 rw-p 0015b000 08:01 17825953 /lib/libc-2.7.so<br />7fbadc238000-7fbadc23d000 rw-p 7fbadc238000 00:00 0<br />7fbadc23d000-7fbadc23f000 r-xp 00000000 08:01 17825970 /lib/libdl-2.7.so<br />7fbadc23f000-7fbadc43f000 ---p 00002000 08:01 17825970 /lib/libdl-2.7.so<br />7fbadc43f000-7fbadc441000 rw-p 00002000 08:01 17825970 /lib/libdl-2.7.so<br />7fbadc441000-7fbadc478000 r-xp 00000000 08:01 17825802 /lib/libncurses.so.5.6<br />7fbadc478000-7fbadc677000 ---p 00037000 08:01 17825802 /lib/libncurses.so.5.6<br />7fbadc677000-7fbadc67c000 rw-p 00036000 08:01 17825802 /lib/libncurses.so.5.6<br />7fbadc67c000-7fbadc699000 r-xp 00000000 08:01 17825944 /lib/ld-2.7.so<br />7fbadc889000-7fbadc88b000 rw-p 7fbadc889000 00:00 0<br />7fbadc896000-7fbadc899000 rw-p 7fbadc896000 00:00 0<br />7fbadc899000-7fbadc89b000 rw-p 0001d000 08:01 17825944 /lib/ld-2.7.so<br />7fffe4885000-7fffe489a000 rw-p 7ffffffea000 00:00 0 [stack]<br />7fffe49fe000-7fffe4a00000 r-xp 7fffe49fe000 00:00 0 [vdso]<br />ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.