Skip to content

Commit 254e73b

Browse files
committed
add rcore_os_lab1
1 parent ae85083 commit 254e73b

File tree

4 files changed

+198
-0
lines changed

4 files changed

+198
-0
lines changed

2023/08/rcore_os_lab1_qemu_gdb.md

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# [rcore lab1 qemu gdb](/2023/08/rcore_os_lab1_qemu_gdb)
2+
3+
yay -S riscv-gnu-toolchain-bin
4+
5+
riscv64-unknown-elf-gdb: error while loading shared libraries: libpython3.8.so.1.0
6+
7+
从 ubuntu20.04 拷贝 libpython3.8.so 之后
8+
9+
> Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
10+
Python runtime state: core initialized
11+
12+
好吧还是从 https://github.com/riscv-collab/riscv-gnu-toolchain 源码安装
13+
14+
结果 make linux 卡在 `git clone submodule`... 所以 rcore 官方教程推荐下载 <https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14.tar.gz>
15+
16+
---
17+
18+
## rcore 实验一
19+
20+
<http://rcore-os.cn/rCore-Tutorial-Book-v3/chapter1/4first-instruction-in-kernel2.html?highlight=strip%20all>
21+
22+
先掌握下作业题和实验代码的方法论,在操作系统训练营中
23+
24+
- 作业题通常是 github classroom 克隆一份代码仓库 make rustlings 解决完编译错误提交代码跑 CI 打分
25+
- 实验题通常是克隆一个代码仓库,例如实验一就 git checkout ch1 最后 make run
26+
27+
由于 makefile 没有 `set -x` 我也不熟悉,我把 rcore 实验一的 makefile 代码整理成 shell 脚本
28+
29+
```sh
30+
<<- EOF
31+
[build]
32+
target = "riscv64gc-unknown-none-elf"
33+
[target.riscv64gc-unknown-none-elf]
34+
rustflags = [
35+
"-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes"
36+
]
37+
EOF
38+
cargo clean
39+
cp src/linker-qemu.ld src/linker.ld
40+
cargo b
41+
42+
# objcopy --only-section copy code/data section only?
43+
target=target/riscv64gc-unknown-none-elf/debug
44+
riscv64-unknown-elf-objcopy $target/os --strip-all -O binary $target/os.bin
45+
46+
qemu-system-riscv64 -machine virt -nographic \
47+
-bios ../bootloader/rustsbi-qemu.bin \
48+
-s -S \
49+
-device loader,file=$target/os.bin,addr=0x80200000
50+
```
51+
52+
`-device` 告诉 qemu 帮忙将二进制镜像加载到内存指定位置
53+
54+
想着 gdb 能看点函数符号,我尝试去掉 --strip-all 结果 qemu 一运行就卡死了
55+
56+
我的思考是 0x802 内存地址必须紧凑排满生成出的代码块,因此就不能 debug symbol? 这里我没想明白,linux kernel 确实也有 debug symbol 相关配置
57+
58+
解答: 看本文后续 ELF section 解释以及 linker-qemu.ld 源码中都是将各个 section 位置写死装载到内存中
59+
60+
## qemu gdb 初体验
61+
62+
> riscv64-unknown-elf-gdb -ex 'file target/riscv64gc-unknown-none-elf/debug/os' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'
63+
64+
ubuntu 用 gdb-multiarch 亦可
65+
66+
`i r` 命令也就是 info registers 的缩写看看寄存器的值
67+
68+
`i r mstatus` 能看一些特殊寄存器
69+
70+
结果全是 0 只有当前执行指令地址的 pc 寄存器有值 0x1000
71+
72+
```
73+
(gdb) x/10x 0x1000
74+
0x1000: 0x00000297 0x02828613 0xf1402573 0x0202b583
75+
0x1010: 0x0182b283 0x00028067 0x80000000 0x00000000
76+
0x1020: 0x87e00000 0x00000000
77+
```
78+
79+
`x /10x 0x1000` 命令看内存地址 0x1000 开始,往后看 10 个 32bit,x 表示用 16 进制显示
80+
81+
由于 RustSBI 版本有所变动,所以这 10 个指令内容跟书中不一样很正常
82+
83+
## vscode gdb 看不到寄存器
84+
85+
毕竟内核代码是编译出来的 ELF 文件 strip 掉一堆元信息,vscode 调试窗口看不到变量值,估计 CLion 也是看不到
86+
87+
```json
88+
{
89+
"name": "rcore-os",
90+
"type": "cppdbg",
91+
"request": "launch",
92+
"program": "${workspaceFolder}/os/target/riscv64gc-unknown-none-elf/debug/os",
93+
"args": [
94+
"-ex",
95+
"file target/riscv64gc-unknown-none-elf/debug/os",
96+
"-ex",
97+
"set arch riscv:rv64"
98+
],
99+
"stopAtEntry": false,
100+
"cwd": "${workspaceFolder}",
101+
"environment": [],
102+
"externalConsole": false,
103+
"MIMode": "gdb",
104+
"setupCommands": [
105+
{
106+
"description": "",
107+
"text": "-enable-pretty-printing",
108+
"ignoreFailures": true
109+
}
110+
],
111+
"miDebuggerPath": "/home/w/files/apps/riscv64_toolchain/bin/riscv64-unknown-elf-gdb",
112+
"miDebuggerServerAddress": "localhost:1234"
113+
}
114+
```
115+
116+
## 常用工具使用方法笔记
117+
118+
http://rcore-os.cn/rCore-Tutorial-Book-v3/appendix-b/index.html#
119+
120+
### readelf/rust-readobj
121+
122+
readelf -h os/target/riscv64gc-unknown-none-elf/debug/os
123+
124+
```
125+
ELF Header:
126+
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
127+
Class: ELF64
128+
Data: 2's complement, little endian
129+
Version: 1 (current)
130+
OS/ABI: UNIX - System V
131+
ABI Version: 0
132+
Type: EXEC (Executable file)
133+
Machine: RISC-V
134+
```
135+
136+
rust-readobj require cargo-binutils and rustup llvm-tools-preview component
137+
138+
rust-readobj -all os/target/riscv64gc-unknown-none-elf/debug/os | head
139+
140+
```
141+
File: os/target/riscv64gc-unknown-none-elf/debug/os
142+
Format: elf64-littleriscv
143+
Arch: riscv64
144+
AddressSize: 64bit
145+
LoadName: <Not found>
146+
ElfHeader {
147+
Ident {
148+
Magic: (7F 45 4C 46)
149+
Class: 64-bit (0x2)
150+
```
151+
152+
Magic 前 4 byte 是固定组合让加载器快速确定文件是不是一个 ELF
153+
154+
text section 就是代码段一般在前两个位置 text section 的例子
155+
156+
```
157+
Section {
158+
Index: 1
159+
Name: .text (1)
160+
Type: SHT_PROGBITS (0x1)
161+
Flags [ (0x6)
162+
SHF_ALLOC (0x2)
163+
SHF_EXECINSTR (0x4)
164+
]
165+
Address: 0x80200000
166+
Offset: 0x1000
167+
Size: 21684
168+
```
169+
170+
当将程序加载到内存的时候,对于每个 program header 所指向的区域,我们需要将对应的数据从文件复制到内存中
171+
172+
!> 这也是为什么 cargo b 编译出 elf 必须 strip-all 去掉所有无关 section 才能让首个地址才是代码
173+
174+
由于实验一代码限定死了内存布局,只有 strip-all 才能让我们手动完成【加载】任务
175+
176+
说起 ELF 文件加载想起一本必须要看的经典书《程序员的自我修养:链接、装载与库》
177+
178+
### ELF 三个核心 section
179+
180+
- text: 放代码和常量
181+
- bss: 未初始化的 static 变量
182+
- data: 已初始化的 static 变量
183+
184+
## objdump 反汇编
185+
186+
rust-objdump -all target/riscv64gc-unknown-none-elf/release/os
187+
188+
可以去找下 main/_start 的汇编代码
189+
190+
## objcopy
191+
实验一中已经用熟练了

2023/08/riscv_asm_swap_two_integer.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ deref example: movl (%rdi), %eax copies the value from the memory address pointe
3737
|x10,x11|a0,a1|function argument or return value register|
3838
|x12,x17|a2,a7|function argument register|
3939

40+
除了 general register 还有以下几个特殊寄存器
41+
- pc: Program Counter, address of the current instruction being executed
42+
43+
4044
## 试试编译汇编
4145

4246
我还不会写汇编,可以先写出 C 代码编译出汇编来学习下

2023/08/riscv_qemu_opensbi.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,5 @@ bootloader 相关内容重点关注下以下几个函数
125125
## qemu 命令解读
126126

127127
以 mit-pdos/xv6-riscv 仓库的 make qemu 为例
128+
129+
> qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -global virtio-mmio.force-legacy=false -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
- [文章列表 - 吴翱翔的博客](/)
22
- [正在读的书](/books.md)
33
- **2023-08**
4+
- [qemu vscode gdb](/2023/08/qemu_riscv_vscode_gdb.md)
45
- [gcc/ld --as-needed](/2023/08/gcc_ld_as_needed.md)
56
- [dumpbin](/2023/08/dumpbin_ldd_alternative_on_windows.md)
67
- [ptr::addr_of!](/2023/08/ptr_addr_of.md)

0 commit comments

Comments
 (0)