Open OccupyMars2025 opened 1 year ago
os/src/logging.rs
to user/src/logging.rs
to enable colorful logging in app programs// user/src/lib.rs
pub extern "C" fn _start() -> ! {
logging::init();
info!("Enter user/src/lib.rs _start() ");
clear_bss();
exit(main());
panic!("unreachable after sys_exit!");
}
logging::init();
to every function just like the following code. It is a little tedious// user/src/lib.rs
pub fn exit(exit_code: i32) -> isize {
logging::init();
debug!("Enter user/src/lib.rs exit() ");
sys_exit(exit_code)
}
// user/src/logging.rs
let color = match record.level() {
Level::Error => 31, // Red
Level::Warn => 93, // BrightYellow
// Level::Info => 34, // Blue
Level::Info => 41, // background in red
// Level::Debug => 32, // Green
Level::Debug => 43, // background in gray
// Level::Trace => 90, // BrightBlack
Level::Trace => 46, // background in green
};
// os/src/console.rs
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
for c in s.chars() {
console_putchar(c as usize);
}
Ok(())
}
}
// user/src/console.rs
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
write(STDOUT, s.as_bytes());
Ok(())
}
}
In my current understanding, GDB can only show source code with debug-mode compiled code when "stepping" the excutable.
app_0_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/00hello_world.bin"
app_0_end:
if you use cd os
and make run
, you can get the following:
if you use cd os
and LOG=TRACE make run
, you can get the following:
option_env!
:// user/src/logging.rs
pub fn init() {
static LOGGER: SimpleLogger = SimpleLogger;
log::set_logger(&LOGGER).unwrap();
log::set_max_level(match option_env!("LOG") {
Some("ERROR") => LevelFilter::Error,
Some("WARN") => LevelFilter::Warn,
Some("INFO") => LevelFilter::Info,
Some("DEBUG") => LevelFilter::Debug,
Some("TRACE") => LevelFilter::Trace,
_ => LevelFilter::Off,
});
}
cargo build
? (there are so many APP programs)
.align 3
.section .data
.global _num_app
_num_app:
.quad 5
.quad app_0_start
.quad app_1_start
.quad app_2_start
.quad app_3_start
.quad app_4_start
.quad app_4_end
.section .data
.global app_0_start
.global app_0_end
app_0_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/00hello_world.bin"
app_0_end:
.section .data
.global app_1_start
.global app_1_end
app_1_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/01store_fault.bin"
app_1_end:
.section .data
.global app_2_start
.global app_2_end
app_2_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/02power.bin"
app_2_end:
.section .data
.global app_3_start
.global app_3_end
app_3_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/03priv_inst.bin"
app_3_end:
.section .data
.global app_4_start
.global app_4_end
app_4_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/04priv_csr.bin"
app_4_end:
‘.align 3’ advances the location counter until it is a multiple of 8. If the location counter is already a multiple of 8, no change is needed. .align n 指令的对齐值有两种方案:n 或 2^n 。各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释.align指令会显得有些混乱,原因在于保持兼容。
os/src/link_app.S这个文件是在 cargo build 的时候,由脚本 os/build.rs 控制生成的
add -vv
to cargo build
to show the println content of os/build.rs
stvec
?// riscv-ab2abd16c438337b/11d43cf/src/register/stvec.rs
read_csr_as!(Stvec, 0x105, __read_stvec);
write_csr!(0x105, __write_stvec);
/// Writes the CSR
#[inline]
pub unsafe fn write(addr: usize, mode: TrapMode) {
_write(addr + mode as usize);
}
// os/src/trap/mod.rs
pub fn init() {
extern "C" {
fn __alltraps();
}
unsafe {
stvec::write(__alltraps as usize, TrapMode::Direct);
}
}
BASE << 2
. And __alltraps as usize
must be a multiple of 4 which is guaranteed by the following assembly code# os/src/trap/trap.S
.align 2
__alltraps:
csrrw sp, sscratch, sp
// os/src/batch.rs
static KERNEL_STACK: KernelStack = KernelStack {
data: [0; KERNEL_STACK_SIZE],
};
static USER_STACK: UserStack = UserStack {
data: [0; USER_STACK_SIZE],
};
# os/Cargo.toml
[dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
where does features = ["inline-asm"]
take effect ?
// riscv-ab2abd16c438337b/11d43cf/src/register/macros.rs
macro_rules! read_csr {
($csr_number:expr, $asm_fn: ident) => {
/// Reads the CSR
#[inline]
unsafe fn _read() -> usize {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => {
let r: usize;
core::arch::asm!("csrrs {0}, {1}, x0", out(reg) r, const $csr_number);
r
}
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn() -> usize;
}
$asm_fn()
}
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
};
}
[remain to solve]user/src/lib.rs : when the main() in _start() is replaced by an APP main() ?
我们使用 Rust 的宏将其函数符号 main 标志为弱链接。这样在最后链接的时候,虽然在 lib.rs 和 bin 目录下的某个应用程序都有 main 符号,但由于 lib.rs 中的 main 符号是弱链接,链接器会使用 bin 目录下的应用主逻辑作为 main 。这里我们主要是进行某种程度上的保护,如果在 bin 目录下找不到任何 main ,那么编译也能够通过,但会在运行时报错。
http://rcore-os.cn/rCore-Tutorial-Book-v3/chapter2/2application.html#id4
refer to weak linkage in the source code : https://github.com/rust-lang/rust compiler/rustc_codegen_ssa/src/codegen_attrs.rs tests/ui/lto/weak-works.rs