一、安装eclipse
1)官网下载对应的版本(eclipse-inst-jre-linux64.tar.gz)
Eclipse Packages | The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 350 open source projects...
2)解压
tar -xvf eclipse-inst-jre-linux64.tar.gz
3)进入解压后的eclipse-installer目录,运行安装程序
root@linux:/home/gsf/Downloads# cd eclipse-installer/
root@linux:/home/gsf/Downloads/eclipse-installer# ./eclipse-inst
4)运行eclipse
root@linux:~/eclipse/embedcpp-2020-12/eclipse# ./eclipse
5)安装CDT
Help --> Eclipse Marketplace,搜索“cdt”,安装Bracketeer for C/C++(CDT)
二、编译rootfs及kernel iamge
参考ubuntu20.04 搭建kernel调试环境第二篇--制作rootfs,制作rootfs。
参考ubuntu20.04 搭建kernel调试环境第三篇--kernel编译及运行,编译kernel image。
三、配置eclipse远程调试kernel
1)运行eclipse
root@linux:~/eclipse/embedcpp-2020-12/eclipse# ./eclipse
2)选择C/C++透视图,使eclipse页面布局方便查看调试C代码
3)新建一个工程
File --> New --> Other
弹出的窗口中选择C/C++ --> Makefile Project with Existing Code
我们没用到Makefile,所以不一定要选Makefile Project with Existing Code,也可选择其他的C、C++project。选择该类型Project的好处是,在创建Project的过程中可以指定kernel源码根目录,调试时不需要其他设置就可以找到根目录中的vmlinux。
弹出的窗口如下,我的填的信息:
Toolchain for indexer Settings-----没用到,任意选都可以。
设置完成,关闭该窗口。
4)设置调试选项
Run --> Debug Configurations,弹出下面窗口:
序号1处,右击选择New Configuration。
序号2处,设置配置的名称,随便写个(但要保证至少4个字符),自己能知道该名称代表什么配置就可以。
序号3处,点Browse按钮,选择3)步创建的project。
序号4处,选择我们编译的vmlinux。
设置完成后,点击上图中的Debugger:
(如果调试的bzImage是x86架构内核,GDB debugger选项直接填gdb或者/bin/gdb)
继续设置debug选项中的Connection:
Port number填qemu的远程调试端口1234。
填完上面信息,点击上图中的Source,增加“Absolute File Path”:
这步的目的是为了在debug代码时可以找到对应的C源文件。
注意,如果在debug调试内核代码出现工具链错误,请参考中“安装开发软件”与“安装python2.7”两节内容。
四、调试kernel
1)一个终端运行qemu启动kernel
gsf@linux:~/debug/kernel/linux-5.10.3$ qemu-system-arm -nographic -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -S -s
注:如果用root用户执行上面命令出现Failed to initialize PA contextXDG_RUNTIME_DIR错误,换成普通用户试试。
--nographic:关闭图形调试,将打印信息输出到串口。
-M machine type,可通过qemu-system-arm -machine help查询支持哪些machine。
-m 内存大小
-kernel 要运行的额内核image
-append kernel运行时的命令行参数
-dtb 设备树文件
-S: 冻结CPU直至接受到c命令,用于远程gdb调试。
-s:是 -gdb tcp::1234缩写,表示在TCP 1234端口打开一个gdb服务器,用于远程gdb调试。
console=ttyAMA0,用于输出终端信息,终端名称取决于驱动。vexpress-a9平台终端名称是ttyAMA0。
2)elipse点击debug,注意gdb命令在Debugger Console中输入
读入符号表、设置断点后运行,eclipse会自动显示断点处的C源码。
附一:调试过程中,一些问题的解决
1)如果出现变量值无法查看的问题(例如下图,查看函数定义的bio_slab_max时提示Syntax error),把函数的__init属性去掉重新编译vmlinux即可解决。
2)遇到函数调用,单步调试进不去。点击单步运行,可以看到调试器在运行,但是没法进入函数内部,把函数的__always_inline、__inline属性去掉重新编译vmlinux即可解决。若是还不能进入函数,可在源码中指定不优化该函数。
可以通过下面命令删掉文件中所有的__always_inline字符串:
sed -i "s/\ __always_inline\ / /g" 文件名
可以通过下面命令删除当前目录中所有c文件的__always_inline字符串(sed命令中,待替换的字符串前后有转义\定义的空格。)
sed -i "s/\ __always_inline\ / /g" `find ./ -name "*.c"`
或for file in `ls ./`; do sed -i "s/\ __always_inline\ / /g" $file; done
3)单步调试没有严格按源码顺序执行
这是编译时做了优化导致,可在该函数声明的地方,增加红字属性,编译时不要做优化。
static struct elevator_type *elevator_get_default(struct request_queue *q) __attribute__((optimize("O0")));