交叉編譯問題記錄-嵌入式環境下 GDB 的使用方法


本文為作者原創,轉載請注明出處:https://www.cnblogs.com/leisure_chn/p/10693247.html

本文以嵌入式 Linux 環境下的 gdb 使用為例,記錄交叉編譯過程中一個比較關鍵的問題:configure 過程中 --build, --host, --target 參數的區別。

1. 交叉編譯

交叉編譯是指在一種平台上編譯出運行於另一種平台的程序。這里的平台,涉及硬件和軟件兩個部分,硬件平台指 CPU 架構,軟件平台指操作系統。交叉編譯主要針對嵌入式領域,因為嵌入式系統資源受限,沒有辦法在嵌入式平台上運行一套編譯環境,因此需要在其他性能更強勁的平台上借助交叉編譯工具鏈來制作可在嵌入式平台上運行的程序。

交叉編譯與普通編譯基本步驟一樣:

[1] configure
在編譯前進行配置。如果 --host 參數與 --build 參數不同,則是交叉編譯。否則就是普通編譯。

[2] make
編譯。根據上一步 configure 配置生成的參數,調用相應的編譯工具鏈編譯生成目標程序。

[3] make install
安裝。將 make 生成的目標程序安裝到指定目錄。如果不運行 make install,手動拷貝到指定目錄也可。

1.1 --build --host --target

看一下 configure 步驟中 --build、--host 和 --target 三個參數的定義,下面在 gdb 源碼目錄運行 './configure --help'

./configure --help
System types:
  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  --target=TARGET   configure for building compilers for TARGET [HOST]

源碼經過編譯生成可執行程序。根據執行編譯操作的平台、可執行程序的運行平台、可執行的程序的處理平台,可以將編譯操作分為多種類型,對應的三個配置參數如下:

--build:運行編譯工具鏈的平台,也就是正在執行編譯操作的平台。如果未指定此參數,則通過 config.guess 猜測得到。通常都不指定此參數。

--host:可執行程序將運行的平台。如果未指定此參數,則和 --build 相同。如果 --host 和 --build 不同,是交叉編譯;否則是普通編譯。

--target:可執行程序將處理的平台。如果未指定此參數,則和 --host 相同。一般來說,程序運行在什么平台,處理的就是什么平台,此參數值和 --host 參數相同,不需顯式指定,所以通常不會關注到此參數。但在制作交叉編譯工具 (如 gcc、gdb 等) 這種特殊情況下,此值和 --host 不同,例如交叉編譯器 arm-linux-gcc,它運行在 x86-linux 平台 (--host 參數),但處理的是 arm-linux 平台 (--target 參數)。如果是交叉編譯一個普通的應用,如運行於 arm-linux 平台的 tftp 程序,則它的運行平台和處理平台都是 arm-linux 平台。

1.2 三種編譯類型

編譯類型可以分為三種,主要體現在 configure 階段不同的配置參數:(假設交叉編譯工具鏈安裝在 x86-linux 平台,待編譯的目標嵌入式平台為 arm-linux 平台,這里僅為了說明意圖,平台命名並不嚴謹)

[1] 編譯 PC 平台普通程序
一般執行如下形式的配置命令:

./configure

將缺省的參數補全,實際等效於如下命令:

./configure --build=x86_linux --host=x86_linux --target=x86_linux

[2] 編譯交叉編譯工具鏈
交叉編譯工具鏈的特別之處在於,它在 x86-linux 平台上運行,處理的卻是 arm-linux 平台。制作交叉編譯工具鏈並不需要使用交叉編譯。一般執行如下形式的配置命令:

./configure --target=arm_linux

將缺省的參數補全,實際等效於如下命令:

./configure --build=x86_linux --host=x86_linux --target=arm_linux

[3] 交叉編譯嵌入式平台程序
生成嵌入式平台的程序需要用用到交叉編譯。一般執行如下形式的配置命令:

./configure --host=arm_linux CC=arm-linux-gcc

將缺省的參數補全,實際等效於如下命令:

./configure --build=x86_linux --host=arm_linux --target=arm_linux CC=arm-linux-gcc

實際上,如果我們要制作運行於嵌入式平台的編譯工具(比如 gcc、gdb 等),也可以先執行上面 configure 命令然后執行 make,但是生成的 gcc、gdb 等工具基本上無法在目標嵌入式平台上正常運行,因為硬件帶不動,所以嵌入式平台的編譯工具鏈是按 [2] 中的方法制作 ,而不是按 [3] 中的方法制作。

2. GDB 交叉編譯與使用實例

嵌入式平台中使用 GDB 時會用到 GDB 的遠程 (remote) 調試模式:在目標板上通過 gdbserver 運行待調試的程序,在宿主機上運行 gdb 並通過 'target remote [ip]:[port]' 來連接到目標板上的 gdbserver,從而啟動遠程調試。各種調試命令在宿主機上輸入,程序執行效果(包括打印)在目標板上展示,這很容易理解,因為正在調試的程序本來就是在目標板上運行的。不在目標板上直接運行 gdb 進行調試是因為目標板硬件配置低,跑不動 gdb,當然,不排除某些嵌入式平台的性能很強勁,能夠正常運行 gdb。當嵌入式平台的硬件越來越強大時,嵌入式平台與通用計算機平台的界限也越來越模糊,實際情況也正是這樣,硬件性能越來越強悍,資源短缺的問題越來越淡化,這種發展形勢下,嵌入式技術的沒落是必然的結果。

搭建嵌入式平台下的 gdb 調試環境,對理解前面交叉編譯過程中的 --build、--host 和 --target 三個參數非常用幫助。

2.1 環境描述

虛擬機:CPU:x86_64,系統:openSUSE Leap 42.3,IP:192.168.202.240
開發板:CPU:mips mt7688,系統:openwrt linux,IP:192.168.202.141
虛擬機上安裝的 C 交叉編譯器為 mipsel-openwrt-linux-gcc,即交叉編譯工具鏈的前綴為 mipsel-openwrt-linux。

2.2 下載源碼

ftp://ftp.gnu.org/gnu/gdb 下載最新版源碼 gdb-8.2.tar.gz,解壓:

tar zxvf ./gdb-8.2.tar.gz
cd gdb-8.2

2.3 編譯 gdb

編譯 gdb:

cd gdb-8.2
./configure --target=mipsel-openwrt-linux
make

gdb 運行在虛擬機上,所以它不需要交叉編譯。--build 和 --host 參數留空,實際使用的是虛擬機的平台參數。gdb 雖運行在虛擬機上,但它處理的是開發板平台的程序,所以指定 --target 為 mipsel-openwrt-linux,值取的是交叉編譯工具鏈前綴。

2.4 交叉編譯 gdbserver

編譯 gdbserver:

cd gdb-8.2/gdb/gdbserver
./configure --host=mipsel-openwrt-linux CC=mipsel-openwrt-linux-gcc
make

gdbserver 運行在開發板上,所以需要交叉編譯。--build 參數留空,實際使用的是虛擬機的平台參數。--host 參數指定虛擬機平台,值為 mipsel-openwrt-linux。--target 參數留空,所以它的取值將等於 --host 參數值。

2.5 以 remote 方式使用 gdb

開發板:開發板 IP 是 192.168.202.141,則輸入下述任一條指令皆可

gdbserver :1234 test
gdbserver 127.0.0.1:1234 test
gdbserver 192.168.202.141:1234 test

主機:首先在 SHELL 命令行里運行 gdb 應用

./gdb

運行上一條命令后,SHELL 將進入 gdb 模式,下列幾條指令中 '(gdb)' 是提示符:

(gdb) target remote 192.168.202.141
(gdb) b main.c:55
(gdb) c

上面第一條命令是遠程連接到開發板上的 gdbserver。連接之后,就是正常使用了。第二條命令是設置斷點。第三條命令是運行程序,注意待調試的程序實際已在開發板上運行了,所以要使用 'c' 指令,而不能使用 'r' 指令,如果輸入 'r' 指令,可以看到提示 remote 模式不支持 'r' 指令:

(gdb) r
The "remote" target does not support "run".  Try "help target" or "continue".

3. 遺留問題

交叉編譯過程中,一般使用交叉編譯工具鏈的前綴作 --host 及 --target 的值;--build 參數一般不指定,編譯時自動推測。這些都是在實踐層面,一般就算寫錯了,多試一試最終都能編譯通過。而對平台描述的定義,即 --build、--host 及 --target 的值的具體取值規則,我沒有找到正式的出處和定義,是的,網上沒查到。

4. 參考資料

嵌入式 Linux 的 GDB 調試環境建立
Python Exception 異常信息
QT 遠程調試 ARM 板中 python 的問題

5. 修改記錄

2019-04-11 初稿


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM