lab1题目难度并不算很高,参考user/
下的其它程序基本都可以搞定(虽然但是,之前代码写少了,还是写着恼火…)
运行./grade-lab-util <name>
即可测试自己的程序有没有写对
Lab2
尝试按照老师的操作使用gdb调试xv6. 我没有在找到fedora下可以直接用的rv64 gdb, 因此选择从源码编译。
根据readme 编译即可。
没有看明白他的newLib
版本和linux
版本有什么区别…有懂的佬可以指点一下吗
之后即尝试进入gdb环境。首先启动qemu gdb
cd xv6-labs-2021
make CPUS=1 qemu-gdb
之后在另一个窗口中运行gdb
./bin/riscv64-unknown-linux-gnu-gdb
xv6-labs-2021]$ ../../../../riscv-gnu-toolchain/build/bin/riscv64-unknown-linux-gnu-gdb
GNU gdb (GDB) 14.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
warning: File "/home/unclebiglu/Documents/repostories/csdiy/s081os/lab1/xv6-labs-2021/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
add-auto-load-safe-path /home/unclebiglu/Documents/repostories/csdiy/s081os/lab1/xv6-labs-2021/.gdbinit
line to your configuration file "/home/unclebiglu/.config/gdb/gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/home/unclebiglu/.config/gdb/gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
(gdb) set confirm off
(gdb) set architecture riscv:rv64
The target architecture is set to "riscv:rv64".
(gdb) target remote 127.0.0.1:26000
Remote debugging using 127.0.0.1:26000
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x0000000000001000 in ?? ()
(gdb) symbol-file kernel/kernel
Reading symbols from kernel/kernel...
(gdb) set disassemble-next-line auto
(gdb) set riscv use-compressed-breakpoints yes
(gdb) b _entry
Breakpoint 1 at 0x8000000a
xv6仓库下面有一个.gdbinit
的文件给了如何进行gdb的指令,我这里直接一条一条手动执行了…应该也有方法自动读这个文件。之后即可设置断点进行调试。
发现编译的gdb不支持tui,但是找到了个方便的脚本用python提供一些功能
─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Breakpoint 1, 0x000000008000000a in _entry ()
=> 0x000000008000000a <_entry+10>: f14025f3 csrr a1,mhartid
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
!0x000000008000000a ? csrr a1,mhartid
0x000000008000000e ? addi a1,a1,1
0x0000000080000010 ? mul a0,a0,a1
0x0000000080000014 ? add sp,sp,a0
0x0000000080000016 ? jal 0x8000574e <start>
0x000000008000001a ? j 0x8000001a <spin>
0x000000008000001c ? addi sp,sp,-32
0x000000008000001e ? sd ra,24(sp)
0x0000000080000020 ? sd s0,16(sp)
0x0000000080000022 ? sd s1,8(sp)
─── Breakpoints ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[1] break at 0x000000008000000a for _entry hit 1 time
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
zero 0x0000000000000000 ra 0x0000000000000000 sp 0x0000000080021140 gp 0x0000000000000000 tp 0x0000000000000000
t0 0x0000000080000000 t1 0x0000000000000000 t2 0x0000000000000000 fp 0x0000000000000000 s1 0x0000000000000000
a0 0x0000000000001000 a1 0x0000000087e00000 a2 0x0000000000001028 a3 0x0000000000000000 a4 0x0000000000000000
a5 0x0000000000000000 a6 0x0000000000000000 a7 0x0000000000000000 s2 0x0000000000000000 s3 0x0000000000000000
s4 0x0000000000000000 s5 0x0000000000000000 s6 0x0000000000000000 s7 0x0000000000000000 s8 0x0000000000000000
s9 0x0000000000000000 s10 0x0000000000000000 s11 0x0000000000000000 t3 0x0000000000000000 t4 0x0000000000000000
t5 0x0000000000000000 t6 0x0000000000000000 pc 0x000000008000000a
─── Source ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── Stack ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[0] from 0x000000008000000a in _entry
─── Threads ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[1] id 1 from 0x000000008000000a in _entry
─── Variables ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
>>>
实验代码部分
Lab2要求增加新的系统调用,然而根本没看明白系统调用是怎么工作的…
首先user/user.h
下存放系统调用声明
user/usys.pl
下存放stub
生成的usys.S
里面是汇编代码,目测是把SYS_fork
一类的system call number送进寄存器之后ecall
由内核完成系统调用。
kernel/syscall.h
里面存放的是宏定义的call number.
kernel/sysproc.c
下面目测是一部分系统调用源码,fork
一类的函数会去调用放在kernel/proc.c
里的实现
为什么uint64
的返回值可以返回-1…
trace
第一道题做完几天了,抽点时间过来整理一下做题思路。
首先观察题目要求输出格式,<pid> <syscall_name> -> <return value>
然后观察被调用的用户代码user/trace.c
, 其接受三个参数,第一个参数是mask
, 传递给系统调用trace
, 后续全部参数被塞在一个新的*argv[]
数组里面然后exec
去执行。trace
系统调用的功能是把所有被mask
标记的系统调用名称及返回值打印出来。
首先为了程序编译通过,系统调用的入口得加上。
修改user/user.h
, user/usys.pl
, kernel/syscall.h
.
syscall.c
里面extern
声明的系统调用和函数指针数组里面也记得加上我们写的系统调用。
根据教案提示在/kernel/proc.h
的proc
结构体里塞个新变量存mask.
sys_trace
系统调用本体没啥工作,就把用户态传过来的参数存进结构体就行了。
所有的系统调用都会通过syscall()
调用。判断一下mask和syscall number打印出来就行。
sysinfo
首先还是该加的定义都加上
按照提示观察sys_fstat()
看copyout
用法
grep -rnw 'kernel/' -e 'copyout'
全局搜一下函数定义…
第一个参数是进程pagetable, 第二个是目的地址,第三个…这咋把局部变量地址传出去了… 第四个是大小
总之照葫芦画瓢先用着
…全记录下来有点麻烦…思路不复杂,有问题去看git diff…