背景介绍,我正在在aarch64上运行裸机QEMU-4.1.0。
有几种方法可以让QEMU将编译好的代码加载到内存中。我想了解其中的根本区别,因为我看到了非常不同的行为,而文档并没有提供任何帮助。
考虑第一条命令行:
qemu-system-aarch64 \
-s -S \
-machine virt,secure=on,virtualization=on \
-m 512M \
-smp 4 \
-display none \
-nographic \
-semihosting \
-serial mon:stdio \
-kernel my_file.elf \
-device loader,addr=0x40004000,cpu_num=0 \
-device loader,addr=0x40004000,cpu_num=1 \
-device loader,addr=0x40004000,cpu_num=2 \
-device loader,addr=0x40004000,cpu_num=3 \
;
在另一个终端中,如果我启动gdb来查看QEMU加载到内存中的内容,它恰好对应我所期望的。事实上,gdb有一个内置命令可以做到这一点...
(gdb) compare-sections
Section .start, range 0x40004000 -- 0x40006164: matched.
Section .vectors, range 0x40006800 -- 0x40006f90: matched.
Section .text, range 0x40006fc0 -- 0x4002ca7c: matched.
...
Section .stacks, range 0x4207c120 -- 0x420bc120: matched.
(gdb) x/10x 0x40004000
0x40004000 <_start>: 0x14000800 0x00000000 0x00000000 0x00000000
...
太完美了!我的ELF文件中的所有内容都在0x40004000处,我在内存中看到了它们,就像我预期的那样!我的第一个核心启动并按照我预期的方式运行。
有趣的是,如果我转储内存中位置零的内容,那里面有一些加载的东西。我没有要求它,也没有明确加载它。我不执行它。它不在我的ELF文件中。我不知道它是什么或者它来自哪里。我猜测QEMU假设我想要一些BIOS在闪存中,并将其放在那里。我不能确定。它还在0x40000000处放置了一些东西(很小)。我也不知道那是什么...我希望小心一点,如果我加载了某些东西,我们不会互相干扰...
编辑:QEMU-7文档澄清了DTB放置在0x40000000(RAM的起始位置)。
- 那么我的第一个问题是:我能否启用一些调试消息来了解QEMU加载的位置以及可能的原因?
继续...
如果我更改命令行,用“-bios my_file.elf”开关替换“-kernel my_file.elf”开关(不更改其他任何内容),然后重复运行/gdb,那么我会看到两件不同的事情...
首先,我看到所有的内核都在运行。我不需要使用PSCI调用来启动它们。好吧,但我认为这与我的问题无关。其次(非常重要的是)我的内存不包含我期望的内容!
(gdb) compare-sections
Section .start, range 0x40004000 -- 0x40006164: MIS-MATCHED!
Section .vectors, range 0x40006800 -- 0x40006f90: MIS-MATCHED!
Section .text, range 0x40006fc0 -- 0x4002ca7c: MIS-MATCHED!
...
Section .stacks, range 0x4207c120 -- 0x420bc120: matched.
(gdb) x/8x 0x40000000
0x40004000 <_start>: 0x00000000 0x00000000 0x00000000 0x00000000
0x40004010 <_start+16>: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/8x 0x40006800
0x40006800 <my_vector_name>: 0x00000000 0x00000000 0x00000000 0x00000000
0x40006810 <my_vector_name+16>: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/8x 0x40006fc0
0x40006800 <my_symbol_name>: 0x00000000 0x00000000 0x00000000 0x00000000
0x40006810 <my_symbol_name+16>: 0x00000000 0x00000000 0x00000000 0x00000000
一切都是零。我看不到我的代码,尽管神秘的代码仍然在0x0和0x4000000处加载。正如你可能预料的那样,在我发出"gdb nexti"之后,内核立即因为"未定义指令"异常而死亡。
嗯...
好的,现在我将"-bios my_file.elf"更改为"-device loader,file=my_file.elf"。我得到了相同的结果。我无法在内存中找到我的代码。
- 在QEMU中,"-bios"和"-kernel"有什么不同?这在哪里有记录,或者我该如何跟踪源代码?我该如何最好地调试这个问题?
谢谢您,亲爱的先生/女士!
编辑:
为了调试,所有好的/相关的东西似乎都在“virt.c”中...
更多编辑(添加信息“-device loader=my_file.elf”)
我的命令行是:
/tools/gnu/qemu-4.1.0/bin/qemu-system-aarch64 \
-s -S \
-machine virt,secure=on,virtualization=on \
-cpu cortex-a53 \
-d int \
-m 512M \
-smp 4 \
-display none \
-nographic \
-semihosting \
-serial mon:stdio \
-device loader,file=NEW_AT_ZERO.elf \
;
以下是NEW_AT_ZERO.dis文件的相关部分:
NEW_AT_ZERO.elf: file format elf64-littleaarch64
NEW_AT_ZERO.elf
architecture: aarch64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000000000
Program Header:
LOAD off 0x0000000000010000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**16
filesz 0x00000000020b8120 memsz 0x00000000020b8120 flags rwx
NOTE off 0x0000000000043484 vaddr 0x0000000000033484 paddr 0x0000000000033484 align 2**2
filesz 0x0000000000000024 memsz 0x0000000000000024 flags r--
private flags = 0:
Sections:
Idx Name Size VMA LMA File off Algn
0 .start 00002164 0000000000000000 0000000000000000 00010000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .vectors 00000790 0000000000002800 0000000000002800 00012800 2**11
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .text 00025bbc 0000000000002fc0 0000000000002fc0 00012fc0 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
3 .bss 0000a904 0000000000028b80 0000000000028b80 00038b7c 2**3
ALLOC
....
Contents of section .start:
0000 00080014 00000000 00000000 00000000 ................
....
1000 fd170094 a00038d5 01044092 020c7892 ......8...@...x.
1010 261842aa 660000b5 00038052 00005ed4 &.B.f......R..^.
1020 7f2003d5 ffffff17 00000000 00000000 . ..............
....
...但当然...
GNU gdb (Linaro_GDB-2017.05.09) 7.12.1.20170417-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=aarch64-none-elf".
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"...
Remote debugging using localhost:1234
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x0000000000000000 in ?? ()
Reading symbols from ./NEW_AT_ZERO.elf...done.
(gdb) compare_sections
Undefined command: "compare_sections". Try "help".
(gdb) compare-sections
Section .start, range 0x0 -- 0x2164: MIS-MATCHED!
Section .vectors, range 0x2800 -- 0x2f90: MIS-MATCHED!
Section .text, range 0x2fc0 -- 0x28b7c: MIS-MATCHED!
....
Section .stacks, range 0x2078120 -- 0x20b8120: matched.
warning: One or more sections of the target image does not match
the loaded file
(gdb) x/4x 0
0x0 <_start>: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/12x 0x1000
0x1000 <symbol>: 0x00000000 0x00000000 0x00000000 0x00000000
0x1010 <symbol+16>: 0x00000000 0x00000000 0x00000000 0x00000000
0x1020 <end_symbol>: 0x00000000 0x00000000 0x00000000 0x00000000