目录
- 简介
- 开始使用
- 电脑端
- 准备
- 安装gdb
- 1.编译带调试信息的可执行文件
- 2.进入gdb
- 3.启动程序
- 常用命令
- 常用命令
- l
- 回车键
- b
- C
- S
- n
- p
- q
- 参考文档
- 1、安装gdb。
- 2、gdb的简单使用。
- (1) 在可执行文件中加入源码信息
- (2) 进入gdb
- (3) gdb调试常用命令
- [1] start
- [2] 单步执行(n)
- [3] gdb断点调试
- [7] gdb的观察点(watch 和c)
- [8] 段错误
- [9] gdb基本命令
- 开发板移植-自行编译(作废)
- 获取 gdb和 gdbserver源码
- 编译 gdb
- 开发板移植-自行编译(成功)
- 下载可用的编译器
- GDB移植到开发板
- 编译可调试的程序
- gdb+gdbserver调试程序
- VSCode+gdbserver图形化调试
- 依赖环境搭建
- 参考文档
更新日志:
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) n6 int b = a;(gdb) n8 printf("a = %d, b = %d\n", a, b);(gdb) na = 1, b = 19 return 0;(gdb) quitA debugging session is active. Inferior 1 [process 22935] will be killed.Quit anyway? (y or n) yroot@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 8Breakpoint 2 at 0x40053b: file a.c, line 8.(gdb) cContinuing.Breakpoint 2, main () at a.c:88 printf("a = %d, b = %d\n", a, b);(gdb) display b1: b = 1(gdb) na = 1, b = 19 return 0;1: b = 1(gdb) 10 }1: b = 1(gdb) quitroot@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 aGNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1Copyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later 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:.Find the GDB manual and other documentation resources online at:.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 7Breakpoint 2 at 0x40053b: file a.c, line 7.(gdb) b 8Note: breakpoint 2 also set at pc 0x40053b.Breakpoint 3 at 0x40053b: file a.c, line 8.(gdb) i breakpoints Num Type Disp Enb Address What2 breakpoint keep y 0x000000000040053b in main at a.c:73 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 aGNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1Copyright (C) 2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later 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:.Find the GDB manual and other documentation resources online at:.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 bHardware watchpoint 2: b(gdb) cContinuing.Hardware watchpoint 2: bOld value = 0New value = 1main () at a.c:88 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所示:
########################这里之后就报错了, 具体不清楚,
开发板移植-自行编译(成功)
下载可用的编译器
下载
Linaro Releases
板子应该下载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页
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |