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.

以及,调试完似乎并没有什么收获...

posted @ 2024-12-31 23:25  daydalek  阅读(73)  评论(0)    收藏  举报