gpt4 book ai didi

QEMU "-bios"对比 "-kernel"对比 "-device loader,file=..."

转载 作者:行者123 更新时间:2023-12-02 02:53:06 27 4
gpt4 key购买 nike

作为背景,我在 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 \
;

在另一个 shell 中,如果我启动 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 正在加载的位置,甚至可能是为什么?

  • 继续...
    如果我将命令行更改为用“-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

    最佳答案

    QEMU 用于将代码加载到 guest 中的命令行选项是多种多样的,并且通常在架构之间甚至同一架构的机器类型之间具有不同的语义。这是不幸的,但这是与旧 QEMU 版本的向后兼容以及“为这种图像文件类型做正确的事情会很好”特殊情况的逐渐积累的结果。

    概括总结:

    -kernel 是“加载 Linux 内核”选项。它将以最适合所用架构的任何方式加载和引导内核。例如,对于 x86 PC 机器,它只会将文件提供给 guest BIOS,并依靠 guest BIOS 将文件实际加载到 RAM 中。在 Arm 上,加载 Linux 内核意味着我们遵循内核为如何引导它制定的规则(https://www.kernel.org/doc/Documentation/arm64/booting.txt 用于 64 位或 https://www.kernel.org/doc/Documentation/arm/Booting 用于 32 位),我们通过一些 stub 来实现引导加载程序代码(这是您在低内存中看到的)。内核引导规则还要求我们在 RAM 中为它提供一个设备树 blob,这是 0x40000000 处的数据。我们还根据 Linux 内核引导预期,通过将辅助 CPU 保持在 PSCI 断电状态或通过使用 WFI 循环的少量辅助 CPU 引导加载程序代码来处理辅助 CPU,以便主 CPU 可以唤醒它们。 (我们做什么取决于所使用的板卡型号,因为我们做的是真正的板卡,特别是对于 32 位板卡变化很大。)

    作为一个奇怪的异常(exception),对于 Arm,如果您将 ELF 文件传递​​给 -kernel,我们将假定它不是 Linux 内核,并且将通过仅从 ELF 入口点启动来启动它。我们在 RAM 的基础上提供 DTB blob,但前提是它不会与加载的 ELF 文件重叠。 (另外:对于 'virt' 特别是无论如何你都想要 DTB,因为我们不保证在 QEMU 版本之间将设备保持在相同的物理地址——DTB 是我们告诉 guest 代码它应该在哪里寻找东西的方式。你可以依靠 0x0 处的闪存和 0x4000_0000 处开始的 RAM,但确实应该从 DTB 中提取所有其他设备地址。在实践中,我们已经努力避免重新排列板内存映射,但读取 DTB 对访客代码来说是正确的做。)

    -device loader 是“通用加载器”,它在任何架构上的行为都相同。它只是将一个 ELF 镜像加载到客户 RAM 中,并没有做任何改变 CPU 重置行为的事情。如果您有一个包含异常向量表的完全裸机镜像并希望它以硬件不复位的相同方式启动,这是一个不错的选择。

    -bios 是“加载 bios 镜像,无论以何种方式对该机器型号似乎都有利”选项。同样,这是一种“按我的意思行事”的选项,其细节因机器模型和机器模型而异;有些机器根本不支持它。某些机器(例如 x86 PC)将始终加载 bios,如果用户未指定,则使用默认二进制文件。如果用户要求,有些会加载 bios,但不是其他情况(arm virt 板就是这样)。通常,BIOS 镜像应该是“裸机原始二进制”镜像,它将被加载到一些闪存或 ROM 存储器中,这对应于硬件在复位后开始执行的位置。至少在某些机器上,包括“virt”,您可以改为使用“-drive if=pflash,...”之类的命令行来提供闪存/ROM 设备的内容。这是 QEMU 中常见模式的一个示例,您可以使用简短的“按我的意思做”选项,该选项很方便但背后有很多魔力,或者使用更长的“正交”选项,让您指定很多子选项并获得您想要的行为。请注意,BIOS 镜像不应是 ELF 文件,它们应该只是放入 ROM 的原始数据。

    其中很多是未记录的,因为“我想运行我自己设计的裸机程序”是一个非常小众的用例,而且因为我们的文档中没有很好的位置来轻松记录不同的板型号。

    关于QEMU "-bios"对比 "-kernel"对比 "-device loader,file=...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58420670/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com