我正在尝试创建一个简单的汇编程序,将其编译为.elf可执行文件,并使用qemu-system-riscv32
和gdb-multiarch
运行+调试它。
每当我尝试运行我的.elf时,我会遇到两个问题:
- qemu抱怨内存部分重叠:
The following two regions overlap (in the memory address space): out/hello_world.elf ELF program header segment 1 (addresses 0x000000007ffff000 - 0x0000000080000050)
/usr/local/bin/../share/qemu/opensbi-riscv32-generic-fw_dynamic.bin (addresses 0x0000000080000000 - 0x000000008001e0c0)
1.而且当我试图修复重叠问题时,我的main从未进入(和qemu存在)。GDB显示程序计数器/ PC开始时为0x 1004。当我继续的时候,我的b main
永远不会被击中。当I CTRL+Cgdb
指示qemu进程已退出,但除了远程gdb会话连接已丢失外,没有其他错误。
如前所述,我尝试在链接器定义文件中更改内存范围/入口点,使其不与risc-v中的opensbi重叠。
为了说明我的设置,这是我的hello_world.s:
.globl main
.type main, @function
main:
li a1, 1337
mv a0, zero
ret
.size main, .-main
qemu.s:
.section .init, "ax"
.global _start
_start:
.cfi_startproc
.cfi_undefined ra
.option push
.option norelax
la gp, __global_pointer$
.option pop
la sp, __stack_top
add s0, sp, zero
#jal zero, _start_continue
call main
.cfi_endproc
.end
Makefile:
CROSS_PREFIX=riscv32-unknown-elf-
INC=-I./src/
clean:
rm -f out/*.o out/*.elf
%:
# create output dir
mkdir -p out
# compile the assembly specified in the name
$(CROSS_PREFIX)as $(INC) -g -c src/qemu.s -o out/qemu.o
$(CROSS_PREFIX)as $(INC) -g -c src/$@.s -o out/$@.o
# link the assembly
$(CROSS_PREFIX)ld -Triscv32-virt.ld out/qemu.o out/$@.o -o out/$@.elf
我的调试脚本:
#!/usr/bin/env bash
SEQUENCE=$1
make ${SEQUENCE}
qemu-system-riscv32 -kernel out/${SEQUENCE}.elf -nographic -s -S -m 512M &
CHILD_PID=$!
gdb-multiarch -tui -q -ex "file out/${SEQUENCE}.elf" -ex "target remote 127.0.0.1:1234" -ex "layout asm" -ex "b main" -ex "ni"
kill -9 ${CHILD_PID}
(due对于ni
命令,GDB显示PC在0x 1004而不是0x 1000,但为什么qemu在0x 1000而不是ELF入口地址进入我的应用程序?)
我在以下答案的帮助下创建了ld
文件:How to debug cross-compiled QEMU program with GDB?
这导致了这样一个文件:
riscv32-virt.ld:
/* Script for -z combreloc */
/* Copyright (C) 2014-2023 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
"elf32-littleriscv")
OUTPUT_ARCH(riscv)
MEMORY
{
RAM (rwx) : ORIGIN = 0x80020000, LENGTH = 511M
RAM2 (rwx) : ORIGIN = 0x80000000, LENGTH = 128K
}
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", ORIGIN(RAM))); . = SEGMENT_START("text-segment", ORIGIN(RAM)) + SIZEOF_HEADERS;
PROVIDE(__stack_top = ORIGIN(RAM) + LENGTH(RAM));
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
*(.rela.ifunc)
}
.rela.plt :
{
*(.rela.plt)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(SORT(.text.sorted.*))
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf.em. */
*(.gnu.warning)
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 :
{
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
}
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.sframe : ONLY_IF_RO { *(.sframe) *(.sframe.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.sframe : ONLY_IF_RW { *(.sframe) *(.sframe.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
/* Thread Local Storage sections */
.tdata :
{
PROVIDE_HIDDEN (__tdata_start = .);
*(.tdata .tdata.* .gnu.linkonce.td.*)
}
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.data :
{
__DATA_BEGIN__ = .;
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
__SDATA_BEGIN__ = .;
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.sbss :
{
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we do not
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
__BSS_END__ = .;
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1. */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions. */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2. */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2. */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions. */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3. */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF 5. */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.debug_sup 0 : { *(.debug_sup) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
可以注意到,我将内存扩展到了512 M(因为我的测试需要这么多)。为此,我将-m 512M
赋值给qemu
,并在链接器定义文件中更改它。
一开始我有这个:
MEMORY
{
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 512M
}
但这造成了重叠误差。所以我尝试将ORIGIN移动到0x80020000
,但这使得我的代码在gdb会话期间永远不会输入。这同样适用于当前代码(因为可能qemu期望0x80000000
位置被Map):
MEMORY
{
RAM (rwx) : ORIGIN = 0x80020000, LENGTH = 511M
RAM2 (rwx) : ORIGIN = 0x80000000, LENGTH = 128K
}
我用readelf做了双重检查,检查条目地址是否正确,它确实正确!:
Elf file type is EXEC (Executable file)
Entry point 0x80020000
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
RISCV_ATTRIBUT 0x001050 0x00000000 0x00000000 0x0004c 0x00000 R 0x1
LOAD 0x000000 0x8001f000 0x8001f000 0x01050 0x01050 R E 0x1000
Section to Segment mapping:
Segment Sections...
00 .riscv.attributes
01 .init .text .eh_frame
相关软件的版本:
# make --version
GNU Make 4.3
Built for x86_64-pc-linux-gnu
# readelf --version
GNU readelf (GNU Binutils for Ubuntu) 2.38
# qemu-system-riscv32 --version
QEMU emulator version 8.0.2 (v8.0.2)
# gdb-multiarch --version
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
# riscv32-unknown-elf-as --version
GNU assembler (GNU Binutils) 2.40.0.20230214
# riscv32-unknown-elf-ld --version
GNU ld (GNU Binutils) 2.40.0.20230214
# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.2 LTS
Release: 22.04
Codename: jammy
这是在Windows 10 21 H2 19044.2604上的WSL 2上运行的。
我做错了什么,qemu不会进入我的入口点,也不会执行我的代码?
当我进入GDB时,我偶然发现了一条有趣的信息:
(gdb) maintenance info sections
Exec file: `/mnt/c/Users/nxf75132/Desktop/qrv32/out/hello_world.elf', file type elf32-littleriscv.
[0] 0x80020000->0x80020018 at 0x00001000: .init ALLOC LOAD READONLY CODE HAS_CONTENTS
[1] 0x80020018->0x80020024 at 0x00001018: .text ALLOC LOAD READONLY CODE HAS_CONTENTS
[2] 0x80020024->0x80020050 at 0x00001024: .eh_frame ALLOC LOAD READONLY DATA HAS_CONTENTS
[3] 0x0000->0x004c at 0x00001050: .riscv.attributes READONLY HAS_CONTENTS
[4] 0x0000->0x0040 at 0x000010a0: .debug_aranges READONLY HAS_CONTENTS
[5] 0x0000->0x005b at 0x000010e0: .debug_info READONLY HAS_CONTENTS
[6] 0x0000->0x0035 at 0x0000113b: .debug_abbrev READONLY HAS_CONTENTS
[7] 0x0000->0x0097 at 0x00001170: .debug_line READONLY HAS_CONTENTS
[8] 0x0000->0x0054 at 0x00001207: .debug_str READONLY HAS_CONTENTS
at
部分似乎指示.init部分的0x00001000
-我怀疑这可能是问题所在,但我如何修复这个问题?
当我执行gdb cat
和此命令时,所有起始地址似乎都与at
地址重叠(只有在某些情况下不匹配)。但是.init和.text部分采用预期格式,其中at
是起始地址(第二列0x... ->)。
编辑:使用以下命令运行其他调试时:
# qemu-system-riscv32 -D ./log.txt -kernel "out/hello_world.elf" -m 512M -monitor stdio -d cpu,exec,in_asm,nochain -singlestep
QEMU 8.0.2 monitor - type 'help' for more information
(qemu) VNC server running on 127.0.0.1:5900
quit # after some time (e.g. one minute)
我在log.txt中得到额外的调试,第一个条目是:
----------------
IN:
Priv: 3; Virt: 0
0x00001000: 00000297 auipc t0,0 # 0x1000
Trace 0: 0x7f5940000100 [00000000/00001000/00109003/ff000201]
V = 0
pc 00001000
mhartid 00000000
mstatus 00000000
mstatush 00000000
hstatus 00000000
vsstatus 00000000
mip 00000080
mie 00000000
mideleg 00000000
hideleg 00000000
medeleg 00000000
hedeleg 00000000
mtvec 00000000
stvec 00000000
vstvec 00000000
mepc 00000000
sepc 00000000
vsepc 00000000
mcause 00000000
scause 00000000
vscause 00000000
mtval 00000000
stval 00000000
htval 00000000
mtval2 00000000
mscratch 00000000
sscratch 00000000
satp 00000000
x0/zero 00000000 x1/ra 00000000 x2/sp 00000000 x3/gp 00000000
x4/tp 00000000 x5/t0 00000000 x6/t1 00000000 x7/t2 00000000
x8/s0 00000000 x9/s1 00000000 x10/a0 00000000 x11/a1 00000000
x12/a2 00000000 x13/a3 00000000 x14/a4 00000000 x15/a5 00000000
x16/a6 00000000 x17/a7 00000000 x18/s2 00000000 x19/s3 00000000
x20/s4 00000000 x21/s5 00000000 x22/s6 00000000 x23/s7 00000000
x24/s8 00000000 x25/s9 00000000 x26/s10 00000000 x27/s11 00000000
x28/t3 00000000 x29/t4 00000000 x30/t5 00000000 x31/t6 00000000
在此之后,PC上升到PC 0x 1014,在那里它执行jr,t0到0x 80000000。指令有时不对齐(例如,PC= 0x 8000004 e),这可能表明正在执行“垃圾”?
或者例如0x 8000005 e连续两次。
我让它运行了一段时间,它似乎陷入了0x 8000 d4 ca/0x 8000 d4 cc/0x 8000 d4 ce的某种循环(也在这个区域跳来跳去),从来没有到达我的main / startup代码。当我看到执行的指令时,对我来说它们没有逻辑意义:
0x00001000: 00000297 auipc t0,0 # 0x1000
0x00001004: 02828613 addi a2,t0,40
0x00001008: f1402573 csrrs a0,mhartid,zero
0x0000100c: 0202a583 lw a1,32(t0)
0x00001010: 0182a283 lw t0,24(t0)
0x00001014: 00028067 jr t0
0x80000000: 00050433 add s0,a0,zero
0x80000004: 000584b3 add s1,a1,zero
0x80000008: 00060933 add s2,a2,zero
0x8000000c: 2571 jal ra,1676 # 0x80000698
0x80000698: 494255b7 lui a1,1229082624
0x8000069c: 34f58593 addi a1,a1,847
0x800006a0: 4208 lw a0,0(a2)
0x800006a2: feb517e3 bne a0,a1,-18 # 0x80000690
0x800006a6: 4589 addi a1,zero,2
0x800006a8: 4248 lw a0,4(a2)
0x800006aa: fea5c3e3 bgt a0,a1,-26 # 0x80000690
0x800006ae: 4589 addi a1,zero,2
0x800006b0: 00b54463 bgt a1,a0,8 # 0x800006b8
0x800006b4: 4a48 lw a0,20(a2)
0x800006b6: 8082 ret
0x8000000e: 00050833 add a6,a0,zero
0x80000012: 00040533 add a0,s0,zero
0x80000016: 000485b3 add a1,s1,zero
0x8000001a: 00090633 add a2,s2,zero
0x8000001e: 58fd addi a7,zero,-1
0x80000020: 01180463 beq a6,a7,8 # 0x80000028
0x80000024: 0b051d63 bne a0,a6,186 # 0x800000de
0x80000028: 0001c817 auipc a6,114688 # 0x8001c028
0x8000002c: fdc80813 addi a6,a6,-36
0x80000030: 4885 addi a7,zero,1
0x80000032: 0118282f amoadd.w a6,a7,(a6)
0x80000036: 0a081463 bnez a6,168 # 0x800000de
0x8000003a: 0001c297 auipc t0,114688 # 0x8001c03a
0x8000003e: fd228293 addi t0,t0,-46
0x80000042: 00000317 auipc t1,0 # 0x80000042
0x80000046: fbe30313 addi t1,t1,-66
0x8000004a: 0062a023 sw t1,0(t0)
0x8000004e: 0001c297 auipc t0,114688 # 0x8001c04e
0x80000052: fc228293 addi t0,t0,-62
0x80000056: 0002a283 lw t0,0(t0)
0x8000005a: 405303b3 sub t2,t1,t0
0x8000005e: 0001ce17 auipc t3,114688 # 0x8001c05e
0x80000062: fa2e0e13 addi t3,t3,-94
0x80000066: 007e2023 sw t2,0(t3)
0x8000006a: 0001d297 auipc t0,118784 # 0x8001d06a
0x8000006e: 06e28293 addi t0,t0,110
0x80000072: 0001e317 auipc t1,122880 # 0x8001e072
0x80000076: 04e30313 addi t1,t1,78
0x8000007a: 06628363 beq t0,t1,102 # 0x800000e0
0x8000007e: a8a1 j 88 # 0x800000d6
0x800000d6: 02b1 addi t0,t0,12
0x800000d8: fa5354e3 ble t0,t1,-88 # 0x80000080
0x80000080: ff82af03 lw t5,-8(t0)
0x80000084: 4e0d addi t3,zero,3
0x80000086: 01cf1b63 bne t5,t3,22 # 0x8000009c
0x8000008a: ff42ae03 lw t3,-12(t0)
0x8000008e: ffc2af03 lw t5,-4(t0)
0x80000092: 9f1e add t5,t5,t2
0x80000094: 9e1e add t3,t3,t2
0x80000096: 01ee2023 sw t5,0(t3)
0x8000009a: a835 j 60 # 0x800000d6
0x800000dc: a011 j 4 # 0x800000e0
0x800000e0: 0001c297 auipc t0,114688 # 0x8001c0e0
0x800000e4: f2828293 addi t0,t0,-216
0x800000e8: 4305 addi t1,zero,1
0x800000ea: 0062a023 sw t1,0(t0)
0x800000ee: 0330000f fence rw,rw
0x800000f2: 4081 mv ra,zero
0x800000f4: 2bb1 jal ra,1372 # 0x80000650
0x80000650: 0000100f fence.i
0x80000654: 4101 mv sp,zero
0x80000656: 4181 mv gp,zero
0x80000658: 4201 mv tp,zero
0x8000065a: 4281 mv t0,zero
0x8000065c: 4301 mv t1,zero
0x8000065e: 4381 mv t2,zero
0x80000660: 4401 mv s0,zero
0x80000662: 4481 mv s1,zero
0x80000664: 4681 mv a3,zero
0x80000666: 4701 mv a4,zero
0x80000668: 4781 mv a5,zero
0x8000066a: 4801 mv a6,zero
0x8000066c: 4881 mv a7,zero
0x8000066e: 4901 mv s2,zero
0x80000670: 4981 mv s3,zero
0x80000672: 4a01 mv s4,zero
0x80000674: 4a81 mv s5,zero
0x80000676: 4b01 mv s6,zero
0x80000678: 4b81 mv s7,zero
0x8000067a: 4c01 mv s8,zero
0x8000067c: 4c81 mv s9,zero
0x8000067e: 4d01 mv s10,zero
0x80000680: 4d81 mv s11,zero
0x80000682: 4e01 mv t3,zero
0x80000684: 4e81 mv t4,zero
0x80000686: 4f01 mv t5,zero
0x80000688: 4f81 mv t6,zero
(...)
1条答案
按热度按时间nafvub8i1#
“解决方案”(还是变通方案?)是使用另一个qemu“板”--机器,因为它被称为。默认值似乎不是Spike,我试过VirtIO:
更改debug.sh:
以及链接器定义存储器部分定义:
我不知道 * 为什么 * 它工作,如果这是一个真实的的 * 解决方案 *,但现在它似乎是一个很好的解决方案。如果有人能插话,比我更有把握地纠正这些错误,我会接受这样的回答。
我的想法是绕过固件(根本没有任何固件)。我不知道缺乏固件的影响。