u-boot 编译,调试及技巧
----------------------------------------
Author: hjjdebug
Date: 2015年 07月 28日 星期二 17:09:17 CST
email: hejinjing@tom.com
----------------------------------------
****************************************
甲: 编译 (版本 u-boot-2015.04)
****************************************
粗略阅读一下makefile, 会让你有不少收获, 进一步深化了阅读make.p查找,获取关注信息
make help 也可以得到一些帮助信息。
-------------------
1. make xxx_config
-------------------
make menuconfig 并不能得到我们的versatilepb, 应该用make versatilepb_config
否则,u-boot 启动不起来, 在已有.config 后, menuconfig 可以做调整。
那么, 都有哪些config 呢?
用make 123_config 试试, 报错:
*** Can't find default configuration "arch/../configs/123_defconfig"!
蛤哈! 打开configs 目录,发现有很多defconfig(1000多种), 这就是所支持的各种配置了。
关于versatile, 我选用了make versatileqemu_config, 用make versatilepb_config 也可以
-----------------
2. make
-----------------
注意: make 之前,要注意以下要点
a. 把优化项 -O2 改为 -O0 方便我们调试
KBUILD_CFLAGS += -O0
b. 交叉编译arm
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
也可以设置导出
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabi-
或者直接修改Makefile 中CROSS_COMPILE 的定义。
c. make V=1 可以verbose 显示
u-boot 生成如下文件:
u-boot: elf32 arm eabi5 716K ;ELF格式映像文件,可加载到SDRAM或SRAM中进行调试;
u-boot.bin: data 120K ;原始二进制文件,用于下载到启动ROM进行系统引导;
System.map: U-Boot映像文件的符号表,各符号的链接地址
****************************************
乙: 运行
****************************************
$ qemu-system-arm -M versatilepb -kernel u-boot
模拟器起来了,但是是空的!
$ qemu-system-arm -M versatilepb -kernel u-boot -nographic
启动到u-boot, 可以敲人help, printenv ...
ctrl-a x 退出qemu 仿真。
****************************************
丙:u-boot 调试:
****************************************
当调用QEMU时添加 -s 和 -S 选项
-s -gdb tcp::1234 的缩写
-S 在启动时停止CPU (键入'cont'继续执行)
$ qemu-system-arm -M versatilepb -kernel u-boot -nographic -s -S
另启动一个控制台:
1. 为了调试的方便,我使用了 gdbinit-gdb 功能扩展插件, 见
http://download.csdn.net/detail/hejinjing_tom_com/8886205#comment
不使用该插件也没关系。
2. 解决了uboot 代码挪移后, gdb 不能设置断点,不能跟踪调试问题。
方法,不跳转,详细见后。
$arm-none-linux-gnueabi-gdb u-boot
GNU gdb (Sourcery CodeBench Lite 2014.05-29) 7.7.50.20140217-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
Reading symbols from u-boot...done.
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
_start () at arch/arm/lib/vectors.S:54
54 b reset
(gdb) ni
41 mrs r0,cpsr
(gdb) ni
42 bic r0,r0,#0x1f
(gdb) ni
43 orr r0,r0,#0xd3
(gdb) ni
44 msr cpsr,r0
(gdb) bt
#0 reset () at arch/arm/cpu/arm926ejs/start.S:44
.....
_main 在crt0.S 中
#0 _main () at arch/arm/lib/crt0.S:67
file arch/arm/lib/relocate.S, line 114
u-boot 分析:
1. 堆栈清0操作, 开始地址(r1, r2-168), 结束地址(r2=0x8fff48, sp 顶部,由board_config 设定)
2. 代码挪移。由gd_data 决定代码挪移位置
开始地址(r1, r2-168), 结束地址(r2=0x8fff48, sp 顶部,由board_config 设定)
代码挪移咱不管,关键是不能让它跳转过去,否则gdb 就不能跟踪了。全是??, 也不会有调试信息。
把这句nop 掉,
----------------------------------------
用gdb 动态修改内存,改变指令
----------------------------------------
=> 0x1041c <_main+76>: add lr, lr, r0
103 add lr, lr, r0
gdb$ set *(int *)0x1041c=0xe1a00000
查看代码:
disassemble /r 0x1041c
0x0001041c <+76>: 00 00 a0 e1 nop ; (mov r0, r0)
0x00010420 <+80>: 2c 00 99 e5 ldr r0, [r9, #44] ; 0x2c
0x00010424 <+84>: 1b 00 00 ea b 0x10498 <relocate_code>
这是我反复跟踪确定的修改位置,一剑封喉,所有该变还变,但最后跳转跳回本地。
----------------------------------------
也可以打开u-boot 文件,用vim直接修改elf 文件
----------------------------------------
打开elf( vim -b u-boot, :%!xxd)
搜索2c00 99e5 1b00, 在008420处,在841c处,改为0000 a0e1,
在写回elf(:%!xxd -r :w
hjj@hjj-Inspiron:~/misc/qemu_arm/u-boot-2015.04$ objdump -d u-boot |grep -C 2 1041c
10414: e28fe00c add lr, pc, #12
10418: e5990040 ldr r0, [r9, #64] ; 0x40
1041c: e1a00000 nop ; (mov r0, r0)
10420: e599002c ldr r0, [r9, #44] ; 0x2c
10424: ea00001b b 10498 <relocate_code>
看到修改正确!
****************************************
丁: 运行及调试结果
****************************************
运行,很高兴它运行起来了。调试端中断打bt 命令,看到了堆栈信息。
gdb 不能调试u-boot艰冰被破解。
运行起来之后,在控制端输入命令,查看输出。
VersatilePB # help
--- cli_simple_run_command begin
--- argv[0] is help
--- cmd table name is base
--- cmd table name is bdinfo
--- cmd table name is bootm
--- cmd table name is bootp
--- cmd table name is cmp
--- cmd table name is cp
--- cmd table name is crc32
--- cmd table name is dhcp
--- cmd table name is env
--- cmd table name is erase
--- cmd table name is flinfo
--- cmd table name is go
--- cmd table name is help
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
cmp - memory compare
cp - memory copy
crc32 - checksum calculation
dhcp - boot image via network using DHCP/TFTP protocol
env - environment handling commands
erase - erase FLASH memory
flinfo - print FLASH memory information
go - start application at address 'addr'
help - print command description/usage
iminfo - print header information for application image
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing address)
mw - memory write (fill)
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
reset - Perform RESET of the CPU
setenv - set environment variables
tftpboot- boot image via network using TFTP protocol
version - print monitor, compiler and linker version
VersatilePB #
--- cmd 是我加的调试打印信息.看官莫疑!
调试端中断, 查看堆栈
gdb$ bt
#0 0x00017d8c in pl01x_serial_getc () at drivers/serial/serial_pl01x.c:234
#1 0x00017cc8 in serial_getc () at drivers/serial/serial.c:452
#2 0x000148f0 in console_getc (file=0x0) at common/console.c:240
#3 fgetc (file=file@entry=0x0) at common/console.c:321
#4 0x00014920 in getc () at common/console.c:381
#5 0x0001694c in cli_readline_into_buffer (prompt=prompt@entry=0x244a3 "VersatilePB # ", buffer=buffer@entry=0x26424 "", timeout=timeout@entry=0x0) at common/cli_readline.c:539
#6 0x00016b0c in cli_readline (prompt=prompt@entry=0x244a3 "VersatilePB # ") at common/cli_readline.c:482
#7 0x000166c0 in cli_simple_loop () at common/cli_simple.c:276
#8 0x00016838 in cli_loop () at common/cli.c:209
#9 0x00010e38 in main_loop () at common/main.c:89
#10 0x00010730 in board_init_r (id=<optimized out>, dest_addr=<optimized out>) at arch/arm/lib/board.c:683
#11 0x00010454 in clbss_l () at arch/arm/lib/crt0.S:144
Backtrace stopped: frame did not save the PC
----------------------------------------
Author: hjjdebug
Date: 2015年 07月 28日 星期二 17:09:17 CST
email: hejinjing@tom.com
----------------------------------------
****************************************
甲: 编译 (版本 u-boot-2015.04)
****************************************
粗略阅读一下makefile, 会让你有不少收获, 进一步深化了阅读make.p查找,获取关注信息
make help 也可以得到一些帮助信息。
-------------------
1. make xxx_config
-------------------
make menuconfig 并不能得到我们的versatilepb, 应该用make versatilepb_config
否则,u-boot 启动不起来, 在已有.config 后, menuconfig 可以做调整。
那么, 都有哪些config 呢?
用make 123_config 试试, 报错:
*** Can't find default configuration "arch/../configs/123_defconfig"!
蛤哈! 打开configs 目录,发现有很多defconfig(1000多种), 这就是所支持的各种配置了。
关于versatile, 我选用了make versatileqemu_config, 用make versatilepb_config 也可以
-----------------
2. make
-----------------
注意: make 之前,要注意以下要点
a. 把优化项 -O2 改为 -O0 方便我们调试
KBUILD_CFLAGS += -O0
b. 交叉编译arm
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
也可以设置导出
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabi-
或者直接修改Makefile 中CROSS_COMPILE 的定义。
c. make V=1 可以verbose 显示
u-boot 生成如下文件:
u-boot: elf32 arm eabi5 716K ;ELF格式映像文件,可加载到SDRAM或SRAM中进行调试;
u-boot.bin: data 120K ;原始二进制文件,用于下载到启动ROM进行系统引导;
System.map: U-Boot映像文件的符号表,各符号的链接地址
****************************************
乙: 运行
****************************************
$ qemu-system-arm -M versatilepb -kernel u-boot
模拟器起来了,但是是空的!
$ qemu-system-arm -M versatilepb -kernel u-boot -nographic
启动到u-boot, 可以敲人help, printenv ...
ctrl-a x 退出qemu 仿真。
****************************************
丙:u-boot 调试:
****************************************
当调用QEMU时添加 -s 和 -S 选项
-s -gdb tcp::1234 的缩写
-S 在启动时停止CPU (键入'cont'继续执行)
$ qemu-system-arm -M versatilepb -kernel u-boot -nographic -s -S
另启动一个控制台:
1. 为了调试的方便,我使用了 gdbinit-gdb 功能扩展插件, 见
http://download.csdn.net/detail/hejinjing_tom_com/8886205#comment
不使用该插件也没关系。
2. 解决了uboot 代码挪移后, gdb 不能设置断点,不能跟踪调试问题。
方法,不跳转,详细见后。
$arm-none-linux-gnueabi-gdb u-boot
GNU gdb (Sourcery CodeBench Lite 2014.05-29) 7.7.50.20140217-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
Reading symbols from u-boot...done.
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
_start () at arch/arm/lib/vectors.S:54
54 b reset
(gdb) ni
41 mrs r0,cpsr
(gdb) ni
42 bic r0,r0,#0x1f
(gdb) ni
43 orr r0,r0,#0xd3
(gdb) ni
44 msr cpsr,r0
(gdb) bt
#0 reset () at arch/arm/cpu/arm926ejs/start.S:44
.....
_main 在crt0.S 中
#0 _main () at arch/arm/lib/crt0.S:67
file arch/arm/lib/relocate.S, line 114
u-boot 分析:
1. 堆栈清0操作, 开始地址(r1, r2-168), 结束地址(r2=0x8fff48, sp 顶部,由board_config 设定)
2. 代码挪移。由gd_data 决定代码挪移位置
开始地址(r1, r2-168), 结束地址(r2=0x8fff48, sp 顶部,由board_config 设定)
代码挪移咱不管,关键是不能让它跳转过去,否则gdb 就不能跟踪了。全是??, 也不会有调试信息。
把这句nop 掉,
----------------------------------------
用gdb 动态修改内存,改变指令
----------------------------------------
=> 0x1041c <_main+76>: add lr, lr, r0
103 add lr, lr, r0
gdb$ set *(int *)0x1041c=0xe1a00000
查看代码:
disassemble /r 0x1041c
0x0001041c <+76>: 00 00 a0 e1 nop ; (mov r0, r0)
0x00010420 <+80>: 2c 00 99 e5 ldr r0, [r9, #44] ; 0x2c
0x00010424 <+84>: 1b 00 00 ea b 0x10498 <relocate_code>
这是我反复跟踪确定的修改位置,一剑封喉,所有该变还变,但最后跳转跳回本地。
----------------------------------------
也可以打开u-boot 文件,用vim直接修改elf 文件
----------------------------------------
打开elf( vim -b u-boot, :%!xxd)
搜索2c00 99e5 1b00, 在008420处,在841c处,改为0000 a0e1,
在写回elf(:%!xxd -r :w
hjj@hjj-Inspiron:~/misc/qemu_arm/u-boot-2015.04$ objdump -d u-boot |grep -C 2 1041c
10414: e28fe00c add lr, pc, #12
10418: e5990040 ldr r0, [r9, #64] ; 0x40
1041c: e1a00000 nop ; (mov r0, r0)
10420: e599002c ldr r0, [r9, #44] ; 0x2c
10424: ea00001b b 10498 <relocate_code>
看到修改正确!
****************************************
丁: 运行及调试结果
****************************************
运行,很高兴它运行起来了。调试端中断打bt 命令,看到了堆栈信息。
gdb 不能调试u-boot艰冰被破解。
运行起来之后,在控制端输入命令,查看输出。
VersatilePB # help
--- cli_simple_run_command begin
--- argv[0] is help
--- cmd table name is base
--- cmd table name is bdinfo
--- cmd table name is bootm
--- cmd table name is bootp
--- cmd table name is cmp
--- cmd table name is cp
--- cmd table name is crc32
--- cmd table name is dhcp
--- cmd table name is env
--- cmd table name is erase
--- cmd table name is flinfo
--- cmd table name is go
--- cmd table name is help
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
cmp - memory compare
cp - memory copy
crc32 - checksum calculation
dhcp - boot image via network using DHCP/TFTP protocol
env - environment handling commands
erase - erase FLASH memory
flinfo - print FLASH memory information
go - start application at address 'addr'
help - print command description/usage
iminfo - print header information for application image
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing address)
mw - memory write (fill)
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
reset - Perform RESET of the CPU
setenv - set environment variables
tftpboot- boot image via network using TFTP protocol
version - print monitor, compiler and linker version
VersatilePB #
--- cmd 是我加的调试打印信息.看官莫疑!
调试端中断, 查看堆栈
gdb$ bt
#0 0x00017d8c in pl01x_serial_getc () at drivers/serial/serial_pl01x.c:234
#1 0x00017cc8 in serial_getc () at drivers/serial/serial.c:452
#2 0x000148f0 in console_getc (file=0x0) at common/console.c:240
#3 fgetc (file=file@entry=0x0) at common/console.c:321
#4 0x00014920 in getc () at common/console.c:381
#5 0x0001694c in cli_readline_into_buffer (prompt=prompt@entry=0x244a3 "VersatilePB # ", buffer=buffer@entry=0x26424 "", timeout=timeout@entry=0x0) at common/cli_readline.c:539
#6 0x00016b0c in cli_readline (prompt=prompt@entry=0x244a3 "VersatilePB # ") at common/cli_readline.c:482
#7 0x000166c0 in cli_simple_loop () at common/cli_simple.c:276
#8 0x00016838 in cli_loop () at common/cli.c:209
#9 0x00010e38 in main_loop () at common/main.c:89
#10 0x00010730 in board_init_r (id=<optimized out>, dest_addr=<optimized out>) at arch/arm/lib/board.c:683
#11 0x00010454 in clbss_l () at arch/arm/lib/crt0.S:144
Backtrace stopped: frame did not save the PC