程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 源文件移動後gdb不顯示代碼的原因

源文件移動後gdb不顯示代碼的原因

編輯:C++入門知識

源文件移動後gdb不顯示代碼的原因

 

問題

我們從一個最簡單的C語言程序開始。源文件main.c在 用戶目錄gdb文件夾下。

florian@florian-pc:~/gdb$ cat main.c

int main()

{

    return 0;

};

然後將源文件編譯為main(需要調試選項-g),並將main.c移動到src/main.c下,然後對main進行調試。

florian@florian-pc:~/gdb$ gcc main.c -o main -g

florian@florian-pc:~/gdb$ mv main.c src/main.c

florian@florian-pc:~/gdb$ gdb main

(gdb) b main

Breakpoint 1 at 0x8048397: file main.c, line 3.

(gdb) list

1   main.c: 沒有那個文件或目錄.

    in main.c

在gdb中,使用list命令查看源代碼時,無法找到源文件main.c。

探究

由於對DWARF調試格式並不清晰,我本以為使用調試選項編譯的可執行程序內部包含了源文件的內容,這樣無論源碼是否存在,可執行程序都可以被正常調試。但是,從上邊的例子中可以看出,事實並非如此。

我們可以作一個簡單的推測:由於移動源文件的位置後,gdb無法找到源文件的位置,估計可執行文件的調試段內保存的不是源文件的內容,而是路徑信息。

將main.c移動回來,重新編譯,生成目標文件main.o,並查看其段信息。

florian@florian-pc:~/gdb$ mv src/main.c main.c

florian@florian-pc:~/gdb$ gcc -c main.c -o main.o -g

florian@florian-pc:~/gdb$ objdump -s main.o

 

main.o:     file format elf32-i386

 

Contents of section .text:

 0000 5589e5b8 00000000 5dc3               U.......].     

……

Contents of section .debug_str:

 0000 6d61696e 2e63002f 686f6d65 2f666c6f     main.c./home/flo

 0010 7269616e 2f676462 00474e55 20432034     rian/gdb.GNU C 4

 0020 2e342e35 006d6169 6e00                      .4.5.main.     

……

我們發現在.debug_str段內,有兩個很明顯的字符串信息。

(1)/home/florian/gdb:看起來很像源文件所在的絕對路徑。

(2)main.c:顯而易見,是源文件的名稱。

驗證

我們再把main.c移動到src目錄下,再次編譯,看看字符串的信息有何變化。

florian@florian-pc:~/gdb$ mv main.c src/main.c

florian@florian-pc:~/gdb$ gcc -c src/main.c -o main.o -g

florian@florian-pc:~/gdb$ objdump -s main.o

 

main.o:     file format elf32-i386

 

Contents of section .text:

 0000 5589e5b8 00000000 5dc3               U.......].     

……

Contents of section .debug_str:

 0000 2f686f6d 652f666c 6f726961 6e2f6764     /home/florian/gd

 0010 6200474e 55204320 342e342e 35007372     b.GNU C 4.4.5.sr

 0020 632f6d61 696e2e63 006d6169 6e00           c/main.c.main. 

在.debug_str段內的兩個字符串信息發生了變化。

(1)/home/florian/gdb:可見該字符串為執行gcc命令時的當前目錄的絕對路徑。

(2)src/main.c:該字符串為源文件相對於當前目錄的相對路徑。

將兩個目錄合並,便可以得到源文件的絕對路徑:

/home/florian/gdb /src/main.c

結論

由此可見,使用調試選項編譯生成的可執行文件內並非保存了源文件的內容,而是源文件的絕對路徑信息。DWARF調試格式(詳見這裡)定義的其他debug段內保存了二進制代碼與源文件行號的對應關系,這樣gdb的list命令工作時,實際是讀取可執行文件內的行號信息,並將源文件的代碼內容顯示出來。這也是為什麼將源文件移動後,list命令信息無法找到源文件的原因。

從這裡,我們也可以清楚一個事實:當源碼目錄的源文件路徑發生變化後,如果需要對可執行文件進行調試,則必須重新編譯。

類似的問題不僅僅在gdb的list命令中存在,objdump –S命令用於交叉顯示反匯編代碼與源代碼,同樣會受移動源文件的影響。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved