qemu结合gdb调试龙芯1c的裸机程序helloworld

来源:互联网 发布:linux同名文件夹合并 编辑:程序博客网 时间:2024/05/19 16:48

测试环境

Windows 8上运行qemu(qemu中自带gdbserver)
IP: 192.168.3.102
Qemu: qemu-w64-setup-20170824.exe

虚拟机中运行为龙芯1c编译的gdb(不能使用系统自带的gdb,除非是使用的龙芯的pc)
IP: 192.168.3.200
Gdb: gdb-7.0.1a.tar.bz2

Helloworld的linux工具链使用龙芯官方推出的gcc-4.3-ls232.tar.gz
RT-Thread的Linux下的交叉编译工具链mips-2015.05-19-mips-sde-elf-i686-pc-linux-gnu.tar.bz2

以上所用到的软件可以到官网下载,也可以去我网盘http://pan.baidu.com/s/1miuYGze

安装qemu

qemu重自带gdb server。

我是在windows 8上使用的qemu,按照和其它软件一样,双击安装就可以了,安装完成后可能需要手动将目录“C:\Program Files\qemu”添加到环境变量。这里需要用到的可执行文件“qemu-system-mipsel.exe”就在该目录中。

编译龙芯1c的gdb

GDB远程调试套件包括Host端的gdb和Target端的gdbserver,对于gdb,宿主机上发行版本自带的(x64)PC版gdb是不能用的,它没有目标架构(MIPS)相关的调试支持。所以我们应该使用gdb的源码,针对MIPS平台编译一个(toolchain还是Host上的)特别的版本
 ./configure --target=mipsel-linux --prefix=/home/gdb/gdb-dest --program-prefix=mipsel-linux-

测试全过程

启动qemu(自带gdbserver)

在windows上的命令窗口中运行如下命令启动qemu
qemu-system-mipsel -M mips -nographic -kernel bin/image.elf -gdb tcp::1234 -S
其中,-M mips指定machine为mips r4k platform。可以通过命令“qemu-system-mipsel -M ?”查看支持那些machine,用命令“qemu-system-mipsel -cpu ?”查看支持那些cpu。

-kernel后的bin/image.elf为本次调试对象,即运行在qemu上的可执行程序;
-gdb tcp:1234的作用是打开qemu中的gdbserver,并且使用tcp,端口为1234;
最后的一个参数“-S”的作用是qemu启动后立刻挂起gdbserver,等待客户端gdb的连接。

运行mipsel-linux-gdb并开始调试

运行mipsel-linux-gdb并连接qemu中的gdbserver

运行前面已经编译好的mipsel-linux-gdb,并用命令”target remote 192.168.3.102:1234”连接qemu中的gdbserver。

命令”target remote 192.168.3.102:1234“中的IP地址192.168.3.102为运行qemu的PC,端口1234为启动qemu时,传给qemu的gdbserver监听的端口。

读取符号表

编译源码时,在Makefile中加入了编译选项”-g“,所以符号表已经在可执行文件”bin/image.elf“中,那么使用命令”symbol-file”读取即可,如下

好,现在可以开始单步,打断点调试了

单步调试

单步执行最开始那段汇编,源码如下

    .text    .globl _start_start:bresetnop.org 0x180/* General exception */1:b1bnop.align 4reset:/* Clear CP0_SR:BEV to 0 */mfc0$t0, $12and$t0, 0xffbfffffmtc0$t0, $12/* Setup stack address */    lui     $sp, %hi(stack_top)    addiu   $sp, $sp, %lo(stack_top)    lui     $t9, %hi(main)    addiu   $t9, %lo(main)    jalr    $t9    nophang:b       hang

调试过程如下

第一个单步,执行了一条汇编指令”mfc0    $t0, $12”,并提示自动切换到汇编模式
然后执行list命令,显示了当前上下文代码,可以看到其后的第二条汇编指令为”and        $t0, 0xffbfffff”
第二个单步,执行了汇编指令”and        $t0, 0xffbfffff”
第三个单步,执行了汇编指令”mtc0    $t0, $12”

打断点

在main函数处打个断点

注意右边为qemu中还没有打印helloworld,代码中13行打印helloworld,那么在15行再打个断点看看

测试源码

这里只贴部分源码,完整的代码请移步到https://gitee.com/caogos/qemu_gdb_mips_hello

start.S

    .text    .globl _start_start:bresetnop.org 0x180/* General exception */1:b1bnop.align 4reset:/* Clear CP0_SR:BEV to 0 */mfc0$t0, $12and$t0, 0xffbfffffmtc0$t0, $12/* Setup stack address */    lui     $sp, %hi(stack_top)    addiu   $sp, $sp, %lo(stack_top)    lui     $t9, %hi(main)    addiu   $t9, %lo(main)    jalr    $t9    nophang:b       hang

main.c

#include <bsp.h>#include <uart.h>int main(){unsigned int tt = 0;int i = 0;// Test exception//writel(0xffffffff, 0x12341234);init_serial();print_uart0("Hello world!\n");for (i = 0 ; i < 10 ; i++) {tt = read_c0_count();}// Never returnwhile(1);return 0;}

uart.h

#ifndef __UART_H__#define __UART_H__//Define#define UART0_BASE 0xB40003F8/* 16550 COM1 */// APIvoid init_serial(void);void print_uart0(const char *s);void putc(char a);#endif

uart.c

#include <bsp.h>#include <uart.h>static int is_transmit_empty(){ volatile char *addr = (volatile char *)(UART0_BASE + 5);return *addr & 0x20;}void putc(char a){volatile char *addr = (volatile char*)UART0_BASE;while (is_transmit_empty() == 0);*addr = a;}void print_uart0(const char *s){while (*s != '\0') { /* Loop until end of string */putc(*s);s++; /* Next char */}}void init_serial(){writeb(0xc1, UART0_BASE + 2);writeb(0x03, UART0_BASE + 3);writeb(0x03, UART0_BASE + 4);writeb(0x60, UART0_BASE + 5);writeb(0xb0, UART0_BASE + 6);writeb(0x00, UART0_BASE + 7);}

Makefile

OBJDIR = obj/BINDIR = bin/DRVDIR = Drivers/CROSS_COMPILE = mipsel-linux-CC = $(CROSS_COMPILE)gccLD = $(CROSS_COMPILE)ldAS = $(CROSS_COMPILE)asAR = $(CROSS_COMPILE)arOBJCOPY = $(CROSS_COMPILE)objcopySYS_INC = include/DRV_INC =Drivers/include/INC_FLAGS += -I$(SYS_INC) -I$(DRV_INC)CFLAGS += -mips32 -EL -Wall -g -fno-exceptions -fno-builtin -mno-abicalls -nostdinc -fno-stack-protectorLDFLAGS += -nostdlib -nostartfiles -nodefaultlibs -ELELF_IMAGE = $(BINDIR)image.elfTARGET = $(BINDIR)image.binLINKER_SCRIPT = boot.ldAPP_OBJS += main.oSTARTUP_OBJ += start.oDRIVER_OBJ += uart.oOBJS = $(addprefix $(OBJDIR), $(STARTUP_OBJ) $(DRIVER_OBJ) $(APP_OBJS))all: $(TARGET)$(TARGET):$(OBJDIR) $(BINDIR) $(ELF_IMAGE)$(OBJCOPY) -O binary $(ELF_IMAGE) $(TARGET)$(ELF_IMAGE):$(OBJS)$(LD) $(LDFLAGS) -T $(LINKER_SCRIPT) $(OBJS) -o $@$(OBJDIR)start.o:start.S$(CC) $(CFLAGS) -c $< -o $@$(OBJDIR)main.o:main.c$(CC) $(CFLAGS) $(INC_FLAGS) -c $< -o $@# Drivers$(OBJDIR)uart.o:$(DRVDIR)uart.c$(CC) $(CFLAGS) $(INC_FLAGS) -c $< -o $@$(OBJDIR):mkdir -p $@$(BINDIR):mkdir -p $@clean:rm -rf obj bin

boot.ld

ENTRY(_start)SECTIONS{. = 0x80000000;.startup . : { obj/start.o(.text) }.text : { *(.text) }.data : { *(.data) }.bss : { *(.bss) }. = . + 0x1000; /* 4kB of stack memory */stack_top = .;}


虽然源码中的串口基地址目前还不是龙芯1c的,但演示一个非常精简的,使用串口打印调试信息的例子,还是很有参考意义的。

查看qemu帮助信息

查看支持的CPU型号

使用命令“qemu-system-mipsel -cpu ?”查看支持的cpu型号,简单来说就是在命令后面跟一个问号,就会把支持的所以cpu型号打印出来。如下

D:\VmShare\rt-thread\bsp\ls1cdev>qemu-system-mipsel -cpu ?MIPS '4Kc'MIPS '4Km'MIPS '4KEcR1'MIPS '4KEmR1'MIPS '4KEc'MIPS '4KEm'MIPS '24Kc'MIPS '24KEc'MIPS '24Kf'MIPS '34Kf'MIPS '74Kf'MIPS 'M14K'MIPS 'M14Kc'MIPS 'P5600'MIPS 'mips32r6-generic'


查看支持的Machine

使用命令“qemu-system-mipsel -M ?”或“qemu-system-mipsel -machine ?”查看支持的Machine

D:\VmShare\qemu_gdb_rtt_ls1c\bsp\ls1cdev>qemu-system-mipsel -machine ?Supported machines are:ar7-amd              MIPS AR7 with AMD flashar7                  MIPS 4KEc / AR7 platformfbox-4mb             FBox 4 MiB flash (AR7 platform)fbox-8mb             FBox 8 MiB flash (AR7 platform)malta                MIPS Malta Core LV (default)mips                 mips r4k platformmipsel               misp r4k platform (little endian)mipssim              MIPS MIPSsim platformnone                 empty machinesinus-basic-3        Sinus DSL Basic 3 (AR7 platform)sinus-basic-se       Sinus DSL Basic SE (AR7 platform)sinus-se             Sinus DSL SE (AR7 platform)speedport            Speedport (AR7 platform)tnetd7200            MIPS 4KEc / TNETD7200 platformtnetd7300            MIPS 4KEc / TNETD7300 platformD:\VmShare\qemu_gdb_rtt_ls1c\bsp\ls1cdev>qemu-system-mipsel -M ?Supported machines are:ar7-amd              MIPS AR7 with AMD flashar7                  MIPS 4KEc / AR7 platformfbox-4mb             FBox 4 MiB flash (AR7 platform)fbox-8mb             FBox 8 MiB flash (AR7 platform)malta                MIPS Malta Core LV (default)mips                 mips r4k platformmipsel               misp r4k platform (little endian)mipssim              MIPS MIPSsim platformnone                 empty machinesinus-basic-3        Sinus DSL Basic 3 (AR7 platform)sinus-basic-se       Sinus DSL Basic SE (AR7 platform)sinus-se             Sinus DSL SE (AR7 platform)speedport            Speedport (AR7 platform)tnetd7200            MIPS 4KEc / TNETD7200 platformtnetd7300            MIPS 4KEc / TNETD7300 platform


龙芯官方的qemu

龙芯官方有最新的,支持龙芯1c的qemu,使用上和qemu官网下载的有点区别,网盘(本文前面有链接)中有个简要的说明文档,串口信息通过vncviewer查看,但目前我始终未能看到串口打印,有会的欢迎留言分享,谢谢!

http://www.loongnix.org/dev/ftp/embed/ls1c/qemu-ls1c.tar.gz

http://www.loongnix.org/dev/ftp/embed/ls1b/simulator/qemu.pdf

这是龙芯qemu配套说明文档中的部分截图。另外把测试时使用的命令也贴上,仅供参考

export PATH=$PATH:/home/develop/test/qemu-ls1c/qemu386/binqemu-system-mipsel -M ls1c -serial vc -kernel bin/image.elf -gdb tcp::1234 -Starget remote localhost:1234symbol-file /mnt/hgfs/VmShare/qemu_gdb_mips_hello/bin/image.elfvncview 127.0.0.1:5900



原创粉丝点击