本文介紹瞭如何使用GDB調試工具、如何將GDB移植到linu開發板上、如何在交叉編譯時使用GDB,,如何設置LVGL FreeType中文字型檔. ...
目錄
更新日誌:
v1.2 2024年6月24日19:59:19 基本文檔編寫 2024年7月2日發佈於博客園
簡介
gdb工具是 GNU項目調試器,基於命令行。和其他的調試器一樣,我們可以使用 gdb來一行行的運行程式、單步執行、跳入 /跳出函數、設置斷點、查看變數等等,它是 UNIX/LINUX操作系統下強大的程式調試工具。 gdb支持多種語言,包括 Ada、彙編、 C/C++、 D、 Fortran、 GO、Objective-C、 OpenCL、 Modula-2、 Pascal和 Rust。關於 gdb更多詳細的信息請到 gdb官網查閱,gdb官網地址為: www.gnu.org。
一般的桌面 Linux系統,比如 ubuntu、 centos等,我們可以直接運行 gdb來調試程式。但是嵌入式中晶元性能一般比較弱,所以直接在嵌入式系統中運行 gdb不太現實 (性能強大的嵌入式晶元可以這麼做 )。嵌入式系統中一般在 PC端運行 gdb工具,源碼也是在 PC端,源碼應的可執行文件放到開發板中運行。為此我們需要在開發板中運行 gdbserver,通過網路與 PC端的 gdb進行通信。因此要想在 PC上通過 gdb調試嵌入式程式,那麼需要兩個東西: gdb和gdbserver,其中 gdb是運行在 PC上的, gdbserver需要我們移植到開發板上。
開始使用
開發板要和上位機處於同一區域網!!
開發板要和上位機處於同一區域網!!
開發板要和上位機處於同一區域網!!
重要的事情說三遍!
電腦端
準備
安裝gdb
在root用戶許可權下:
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get update
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get install gdb
Do you want to continue? [Y/n] y
1.編譯帶調試信息的可執行文件
使用編譯命令 -g 例如:
-g選項的作用是:在可執行文件中加入源碼信息,比如:可執行文件中第幾條機器指令對應源代碼的第幾行,但並不是把整個源文件都嵌入到可執行文件中,而是在調試時必須保證gdb能找到源文件。
cc client.c cJSON.c myJSON.c base64.c -g -o client.out -pthread
2.進入gdb
gdb client.out
這時候gdb環境準備就緒, 會有歡迎界面, 按一下回車鍵, 開始進入命令輸入
3.啟動程式
start
這時候程式啟動,但等待你的下一步操作, 可以設置斷點等
常用命令
在start以後
設置斷點:
b 124 #在第124行設置斷點, 然後繼續
c #讓程式運行到設置的斷點 124 行停下. 這裡的行數是你的main.c的行數
n #單步運行: 讓程式一次運行一行, 註意不會入子函數模塊!! 只會顯示函數運行結果,例如第124行是調用函數, 則應該c 124, 讓程式在124停止
進入函數
step #在上面的設置斷點到 124行的函數調用時 , 進入到124行的函數內部
n #繼續在函數內部按行執行, 是可以繼續設置斷點的.
列印數值
display count#display可以將變數count添加到監聽隊列, 監聽隊列的值會被顯示列印出來
undisplay 3#將監聽隊列中的第三號成員移除隊列
結束
quit #退出gdb! !!!!註意不可以ctrl+C結束程式, 會導致異常!!!!! 會導致異常!!!!
常用命令
l
是L的小寫
l命令 (list)用於列出所有程式源碼,輸入“ l”
輸入“ l”命令以後就列印出了調試程式的所有源碼,如果源碼沒有列印完的話就重覆按下“ l”命令,或者按下回車鍵, gdb調試工具中回車鍵表示重覆上一個命令!
回車鍵
重覆上一個命令
b
b命令 (break)用於設置斷點,也可以用縮寫“ b”,後面可以跟具體的函數或者行號,比如break main”表示在 main函數處設置斷點,“ break 11”在第 11行設置斷點。
b 11 #在第 11行設置斷點
b main #在 main函數處設置斷點
C
命令用於運行到斷點 處 ,輸入 c命令程式就會運行,直到下一個斷點處(該斷點只會作用一次). 再次c就會繼續往下, 若沒有斷點就會繼續執行, 直到程式結束.
S
s命令 (step)是單步運行執行,此函數會進入到函數裡面。
n
n命令 (next)也是單步運行,但是 n命令不會進入到函數裡面。
p
p命令 (print)用於列印某個變數值。
q
q命令 (quit)用於退出調試,開發板上的 gdbserver也會停止。
參考文檔
1、安裝gdb。
在root用戶許可權下:
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get update ...... ...... ...... root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get install gdb ...... ...... ...... Do you want to continue? [Y/n] y ...... ...... ...... root@iZ2zeeailqvwws5dcuivdbZ:~#
安裝好gdb了。
2、gdb的簡單使用。
用root許可權的Terminal(或一般許可權的Terminal)的vi編輯器編寫一個C程式a.c:
1 #include <stdio.h> 2 3 int main() 4 { 5 int a = 1; 6 int b = a; 7 8 printf("a = %d, b =%d\n", a, b); 9 10 return 0; 11 }
(1) 在可執行文件中加入源碼信息
這個過程通過gcc來完成:
gcc –o a a.c -g
-o選項的作用是:對命令輸出結果進行導入操作,這裡是把gcc –o a a.c -g的操作結果輸出到文件a(文件名可以自定義)中進行保存。
-g選項的作用是:在可執行文件中加入源碼信息,比如:可執行文件中第幾條機器指令對應源代碼的第幾行,但並不是把整個源文件都嵌入到可執行文件中,而是在調試時必須保證gdb能找到源文件。
(2) 進入gdb
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gcc -o a a.c -g root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from a...done. (gdb)
如下圖所示:
gdb提供一個類似Shell的命令行環境,上面的(gdb)就是提示符,在提示符後面輸入gdb的相應命令就可以實現其對應的功能。
(3) gdb調試常用命令
[1] start
用start命令開始執行程式:
(gdb) start Temporary breakpoint 1 at 0x40052e: file a.c, line 5. Starting program: /root/2/02/a Temporary breakpoint 1, main () at a.c:5 5 int a = 1; (gdb)
gdb提示準備執行a.c程式的第六行代碼。然後繼續用(gdb)提示需要輸入的命令。
[2] 單步執行(n)
(gdb) start Temporary breakpoint 1 at 0x40052e: file a.c, line 5. Starting program: /root/2/02/a Temporary breakpoint 1, main () at a.c:5 5 int a = 1; (gdb) n 6 int b = a; (gdb) n 8 printf("a = %d, b = %d\n", a, b); (gdb) n a = 1, b = 1 9 return 0; (gdb) quit A debugging session is active. Inferior 1 [process 22935] will be killed. Quit anyway? (y or n) y root@iZ2zeeailqvwws5dcuivdbZ:~/2/02#
在start命令後,每輸入一個n就能夠單步執行一條語句(輸入一個命令後,直接回車表示最近輸入命令的含義)。當程式執行完時,可以輸入quit命令來退出gdb模式。
[3] gdb斷點調試
[ breakpoint,*continue和*display ]
(gdb) start Temporary breakpoint 1 at 0x40052e: file a.c, line 5. Starting program: /root/2/02/a Temporary breakpoint 1, main () at a.c:5 5 int a = 1; (gdb) b 8 Breakpoint 2 at 0x40053b: file a.c, line 8. (gdb) c Continuing. Breakpoint 2, main () at a.c:8 8 printf("a = %d, b = %d\n", a, b); (gdb) display b 1: b = 1 (gdb) n a = 1, b = 1 9 return 0; 1: b = 1 (gdb) 10 } 1: b = 1 (gdb) quit root@iZ2zeeailqvwws5dcuivdbZ:~/2/02#
gdb a會進入a可執行程式的gdb模式,start命令就使程式準備運行程式中的第一條語句。b 8是breakpoint 8的簡寫(breakpoint的參數也可以以是某個函數名,表示在此函數處設置一個斷點),表示在程式第八行設置一個斷點。c是continue的縮寫,表示繼續運行程式,程式會在設置斷點處停下來。displayb表示將b的值顯示出來(undisplay取消對變數的跟蹤),然後再輸入單步調試命令n(next)就可以使程式繼續運行。
可見斷點有助於快速跳過沒有問題的代碼,然後在有問題的代碼上慢慢走慢慢分析,“斷點加單步”是使用調試器的基本方法。至於應該在哪裡設置斷點,怎麼知道哪些代碼可以跳過,而哪些代碼要慢慢走,也要通過對錯誤現象的分析和假設來確定,以前我們用printf列印中間結果時,也要分析應該在哪裡插入printf,列印哪些中間結果,調試的基本思路是一樣的。
[4]*info*
一次調試可以設置多個斷點,用info命令可以查看已經設置的斷點:
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from a...done. (gdb) start Temporary breakpoint 1 at 0x40052e: file a.c, line 5. Starting program: /root/2/02/a Temporary breakpoint 1, main () at a.c:5 5 int a = 1; (gdb) b 7 Breakpoint 2 at 0x40053b: file a.c, line 7. (gdb) b 8 Note: breakpoint 2 also set at pc 0x40053b. Breakpoint 3 at 0x40053b: file a.c, line 8. (gdb) i breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040053b in main at a.c:7 3 breakpoint keep y 0x000000000040053b in main at a.c:8 (gdb)
[5]*delete*
每個斷點都有一個編號(有的斷點行數不一樣,但地址卻一樣,有的地方不能夠設置斷點或者說與上一個設置的斷點等效),可以用編號指定刪除某個斷點。
......(gdb) b 7 Breakpoint 2 at 0x40053b: file a.c, line 7. (gdb) b 8 Note: breakpoint 2 also set at pc 0x40053b. Breakpoint 3 at 0x40053b: file a.c, line 8. (gdb) i breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040053b in main at a.c:7 3 breakpoint keep y 0x000000000040053b in main at a.c:8 (gdb) delete 3 (gdb) i breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040053b in main at a.c:7 (gdb)
有時候一個斷點暫時不用可以禁用掉而不必刪除,這樣以後想用的時候可以直接啟用,而不必重新從代碼里找應該在哪一行設斷點,這個過程用 disable 和 enable 來完成。
[6]*條件斷點 (break 和run)*
gdb的斷點功能非常靈活,還可以設置斷點在滿足某個條件時才激活,例如:
......//先把其餘的斷點刪掉。(gdb) b 9 if a == 2 Breakpoint 5 at 0x400552: file a.c, line 9. (gdb) i breakpoints Num Type Disp Enb Address What 5 breakpoint keep y 0x0000000000400552 in main at a.c:9 stop only if a == 2 (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/2/02/a a = 1, b = 1 [Inferior 1 (process 22968) exited normally] (gdb)
r表示從頭開始運行程式,在a==2的條件下中斷才有效。a不等於2,所以中斷無效。
[7] gdb的觀察點(watch 和c)
斷點是當程式執行到某一代碼行時中斷,而觀察點是當程式訪問某個存儲單元時中斷,如果我們不知道某個存儲單元是在哪裡被改動的,這時候觀察點尤其有用。
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from a...done. (gdb) start Temporary breakpoint 1 at 0x40052e: file a.c, line 5. Starting program: /root/2/02/a Temporary breakpoint 1, main () at a.c:5 5 int a = 1; (gdb) watch b Hardware watchpoint 2: b (gdb) c Continuing. Hardware watchpoint 2: b Old value = 0 New value = 1 main () at a.c:8 8 printf("a = %d, b = %d\n", a, b); (gdb)
程式執行到b存儲單元,將此執行單元執行前後的值都顯示出來。
[8] 段錯誤
如果程式運行時出現段錯誤,用gdb可以很容易定位到究竟是哪一行引發的段錯誤。在gdb中運行,遇到段錯誤會自動停下來,這時可以用命令查看當前執行到哪一行代碼了。
gdb顯示段錯誤出現在 _IO_vfscanf 函數中,用bt命令可以看到是哪一個函數調用了它。
[9] gdb基本命令
gdb有許多有用的命令如list(顯示源代碼),這樣就可以結合源碼與調試信息更好的進行調試。將gdb常用命令摘抄如下表:
命令 描述 backtrace(bt) 查看各級函數調用及參數 finish 連續運行到當前函數返回為止,然後停下來等待命令 frame(f) 幀編號 選擇棧幀 info(i) locals 查看當前棧幀局部變數的值 list(l) 列出源代碼,接著上次的位置往下列,每次列十行 list 行號 列出第幾行開始的源代碼 list 函數名 列出某個函數的源代碼 next(n) 執行下一行語句 print(p) 列印表達式的值,通過表達式的值可以修改變數的值或者調用函數 quit(q) 退出gdb調試環境 set var 修改變數的值 start 開始執行程式,停在main函數第一行語句前面等待命令 step(s) 執行下一行語句,如果有函數則進入到函數中 break(b) 行號 在某一行設置斷點 break 函數名 在某個函數開頭設置斷點 break(b)… if… 設置條件斷點 continue(c) 從當前位置開始連續運行程式 delete breakpoints 斷點號 刪掉此號的斷點 display 變數名 跟蹤查看某個變數,每次停下來都顯示它的值 disable breakpoints 斷點號 禁用此斷點 enable 斷點號 啟用此斷點 info(i) breakpoints 查看當前設置了哪些斷點 run(r) 從頭開始連續運行程式 undisplay 跟蹤顯示行號 取消跟蹤顯示 watch 設置觀察點 info(i) watchpoints 查看當前設置了哪些觀察點 x 從某個位置開始列印存儲單元的內容,全部當成位元組來看,而不區分哪個位元組屬於哪個變數
disassemble 反彙編當前函數或者指定的函數,單獨用disassemble命令是反彙編當前函數,如果disassemble命令後面跟函數名或地址則反彙編指定的函數。 si 可以一條指令一條指令地單步調試。 info registers 可以顯示所有寄存器的當前值。在gdb中表示寄存器名時前面要加個$,例如p $esp可以列印esp寄存器的值。
set follow-fork-mode child/parent 設置gdb在fork之後跟蹤子進程/父進程
set args 'command-line' 給執行的程式傳命令行參數
s(stepin) 進入子函數
開發板移植-自行編譯(作廢)
適用於編譯器沒有自帶gdb, 需要編譯.
2024年6月24日: 嘗試編譯失敗, 使用 的5.4.0交叉編譯器, 無法生成gdb, 懷疑是編譯器不完全, 解決方法: 更換編譯器.
獲取 gdb和 gdbserver源碼
開發板配套預設的編譯器沒有gdb因此需要自己編譯
首先到 gdb官網上獲取源碼,地址為 https://www.gnu.org/software/gdb/download/在筆者寫本教程的時候,最新的 gdb源碼 版本 為 9.1。已經放到了開發板光碟中,路徑為: 1、常式源碼->7、第三方庫源碼 -> gdb-9.1.tar.gz。將 gdb源碼發送到 ubuntu中 中並解壓,命令如下:
Index of /pub/gdb/releases (sourceware.org)
以root賬戶運行:
cd /root
mkdir gdb
mkdir /DevelopmentTool/gdb#存放編譯後可運行的gdb
#將文件放入 gdb文件夾中,臨時存放
root@yuyi-machine:~/gdb# tar -vxzf gdb-9.1.tar.gz//解壓 gdb源碼
root@yuyi-machine:~/gdb# ls
gdb-9.1 gdb-9.1.tar.gz
解壓完成以後就會得到一個名為 gdb-9.1的文件夾,此文件夾就是 gdb和 gdbserver源碼,其中 gdb-9.1/gdb/gdbserver目錄就是 gdbserver源碼。
編譯 gdb
1、編譯 gdb
首先編譯 gdb gdb是運行在 PC端的程式, gdb編譯的時候需要進行配置,配置項如下:
--target 目標機交叉編譯器首碼,也就是你所使用的交叉編譯器首碼,比如在本教程中就設置為 arm-linux-gnueabihf。
--host 指定編譯後的程式在哪裡運行,編譯 gdb的時候就需用設置,因為我們是需要在 PC上運行的,編譯 gdbserver的時候就要設置為 arm-linux。
--prefix 指定安裝目錄。
創建一個名為“gdb”的文件夾,用來保存編譯後的 gdb和 gdbserver,路徑自行選擇。 gdb編譯比較奇葩!使用如下命令配置並編譯 gdb:
cd gdb-9.1/ //進入 gdb源碼目錄
mkdir build //在 gdb源碼下新建 build目錄, gdb編譯比較奇葩!不能直接在 gdb源
//碼目錄下進行配置和編譯,必須新建一個文件夾,然後在此文件夾下配置和編譯,切記!
cd build //進入到剛剛創建的 build目錄下
../configure --target=arm-linux-gnueabihf --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/gdb
//配置 gdb。配置完成以後會在 build目錄下生成 Makefile文件。
make //編譯
make install //安裝
運行實例:
root@yuyi-machine:~/gdb# ls
gdb-9.1 gdb-9.1.tar.gz
root@yuyi-machine:~/gdb# cd gdb-9.1/
root@yuyi-machine:~/gdb/gdb-9.1# mkdir build
root@yuyi-machine:~/gdb/gdb-9.1# cd build
root@yuyi-machine:~/gdb/gdb-9.1/build# ../configure --target=arm-linux --prefix=/DevelopmentTool/gdb
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... arm-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
********
********
make
make[4]: *** [Makefile:490: gdb.info] Error 127
make[4]: Leaving directory '/root/gdb/gdb-9.1/build/gdb/doc'
make[3]: *** [Makefile:2006: subdir_do] Error 1
make[3]: Leaving directory '/root/gdb/gdb-9.1/build/gdb'
make[2]: *** [Makefile:1651: all] Error 2
make[2]: Leaving directory '/root/gdb/gdb-9.1/build/gdb'
make[1]: *** [Makefile:9564: all-gdb] Error 2
make[1]: Leaving directory '/root/gdb/gdb-9.1/build'
make: *** [Makefile:852: all] Error 2
root@yuyi-machine:~/gdb/gdb-9.1/build#
########################這裡之後就報錯了, 具體不清楚,
make install
root@yuyi-machine:~/gdb/gdb-9.1/build# cd /DevelopmentTool/gdb/
root@yuyi-machine:/DevelopmentTool/gdb# ls
bin lib share
編譯完成以後 PC端運行的 gdb工具就會安裝到 gdb/bin目錄下,名字為 arm-linux-gnueabihf-gdb,如圖 B3.2.2.1所示:
########################這裡之後就報錯了, 具體不清楚,
開發板移植-自行編譯(成功)
下載可用的編譯器
下載
板子應該下載x86_64的版本, 因為開發平臺是64位的linux. 應該不要下載帶h的, h表示硬浮點, 因為 的板子的Linux文件系統中的庫都是使用軟浮點模式編譯的.
官方給的5.4.0版本不完全, 使用很多庫會報錯! 要修改的有很多. 故推薦5.4.1
安裝
sudo apt-get install lsb-core lib32stdc++6 #安裝其它的庫
在電腦的Linux系統中切換為root用戶
su - #切換root
cd /
mkdir /DevelopmentTool/ #創建文件夾
# 然後將 下載好的 gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi.tar.xz 上傳到其中
tar -vxf gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi.tar.xz #解壓
cd /etc/profile.d #進入全局腳本文件夾
touch IoT_development.sh #創建自定義腳本文件
chmod 644 IoT_development.sh
vim IoT_development.sh
# 修改環境變數, 加入下麵的內容即可
export PATH=/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/bin:$PATH
# 重啟系統或
source ./IoT_development.sh
# 查看版本號 如果交叉編譯器安裝正確的話就會顯示版本號,如圖
arm-linux-gnueabi-gcc -v
# 若沒有生效, 需要每個用戶在終端手動運行下麵命令, 或設置另一個全局變數腳本文件
echo "export PATH=/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/bin:$PATH" >> ~/.bashrc
source ~/.bashrc
arm-linux-gnueabi-gcc -v
使用
# 終端直接編譯
arm-linux-gnueabi-gcc main.c -o demo.out
# Makefile編寫
CC = arm-linux-gnueabi-gcc
若有多個不同版本的交叉編譯鏈, 使用時使用完整的名稱即可.
若有需要,程式相關的依賴環境,需要自己補上.
GDB移植到開發板
到了這一步, 編譯器已經可以用gdb, 但是開發板不支持
查看編譯器筆記, 下載新交叉編譯器gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi.tar.xz
編譯可調試的程式
使用 arm-linux-gnueabi-gcc
交叉編譯 demo.c
文件,要想調試程式,那麼編譯的時候必須加上“ “-g
”選項,這樣編譯出來的可執行文件才
帶有調試信息,這一點一定要切記!編譯命令如下所示:
arm-linux-gnueabi-gcc demo.c -o demo.out -g
//編譯測試程式,註意 -g選項
編譯完成以後將得到的 demo.out
可執行文件發送到開發板中。
gdb+gdbserver調試程式
一切準備就緒以後就可以使用 GDB進行調試了,確保 ubuntu和開發板可以進行網路通信。
在開發板中輸入如下命令:
下麵以客戶端 arm-linux-gnueabi-gcc client.c -o client.out -g -pthread 做示範
編譯程式:
yuyi@yuyi-machine:~/workspace/zqingyangLib/examples/2024年6月21日_文件傳輸/temple$ arm-linux-gnueabi-gcc client.c -o client.out -g -pthread
yuyi@yuyi-machine:~/workspace/zqingyangLib/examples/2024年6月21日_文件傳輸/temple$ file client.out
client.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=0fe128394b46c30aa29bc8c4ee4914f35b7305e4, with debug_info, not stripped
傳輸可執行文件到開發板
然後將文件傳輸到開發板,
運行程式
在開發板上輸入:
gdbserver 192.168.64.202:2001 ./client.out //啟動開發板上的 gdbserver
#gdbserver <上位機(調試機)的IP>:<自定義通信埠號> <要調試的可執行文件,例如./client.out>
結果
[root@GEC6818 /yuyiworkspace/tmp]#chmod 777 client.out
[root@GEC6818 /yuyiworkspace/tmp]#gdbserver 192.168.64.202:2001 ./client.out
Process ./client.out created; pid = 1516
Listening on port 2001
上位機(調試機)中輸入如下命令啟動 gdb調試工具:
這裡的./client.out是你要調的程式在上位機的位置, 也就是兩邊都要有 !!!
arm-linux-gnueabi-gdb ./client.out #這裡的./client.out是你要調的程式在上位機的位置, 也就是兩邊都要有
結果
yuyi@yuyi-machine:~/workspace/zqingyangLib/examples/2024年6月21日_文件傳輸$ arm-linux-gnueabi-gdb ./client.out
GNU gdb (Linaro_GDB-2017.01) 7.12.1.20170127-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
上位機: 連接開發板
target remote 192.168.64.203:2001 #連接到開發板上
#target remote <開發板地址>:2001
連接成功以後開發板中的 gdbserver就會提示連接信息, 下麵是開發板的終端輸出:
[root@GEC6818 /yuyiworkspace/tmp]#gdbserver 192.168.64.202:2001 ./client.out
Process ./client.out created; pid = 1516
Listening on port 2001
Remote debugging from host 192.168.64.202
可以看出,遠端調試機的 IP地址為 192.168.64.202,也就是我們的上位機地址,連接成功以後就可以在ubuntu上進行代碼調試了。
下麵是上位機的輸出
./client.out: No such file or directory.
(gdb) target remote 192.168.64.203:2001
Remote debugging using 192.168.64.203:2001
Reading /yuyiworkspace/tmp/client.out from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /yuyiworkspace/tmp/client.out from remote target...
Reading symbols from target:/yuyiworkspace/tmp/client.out...done.
Reading /lib/ld-linux.so.3 from remote target...
Reading /lib/ld-linux.so.3 from remote target...
Reading symbols from target:/lib/ld-linux.so.3...done.
0xb6fcea80 in _start () from target:/lib/ld-linux.so.3
(gdb)
然後可以開始使用了
VSCode+gdbserver圖形化調試
gdb+gdbserver實現對嵌入式linux程式的調試,由於主機上的gdb工具是基於命令行的,因此調試起來不方便,雖然可以加一些插件,但是依舊和IDE的調試體驗差很多。如何使用VSCode+gdbserver來實現圖形化界面的嵌入式linux程式調試。
VSCode設置
給VScode安裝遠程調試插件Remote Development點擊“調試添加配置然後選擇C++(GDB/LLDB)選項.
若沒有配置文件要點 創建 launch.json文件
選擇圖中的“ C++(GDB/LLDB)”,會在當前文件夾新建一個名為 launch.json”的文件,此文件會存放在 .vscode目錄下,
launch.json文件內容如下所示:
{
//需要修改的內容: ★ 。
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch", //★配置名稱;顯示在啟動配置下拉菜單中。
"type": "cppdbg", //配置類型。預設
"request": "launch", //請求配置類型。可以是“啟動”或“附加”。
//program 程式可執行文件的完整路徑, ${workspaceFolder}是我當前打開的文件工作路徑 家目錄 client.out是我要調試的程式
"program": "${workspaceFolder}/zqingyangLib/examples/2024年6月21日_文件傳輸/temple/client.out", //★
"args": [], //傳遞給程式的命令行參數
"stopAtEntry": false, //可選參數。 先打斷點 再運行 如果為 true,則調試程式應在目標的入口點處停止。如果傳遞了 processId,則不起任何作用。
"cwd": "${workspaceFolder}/zqingyangLib/examples/2024年6月21日_文件傳輸/temple", //★需要調試的應用程式源碼路徑。main的位置
"environment": [], //要添加到程式環境的環境變數
"externalConsole": false, //如果為 true,則為調試對象啟動控制台
"MIMode": "gdb", //要連接到的控制台調試程式。允許的值為 "gdb"
//miDebuggerPath ★此項需要手動添加,用於指定所使用的交叉編譯器 gdb路徑。
"miDebuggerPath": "/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-gdb",
"miDebuggerServerAddress": "192.168.64.203:2002" //★此項需要手動添加,遠程 gdbserver伺服器地址。開發板的地址和服務埠
}
]
}
VSCode調試方法
VSCode設置好以後就可以進行調試了,首先要啟動開發板上的 gdbserver,輸入如下命令
gdbserver 192.168.64.202:2002 client.out
接下來在點擊 VSCode上的“調試” ”->“啟動調試”按鈕,如圖
由於是通過網路進行調試的,因此啟動調試以後會有一個建立連接的過程,可能需要幾秒鐘,建立成功以後如上圖
依賴環境搭建
LVGL-freeType字體
設置中文字體
LVGL移植使用中文字型檔
FreeType簡介:
FreeType是一款開源的字體渲染引擎,它支持多種字體格式,包括TrueType,Type 1,OpenType依賴關係:LVGL-->FreeType-->Libpng-->zlib
which arm-linux-gcc 可以查看安裝路徑
第一步:把freetype和zlib中的頭文件和庫文件分別拷貝到ubuntu的arm-linux-gcc安裝路徑下對應的位置
# 以root賬戶登錄Linux
mkdir /root/template
cd /root/template
# 將三個文件複製到其中
root@yuyi-machine:~/template# ls
freetype_tmp.tar.gz libfreetype.so.6.18.3 zlib_tmp.tar.gz
# 解壓
tar -xzvf freetype_tmp.tar.gz
tar -xzvf zlib_tmp.tar.gz
# 進入你的交叉編譯器bin文件夾所在的同級位置, 並記錄其位置及目錄
cd /DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi
------------
root@yuyi-machine:/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi# ls
arm-linux-gnueabi bin gcc-linaro-5.4.1-2017.01-linux-manifest.txt include lib libexec share
-------------
root@yuyi-machine:/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi# pwd
/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi
-------------
root@yuyi-machine:/DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi# cd /root/template #返回前面的解壓位置
root@yuyi-machine:~/template# ls
freetype_tmp freetype_tmp.tar.gz libfreetype.so.6.18.3 zlib_tmp zlib_tmp.tar.gz
--------------
#**************將zlib中的頭文件和庫文件拷貝到交叉編譯器下對應的位置
root@yuyi-machine:~/template# cd /root/template/zlib_tmp/include
root@yuyi-machine:~/template/zlib_tmp/include# ls
zconf.h zlib.h
----------------------
root@yuyi-machine:~/template/zlib_tmp/include# cp * /DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/include/ -rf
--------------------
root@yuyi-machine:~/template/zlib_tmp/lib# cd ~/template/zlib_tmp/lib
root@yuyi-machine:~/template/zlib_tmp/lib# cp * /DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/lib -rf
---------------------
#**************將freetype中的頭文件和庫文件拷貝到交叉編譯器下對應的位置
root@yuyi-machine:~/template/freetype_tmp/include# cd /root/template/freetype_tmp/include/freetype2/
-----------------
root@yuyi-machine:~/template/freetype_tmp/include/freetype2# ls
freetype ft2build.h
-------------------
root@yuyi-machine:~/template/freetype_tmp/include/freetype2# cp * /DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/include -rf
--------------------
root@yuyi-machine:~/template/freetype_tmp/include/freetype2# cd ~/template/freetype_tmp/lib/
root@yuyi-machine:~/template/freetype_tmp/lib# ls
libfreetype.a libfreetype.la libfreetype.so libfreetype.so.6 libfreetype.so.6.18.3 pkgconfig
root@yuyi-machine:~/template/freetype_tmp/lib# cp * /DevelopmentTool/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/lib -rf
--------------------
第二步:將freetypetmp/lib/下的libfreetype.so.6.18.3下載到開發板/usr/lib中. (可從Linux服務端下載)
[root@GEC6818 /yuyiworkspace/LVGL]#cd /usr/lib/
[root@GEC6818 /usr/lib]#ls
libEGL.so libnl-idiag-3.so
libGLESv2.so libnl-idiag-3.so.200
libfreetype.so.6.18.3 libnl-idiag-3.so.200.24.0
libnl-3.la libnl-nf-3.la
libnl-3.so libnl-nf-3.so
libnl-3.so.200 libnl-nf-3.so.200
libnl-3.so.200.24.0 libnl-nf-3.so.200.24.0
libnl-cli-3.la libnl-route-3.la
libnl-cli-3.so libnl-route-3.so
libnl-cli-3.so.200 libnl-route-3.so.200
libnl-cli-3.so.200.24.0 libnl-route-3.so.200.24.0
libnl-genl-3.la libnl-xfrm-3.la
libnl-genl-3.so libnl-xfrm-3.so
libnl-genl-3.so.200 libnl-xfrm-3.so.200
libnl-genl-3.so.200.24.0 libnl-xfrm-3.so.200.24.0
libnl-idiag-3.la
第三步: 修改
修改LVGL工程的Makefile文件
修改
LDFLAGS ?= -lm -lfreetype
修改LVGL工程中lv_conf.h的第671行
//原本是0
/*FreeType library*/
#define LV_USE_FREETYPE 1
#if LV_USE_FREETYPE
#define LV_FREETYPE_SBIT_CACHE 8*1024//原本是0
第四步: 修改LVGL源碼中/lvgl/examples/libs/freetype/lv_example_freetype_1.c
為下麵的內容
#include "../../lv_examples.h"
#if LV_BUILD_EXAMPLES
#if LV_USE_FREETYPE
/**
* Load a font with FreeType
*/
void lv_example_freetype_1(void)
{
/*Create a font*/
static lv_ft_info_t info;
/*FreeType uses C standard file system, so no driver letter is required.*/
// info.name = "./lvgl/examples/libs/freetype/Lato-Regular.ttf";
info.name = "/fonts/HYZhengYuan55W.ttf"; // TTF文件在開發板上的路徑
info.weight = 24; // 48
info.style = FT_FONT_STYLE_NORMAL;
info.mem = NULL;
if(!lv_ft_font_init(&info)) {
LV_LOG_ERROR("create failed.");
}
/*Create style with the new font*/
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, info.font);
lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);
/*Create a label with the new style*/
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_obj_add_style(label, &style, 0);
lv_label_set_text(label, "革命尚未成功\n同志仍需努力");
lv_obj_center(label);
}
#else
void lv_example_freetype_1(void)
{
/*TODO
*fallback for online examples*/
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "FreeType is not installed");
lv_obj_center(label);
}
#endif
#endif
第五步:把字體文件下載到開發板的/font下麵(剛纔第四步那個函數寫的字體路徑就是這個) 要先創建/font文件夾
第六步: 開發板設置
因為在上面編譯好的libfreetype.so.6.18.3雖然下載到開發板中的/usr/lib下了,但是因為編譯時,其識別的是不帶後續次版本和修訂號的庫libfreetype.so.6。 所以需要在開發板的/usr/lib下將該庫添加一個軟鏈接文件或硬鏈接文件皆可。
開發板命令行中
cd /usr/lib
ln libfreetype.so.6.18.3 libfreetype.so.6 -s
如果已經有軟鏈接 就不需要再下載了
參考文檔
- Linux下gdb的安裝及使用入門 - 黑澤君 - 博客園 (cnblogs.com)
- 正點原子驅動開發手冊 1931頁
本文來自博客園,作者:舟清颺,轉載請註明原文鏈接:https://www.cnblogs.com/zqingyang/p/18279323