THU-rCore 操作系统实验日寄 -2
THU-rCore 操作系统实验踩坑日寄 -2
PART 2
第二章主要涉及单道的批处理和特权级的部分,尚不涉及多道程序设计。
早先一直提到的RustSBI,实为一个Rust的riscv supervisor binary interface。
若按中科院软件所维护的中文版RISC-V Manual翻译,就应该作“RISC-V 监管器(SuperVisor)二进制(Binary)接口(Interface)”。
RISC-V的标准ISA手册分为特权级和非特权级两册。在特权级(priv-isa-asciidoc)手册中可以查得,
RISC-V一共用两位编码定义了四种特权级别。
其中在RISC-V手册里,10所对应的HyperVisor(超级监管级)似乎还在留空的状态,
不过既然为“Hyper”,想必是个比SuperVisor权力更大的等级。
| 级别 | 编码 | 名称 | 缩写 |
|---|---|---|---|
| 0 | 00 | 用户(User)/应用(Application) | U |
| 1 | 01 | 监管器(SuperVisor) | S |
| 2 | 10 | HyperVisor(尚未完全制定好) | H |
| 3 | 11 | 机器(Machine) | M |
RISC-V的访管指令是ecall,Manual中的描述是:“ECALL指令用于向执行环境发出请求,当在U模式、S模式或M模式
下执行时,分别生成一个environment-call-from-U-mode异常、environment-call-from-S-mode异常
或者environment-call-from-M-mode异常” (查这部分的时候发现这里的中文手册翻译还有错,已提issue)。
来看user/bin下的几个用户态程序。用户态程序所使用的syscall是在user/src/lib.rs中提供的。在user/Cargo.toml中指明了该package名为user_lib,
因此在用户程序里是通过extern crate user_lib使用的。
user/bin/00hello_world.rs是一个平平无奇的hello world程序,而01store_fault.rs开始就比较有意思了,它试图往0地址写入,这时就会导致程序连带Qemu一起被
Linux Kernel杀死。03和04两个试图访问在用户态下访问管态的程序,也会招致相同的结果。
qemu-riscv64 ./03priv_inst
Try to execute privileged instruction in U Mode
Kernel should kill this application!
Illegal instruction (core dumped)
user/Makefile中给出了如下内容
TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
elf:
@cargo build --release
binary: elf
@$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
build: binary
由于想用gdb调试一下生成的程序,故我作出如下修改
-MODE :=release
+MODE :=debug
-elf:
- @cargo build --release
+elf:
+ @cargo build
然后
make elf
来尝试生成带有调试信息的debug版。
然而使用riscv64-unknown-elf-gdb尝试调试时,得到的结果却是
Reading symbols from 02power...
(No debugging symbols found in 02power)
没有找到调试信息...
这个问题直到我看到linker.ld的时候才有了眉目
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x80400000;
SECTIONS
{
. = BASE_ADDRESS;
.text : {
*(.text.entry)
*(.text .text.*)
}
.rodata : {
*(.rodata .rodata.*)
*(.srodata .srodata.*)
}
.data : {
*(.data .data.*)
*(.sdata .sdata.*)
}
.bss : {
start_bss = .;
*(.bss .bss.*)
*(.sbss .sbss.*)
end_bss = .;
}
/DISCARD/ : {
*(.eh_frame)
*(.debug*)
}
}
虽然看不太懂,但是我贫瘠的英语储备还是告诉我这个DISCARD一定有问题。
删掉这部分之后,果然gdb就能读取到附加的调试信息
Type "apropos word" to search for commands related to "word"...
Reading symbols from 00hello_world...
残念的是,qemu-system-riscv64的-s和-S选项对qemu-riscv64来说似乎无用,不过with the help of ChatGPT,还是知道了透过qemu-riscv64 -g 1234 program_name就可让它在启动时暂停并等待1234端口的传入连接。之后
riscv64-unknown-elf-gdb \
-ex 'file target/riscv64gc-unknown-none-elf/debug/00hello_world' \
-ex 'set arch riscv:rv64' \
-ex 'target remote localhost:1234'
就可以愉快进行调试了。
(gdb) break main
Breakpoint 1 at 0x8040018a: file src/bin/02power.rs, line 14.
以及,调试完似乎并没有什么收获...

浙公网安备 33010602011771号