QEMU + ARMv8 环境搭建

QEMU + ARMv8 环境搭建


1.实验平台

1.1 安装一些必要的工具

$ sudo apt update -y
$ sudo apt install net-tools libncurses5-dev libssl-dev build-essential openssl qemu-system-arm libncurses5-dev gcc-aarch64-linux-gnu git bison flex bc vim universal-ctags cscope cmake python3-dev gdb-multiarch openjdk-13-jre trace-cmd kernelshark bpfcc-tools cppcheck docker docker.io libelf-dev gcc-7 xterm curl clang exuberant-ctags python-is-python3
$ sudo apt build-dep linux-image-generic

1.2 安装QEMU3 以上版本

1.下载qemu源码

wget https://download.qemu.org/qemu-4.2.0-rc1.tar.xz
tar xvJf qemu-4.2.0-rc1.tar.xz

2.配置qemu前需要安装的软件包:

apt-get install zlib1g zlib1g-dev
apt-get install libglib2.0-dev
apt-get install libpixman-1-dev

3.进入qemu解压目录,运行./configure配置qemu,支持模拟arm架构下的所有单板

./configure --target-list=arm-softmmu --audio-drv-list=

4.编译并安装

make 
make install

当前我安装的6.2.0版本。运行qemu查看版本

~/armv8_trainning$  qemu-system-aarch64 --version
QEMU emulator version 6.2.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

5.安装调试工具

 sudo apt-get install gdb-multiarch

可以看下支持的Machine:

~/armv8_trainning$ qemu-system-aarch64 -M help
Supported machines are:
akita                Sharp SL-C1000 (Akita) PDA (PXA270)
ast2500-evb          Aspeed AST2500 EVB (ARM1176)
ast2600-evb          Aspeed AST2600 EVB (Cortex-A7)
borzoi               Sharp SL-C3100 (Borzoi) PDA (PXA270)
canon-a1100          Canon PowerShot A1100 IS (ARM946)
cheetah              Palm Tungsten|E aka. Cheetah PDA (OMAP310)
collie               Sharp SL-5500 (Collie) PDA (SA-1110)
connex               Gumstix Connex (PXA255)
cubieboard           cubietech cubieboard (Cortex-A8)
emcraft-sf2          SmartFusion2 SOM kit from Emcraft (M2S010)
fp5280g2-bmc         Inspur FP5280G2 BMC (ARM1176)
fuji-bmc             Facebook Fuji BMC (Cortex-A7)
g220a-bmc            Bytedance G220A BMC (ARM1176)
highbank             Calxeda Highbank (ECX-1000)
imx25-pdk            ARM i.MX25 PDK board (ARM926)
integratorcp         ARM Integrator/CP (ARM926EJ-S)
kudo-bmc             Kudo BMC (Cortex-A9)
kzm                  ARM KZM Emulation Baseboard (ARM1136)
lm3s6965evb          Stellaris LM3S6965EVB (Cortex-M3)
lm3s811evb           Stellaris LM3S811EVB (Cortex-M3)
mainstone            Mainstone II (PXA27x)
mcimx6ul-evk         Freescale i.MX6UL Evaluation Kit (Cortex-A7)
mcimx7d-sabre        Freescale i.MX7 DUAL SABRE (Cortex-A7)
microbit             BBC micro:bit (Cortex-M0)
midway               Calxeda Midway (ECX-2000)
mps2-an385           ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an386           ARM MPS2 with AN386 FPGA image for Cortex-M4
mps2-an500           ARM MPS2 with AN500 FPGA image for Cortex-M7
mps2-an505           ARM MPS2 with AN505 FPGA image for Cortex-M33
mps2-an511           ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
mps2-an521           ARM MPS2 with AN521 FPGA image for dual Cortex-M33
mps3-an524           ARM MPS3 with AN524 FPGA image for dual Cortex-M33
mps3-an547           ARM MPS3 with AN547 FPGA image for Cortex-M55
musca-a              ARM Musca-A board (dual Cortex-M33)
musca-b1             ARM Musca-B1 board (dual Cortex-M33)
musicpal             Marvell 88w8618 / MusicPal (ARM926EJ-S)
n800                 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810                 Nokia N810 tablet aka. RX-44 (OMAP2420)
netduino2            Netduino 2 Machine (Cortex-M3)
netduinoplus2        Netduino Plus 2 Machine (Cortex-M4)
none                 empty machine
npcm750-evb          Nuvoton NPCM750 Evaluation Board (Cortex-A9)
nuri                 Samsung NURI board (Exynos4210)
orangepi-pc          Orange Pi PC (Cortex-A7)
palmetto-bmc         OpenPOWER Palmetto BMC (ARM926EJ-S)
quanta-gbs-bmc       Quanta GBS (Cortex-A9)
quanta-gsj           Quanta GSJ (Cortex-A9)
quanta-q71l-bmc      Quanta-Q71l BMC (ARM926EJ-S)
rainier-bmc          IBM Rainier BMC (Cortex-A7)
raspi0               Raspberry Pi Zero (revision 1.2)
raspi1ap             Raspberry Pi A+ (revision 1.1)
raspi2b              Raspberry Pi 2B (revision 1.1)
raspi3ap             Raspberry Pi 3A+ (revision 1.0)
raspi3b              Raspberry Pi 3B (revision 1.2)
realview-eb          ARM RealView Emulation Baseboard (ARM926EJ-S)
realview-eb-mpcore   ARM RealView Emulation Baseboard (ARM11MPCore)
realview-pb-a8       ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9      ARM RealView Platform Baseboard Explore for Cortex-A9
romulus-bmc          OpenPOWER Romulus BMC (ARM1176)
sabrelite            Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9)
sbsa-ref             QEMU 'SBSA Reference' ARM Virtual Machine
smdkc210             Samsung SMDKC210 board (Exynos4210)
sonorapass-bmc       OCP SonoraPass BMC (ARM1176)
spitz                Sharp SL-C3000 (Spitz) PDA (PXA270)
stm32vldiscovery     ST STM32VLDISCOVERY (Cortex-M3)
supermicrox11-bmc    Supermicro X11 BMC (ARM926EJ-S)
swift-bmc            OpenPOWER Swift BMC (ARM1176) (deprecated)
sx1                  Siemens SX1 (OMAP310) V2
sx1-v1               Siemens SX1 (OMAP310) V1
tacoma-bmc           OpenPOWER Tacoma BMC (Cortex-A7)
terrier              Sharp SL-C3200 (Terrier) PDA (PXA270)
tosa                 Sharp SL-6000 (Tosa) PDA (PXA255)
verdex               Gumstix Verdex (PXA270)
versatileab          ARM Versatile/AB (ARM926EJ-S)
versatilepb          ARM Versatile/PB (ARM926EJ-S)
vexpress-a15         ARM Versatile Express for Cortex-A15
vexpress-a9          ARM Versatile Express for Cortex-A9
virt-2.10            QEMU 2.10 ARM Virtual Machine
virt-2.11            QEMU 2.11 ARM Virtual Machine
virt-2.12            QEMU 2.12 ARM Virtual Machine
virt-2.6             QEMU 2.6 ARM Virtual Machine
virt-2.7             QEMU 2.7 ARM Virtual Machine
virt-2.8             QEMU 2.8 ARM Virtual Machine
virt-2.9             QEMU 2.9 ARM Virtual Machine
virt-3.0             QEMU 3.0 ARM Virtual Machine
virt-3.1             QEMU 3.1 ARM Virtual Machine
virt-4.0             QEMU 4.0 ARM Virtual Machine
virt-4.1             QEMU 4.1 ARM Virtual Machine
virt-4.2             QEMU 4.2 ARM Virtual Machine
virt-5.0             QEMU 5.0 ARM Virtual Machine
virt-5.1             QEMU 5.1 ARM Virtual Machine
virt-5.2             QEMU 5.2 ARM Virtual Machine
virt-6.0             QEMU 6.0 ARM Virtual Machine
virt-6.1             QEMU 6.1 ARM Virtual Machine
virt                 QEMU 6.2 ARM Virtual Machine (alias of virt-6.2)
virt-6.2             QEMU 6.2 ARM Virtual Machine
witherspoon-bmc      OpenPOWER Witherspoon BMC (ARM1176)
xilinx-zynq-a9       Xilinx Zynq Platform Baseboard for Cortex-A9
xlnx-versal-virt     Xilinx Versal Virtual development board
xlnx-zcu102          Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on the value of smp
z2                   Zipit Z2 (PXA27x)

我们实验raspi3b作为实验平台,来进行实验。raspi3b 的CPU是AARCH64的,可以验证ARMv8代码。

2. qemu运行

1.qemu常用命令说明

  • -M 指定qemu所运行的board
  • -m 1024M 单板运行物理内存512M
  • -kernel 告诉qemu单板运行内核镜像路径
  • -nographic 不使用图形化界面,只使用串口
  • -append “console=ttyAMA0” 内核启动参数,这里告诉内核board运行,串口设备是哪个tty。
  • -sd xx.ext4,这个指的是绝对路径,指定rootfs
  • -S:便是qemu虚拟机会冻结cpu,直到远程的gdb输入相应的控制命令
  • -s:表示在1234端口接受gdb的调试连接

2.通过-kernel 参数直接指定一个bin文件来运行裸机代码

qemu-system-aarch64  -machine raspi3b -kernel armv8-test01.bin

3.通过-S -s加上端口,用于gdb 连接debug

qemu-system-aarch64  -machine raspi3b -kernel armv8-test01.bin-S -s

4.有时也可以用arm virt这个machine来做实验。使用命令:

$qemu-system-aarch64 -cpu cortex-a57 -smp 16 -m 1G -machine virt,gic-version=3,virtualization=on,its=off -nographic -netdev user,id=net -device virtio-net-device,netdev=net -fsdev local,id=r,path=/home/newdisk/jailhouse/kernel/linux-5.0/share,security_model=none -device virtio-9p-device,fsdev=r,mount_tag=r  -kernel arch/arm64/boot/Image --append "rdinit=/linuxrc console=ttyAMA0 root=/dev/vda1 mem=768M"

这里通过如下参数添加了一个共享目录:~/linux-5.0/share

-fsdev local,id=r,path=~linux-5.0/share,security_model=none -device virtio-9p-device,fsdev=r,mount_tag=r

qemu guest 启动后,运行如下命令挂载共享目录:

mount -t 9p -o trans=virtio r /mnt

这样qemu guest和host就能通过共享目录通信了。

3. 使用gdb调试

参考: https://www.jianshu.com/p/b7896e9afeb7

GDB是一个由GNU开源组织发布的、UNIX/Linux操作系统下的、基于命令行的、功能强大的程序调试工具。

一般来说,GDB主要帮忙你完成下面四个方面的功能:

  1. 启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
  2. 可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
  3. 当程序被停住时,可以检查此时你的程序中所发生的事。
  4. 动态的改变你程序的执行环境。
3.1 运行步骤
  1. qemu运行xx.bin,并带上-S -s参数等待gdb连接

    qemu-system-aarch64  -machine raspi3b -kernel armv8-test01.bin-S -s
    
  2. 另一个窗口运行gdb ,指定elf文件

    gdb-multiarch --tui benos.elf
    

    进入gdb调试窗口。连接localhost:1234

    target remote localhost:1234
    

    然后,就可以执行gdb命令了。如先打断点:

    b  _start
    

    使用命令c (continue)执行到打断点的位置了。

3.2 常用的gdb命令

调用Gdb编译需要在CC后面加上-g 参数再加-o

  1. file <文件名>

    加载被调试的可执行程序文件。因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径。

    (gdb) file file-name
    
  2. attach
    关联指定进程。

    (gdb) attach 1024 //关联进程号为1024的进程进行调试
    
  3. l

    List的简写,列出当前位置之后的10行代码;list line_number: 列出line_number之后的十行代码。

    (gdb) l
    
  4. r
    Run的简写,运行被调试的程序。如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。

    (gdb) r
    
  5. c
    Continue的简写,继续执行被调试程序,直至下一个断点或程序结束。

    (gdb) c
    
  6. b

  • b <函数名称>

  • b <函数名称>

  • b <代码地址>

  • d [编号]*

    b是Breakpoint的简写,设置断点。两可以使用“行号”“函数名称”“执行地址”等方式指定断点位置。
    其中在函数名称前面加*符号表示将断点设置在“由编译器生成的prolog代码处”。如果不了解汇编,可以不予理会此用法。

break ... if ...:条件中断。

d 是Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。
(gdb) b 8
(gdb) b main
(gdb) b *main
(gdb) b *0x804835c
(gdb) d
  1. clear
    clear 用于删除断点。

    • clear 删除所有断点
    • clear 行号 删除指定行断点
    • clear 函数名 删除函数断点
    (gdb)b _start
    (gdb)b 2
    (gdb)b 5
    (gdb)clear 5
    
  2. bt
    backtrace的简写,列出调用栈。

    (gdb) bt
    
  3. s
    执行一行源程序代码,如果此行代码中有函数调用,则进入该函数。相当于其它调试器中的“Step Into (单步跟踪进入)”。
    这个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。

    (gdb) s
    
  4. si

    si命令类似于s命令,但针对汇编指令。

    (gdb) si
    
  5. n

    执行一行源程序代码,此行代码中的函数调用也一并执行。相当于其它调试器中的“Step Over (单步跟踪)”。
    这个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。

    (gdb) n
    
  6. ni

    ni命令类似于n命令,但针对汇编指令。

    (gdb) ni
    
  7. p <变量名称>

    Print的简写,显示指定变量(临时变量或全局变量)的值。

    (gdb) p i
    (gdb) p &nGlobalVar
    
  8. x
    和print命令需要指定变量不同,x命令需要指定内存地址。

    (gdb) help x
    Examine memory: x/FMT ADDRESS.
    ADDRESS is an expression for the memory address to examine.
    FMT is a repeat count followed by a format letter and a size letter.
    Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
      t(binary), f(float), a(address), i(instruction), c(char) and s(string).
    Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
    The specified number of objects of the specified size are printed
    according to the format.
    Defaults for format and size letters are those previously used.
    Default count is 1.  Default address is following last thing printed
    with this command or "print".
    (gdb) x /6cb 0x804835c //打印地址0x804835c起始的内存内容,连续6个字节,以字符格式输出。
    
  9. display …
    undisplay <编号>

    display,设置程序中断后欲显示的数据及其格式。

    例如,如果希望每次程序中断后可以看到即将被执行的下一条汇编指令,可以使用命令display /i $pc,其中 $pc 代表当前汇编指令,/i 表示以十六进行显示。当需要关心汇编代码时,此命令相当有用。

    undispaly,取消先前的display设置,编号从1开始递增。

    (gdb) display /i $pc
    (gdb) undisplay 1
    
  10. i
    Info的简写,用于显示各类信息,详情请查阅“help i”。

    (gdb) help i
    info address -- Describe where symbol SYM is stored
    info all-registers -- List of all registers and their contents
    info args -- Argument variables of current stack frame
    info auto-load -- Print current status of auto-loaded files
    info auto-load-scripts -- Print the list of automatically loaded Python scripts
    info auxv -- Display the inferior's auxiliary vector
    info bookmarks -- Status of user-settable bookmarks
    info breakpoints -- Status of specified breakpoints (all user-settable breakpoints if no argument)
    info checkpoints -- IDs of currently known checkpoints
    info classes -- All Objective-C classes
    info common -- Print out the values contained in a Fortran COMMON block
    info copying -- Conditions for redistributing copies of GDB
    info dcache -- Print information on the dcache performance
    info display -- Expressions to display when program stops
    info extensions -- All filename extensions associated with a source language
    info files -- Names of targets and files being debugged
    info float -- Print the status of the floating point unit
    info frame -- All about selected stack frame
    info frame-filter -- List all registered Python frame-filters
    info functions -- All function names
    info handle -- What debugger does when program gets various signals
    info inferiors -- IDs of specified inferiors (all inferiors if no argument)
    info line -- Core addresses of the code for a source line
    info locals -- Local variables of current stack frame
    info macro -- Show the definition of MACRO
    info macros -- Show the definitions of all macros at LINESPEC
    info mem -- Memory region attributes
    info os -- Show OS data ARG
    info pretty-printer -- GDB command to list all registered pretty-printers
    info probes -- Show available static probes
    info proc -- Show /proc process information about any running process
    info program -- Execution status of the program
    info record -- Info record options
    info registers -- List of integer registers and their contents
    info scope -- List the variables local to a scope
    info selectors -- All Objective-C selectors
    info set -- Show all GDB settings
    info sharedlibrary -- Status of loaded shared object libraries
    info signals -- What debugger does when program gets various signals
    info skip -- Display the status of skips
    info source -- Information about the current source file
    info sources -- Source files in the program
    info stack -- Backtrace of the stack
    info static-tracepoint-markers -- List target static tracepoints markers
    info symbol -- Describe what symbol is at location ADDR
    info target -- Names of targets and files being debugged
    info tasks -- Provide information about all known Ada tasks
    info terminal -- Print inferior's saved terminal status
    info threads -- Display currently known threads
    info tracepoints -- Status of specified tracepoints (all tracepoints if no argument)
    info tvariables -- Status of trace state variables and their values
    info type-printers -- GDB command to list all registered type-printers
    info types -- All type names
    info variables -- All global and static variable names
    info vector -- Print the status of the vector unit
    info vtbl -- Show the virtual function table for a C++ object
    info warranty -- Various kinds of warranty you do not have
    info watchpoints -- Status of specified watchpoints (all watchpoints if no argument)
    info win -- List of all displayed windows
    (gdb) i r
    
  1. q

    Quit的简写,退出GDB调试环境。

    (gdb) q
    
  2. help [命令名称]

    GDB帮助命令,提供对GDB名种命令的解释说明。
    如果指定了“命令名称”参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。

    (gdb) help display
    
  3. layout

    • layout src : Displays source and command windows.
    • layout asm : Displays disassembly and command windows.
    • layout split : Displays source, disassembly and command windows.
    • layout regs : Displays register window. If existing layout
    • layout prev
    • layout next

    在gdb窗口显示如上信息。

    (gdb) layout regs //在gdb窗口显示所有寄存器
    

学会使用帮助文档

上述的命令其实都有更复杂的使用方法,可以通过help命令查看帮助,比如我们使用help p查看print命令的详细说明。

(gdb) help p
Print value of expression EXP.
Variables accessible are those of the lexical environment of the selected
stack frame, plus all those whose scope is global or an entire file.

$NUM gets previous value number NUM.  $ and $$ are the last two values.
$$NUM refers to NUM'th value back from the last one.
Names starting with $ refer to registers (with the values they would have
if the program were to return to the stack frame now selected, restoring
all registers saved by frames farther in) or else to debugger
"convenience" variables (any such name not a known register).
Use assignment expressions to give values to convenience variables.

{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.
@ is a binary operator for treating consecutive data objects
anywhere in memory as an array.  FOO@NUM gives an array whose first
element is FOO, whose second element is stored in the space following
where FOO is stored, etc.  FOO must be an expression whose value
resides in memory.

EXP may be preceded with /FMT, where FMT is a format letter
but no count or size letter (see "x" command).

上述帮助文档提到@参数,这个参数可以让你像查看数组内容一样打印连续内存的数据对象。“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:

int *array = (int *) malloc (len * sizeof (int));

于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:

(gdb) p *array@len
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老衲不依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值