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

本文爲做者原創,轉載請註明出處:http://www.javashuo.com/article/p-txwprthd-bz.htmlhtml

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

1. 交叉編譯

交叉編譯是指在一種平臺上編譯出運行於另外一種平臺的程序。這裏的平臺,涉及硬件和軟件兩個部分,硬件平臺指 CPU 架構,軟件平臺指操做系統。交叉編譯主要針對嵌入式領域,由於嵌入式系統資源受限,沒有辦法在嵌入式平臺上運行一套編譯環境,所以須要在其餘性能更強勁的平臺上藉助交叉編譯工具鏈來製做可在嵌入式平臺上運行的程序。linux

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

[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'ui

./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]

源碼通過編譯生成可執行程序。根據執行編譯操做的平臺、可執行程序的運行平臺、可執行的程序的處理平臺,能夠將編譯操做分爲多種類型,對應的三個配置參數以下:this

--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 初稿

相關文章
相關標籤/搜索