CS61A Project2 Cats

Overview 使用如下命令对每个 question 检查正确性: python3 ok -q [question number] -i 使用 ok 系统允许的 debug 打印: print("DEBUG:", x) 运行 cats GUI 系统: python3 cats_gui.py Problem 1 实现 pick 函数,其中函数接受的参数: paragraphs: 表示 paragraphs 的字符串 list select: 一个对字符串的判断函数,return True or False k: 第 k 个满足 select 的 paragraphs 返回 paragraphs 中第 k 个满足 select 的字符串,没有满足的返回空字符串。 def pick(paragraphs, select, k): """Return the Kth paragraph from PARAGRAPHS for which the SELECT returns True. If there are fewer than K such paragraphs, return an empty string....

2024-09-29 · 4 min

CSAPP - Cache Lab

实验说明 在 cache lab 实验中,包含两个部分: 第一部分要求我们写一个 C program 来模拟 cache memory。 第二部分要求我们通过减少 cache miss 来优化一个矩阵转置函数。 对应的文件分别为csim.c, trans.c 可通过make和make clean来编译和删除编译文件。 PartA Writing a Cache Simulator 准备工作 我们利用valgrind生成的 trace files 作为我们 cache simulator 的 input。 格式为[space]operation address, size: I 0400d7d4,8 M 0421c7f0,4 L 04f6b868,8 S 7ff0005c8,8 I 加载指令 L 加载数据 S 存储数据 M 内存数据修改(先加载数据,再存储数据) I 前面不跟空格,L/S/M 前面需要加一个空格。 csim-ref是一个参考的 cache simulator 实现。使用LRU替换算法。 用法: Usage: ./csim-ref [-hv] -s <s> -E <E> -b <b> -t <tracefile>...

2024-08-05 · 3 min

CSAPP - Attack Lab

文件说明 ctarget: An executable program vulnerable to code-injection(CI) attacks. rtarget: An executable program vulnerable to return-oriented-programming(ROP) attacks. cookie.txt: An 8-digit hex code that you will use as a unique identifier in your attack farm.c: 用来生成 ROP 攻击的代码。 hex2raw: 生成攻击字符串的工具。 输入ctarget -h查看帮助信息: Usage: [-hq] ./ctarget -i <infile> -h Print help information -q Don't submit result to server -i <infile> Input file 我们在本地跑的话必须加上-q选项,否则会提示Running on an illegal host错误。 工具使用 hex2raw hex2raw 可以将文本中保存的 ascii 码值转化成字符串。注意每个 ascii 需要以空格分开,可以加注释(注释/* */前后需要空格)。...

2024-07-05 · 10 min

CSAPP - Data Lab

Build ./dlc bits.c: 用来检查是否符合coding guidelines. ./dlc -e bits.c: 显示每个函数用了多少个操作符。 make btest: 编译btest。 make clean Rules Each "Expr" is an expression using ONLY the following: 1. Integer constants 0 through 255 (0xFF), inclusive. You are not allowed to use big constants such as 0xffffffff. 2. Function arguments and local variables (no global variables). 3. Unary integer operations ! ~ 4. Binary integer operations & ^ | + << >> You are expressly forbidden to: 1....

2024-06-25 · 1 min

CSAPP - Bomb Lab

Setup 新建solution.txt保存答案, 运行./bomb solution.txt进行测试。 gdb bomb (gdb) r solution.txt 注意如果solution.txt 每行的结尾需要是LF结尾,否则无法正确解析。 objdump -t bomb > bomb_symbol_table.txt: 生成符号表。 objdump -d bomb > bomb.txt: 生成反汇编文件。 Answer Bomb1 首先根据bomb.txt找到bomb的执行入口main函数。 400e32: e8 67 06 00 00 call 40149e <read_line> # 读取输入的一行 400e37: 48 89 c7 mov %rax,%rdi # 把读取的字符串地址传入%rdi 400e3a: e8 a1 00 00 00 call 400ee0 <phase_1> # 调用phase_1,传入的第一个参数为%rdi 400e3f: e8 80 07 00 00 call 4015c4 <phase_defused> 400e44: bf a8 23 40 00 mov $0x4023a8,%edi 400e49: e8 c2 fc ff ff call 400b10 <puts@plt> 400e4e: e8 4b 06 00 00 call 40149e <read_line> 400e53: 48 89 c7 mov %rax,%rdi 400e56: e8 a1 00 00 00 call 400efc <phase_2> 400e5b: e8 64 07 00 00 call 4015c4 <phase_defused> 400e60: bf ed 22 40 00 mov $0x4022ed,%edi 400e65: e8 a6 fc ff ff call 400b10 <puts@plt> //....

2024-06-13 · 11 min

xv6_lab3 trap

Q1 RISC-V assembly C 代码: int g(int x) { return x+3; } int f(int x) { return g(x); } void main(void) { printf("%d %d\n", f(8)+1, 13); exit(0); } 生成的汇编代码: 000000000000001c <main>: void main(void) { 1c: 1141 addi sp,sp,-16 // 分配栈空间 1e: e406 sd ra,8(sp) // 保存main的返回地址,因为接下来要调用printf 20: e022 sd s0,0(sp) // 保存前一个函数的frame pointer 22: 0800 addi s0,sp,16 // 现在frame pointer要增加16Bytes printf("%d %d\n", f(8)+1, 13); 24: 4635 li a2,13 26: 45b1 li a1,12 28: 00000517 auipc a0,0x0 2c: 7a050513 addi a0,a0,1952 # 7c8 <malloc+0xe8> // "%d %d\n"字符串地址 30: 00000097 auipc ra,0x0 // ra=pc=0x30 34: 5f8080e7 jalr 1528(ra) # 628 <printf> // 0x30 + 0x5f8 = 0x628 exit(0); 38: 4501 li a0,0 // exit的参数,传入0 3a: 00000097 auipc ra,0x0 3e: 274080e7 jalr 628(ra) # 2ae <exit> 1....

2024-06-04 · 2 min

xv6_chapter4 Traps

Lecture gdb调试shell write函数的syscall过程: (gdb) b *0xdec # 在0xde8地址设置断点 (gdb) c (gdb) delete 1 # 删除断点 (gdb) print $pc $1 = (void (*)()) 0xdec (gdb) info r (gdb) x/3i 0xde8 # 打印0xdfe开始的三条指令 0xdfe: li a7,16 0xe00: ecall 0xe04: ret (gdb) p/x $stvec $2 = 0x3ffffff000 # user space virtual address顶部一个page,trampoline page对应kernel trap handler. (gdb) stepi warning Book Traps: system call. 通过ecall进入kernel exception. 除0,invalid virtual address. interrupt. 进入kernel device driver. 根据处理代码不同,可分为三种traps: traps from user space traps from kernel space timer interrupts 4....

2024-02-26 · 1 min

xv6 calling conventions and stack frames RISC-V

caller: not preserved across fn call. 需要调用函数来保存寄存器。参考下面例子中的ra寄存器值。 callee: preserved across fn call. 被调用函数来保存寄存器。 根据CSAPP 3.7.1栈结构看,return address属于前一栈帧保存的,所以fp register应该指向return address的地址,即当前栈帧的顶部。一个栈帧中保存在最高位地址的是previous fp。所以这里最上面一个stack frame也应该把return address去掉。 sum_to: mv t0, a0 li a0, 0 loop: add a0, a0, t0 addi t0, t0, -1 bnez t0, loop ret // 返回到li t0, 2 sum_then_double: addi sp, sp, -16; // 分配栈空间 sd ra, 0(sp) // ra的值存入sp+0地址。caller保存sum_the_double执行完的返回地址 call sum_to // 这里调用call,ra的值被设置为下一条指令地址,即li t0, 2 li t0, 2 mul a0, a0, t0 ld ra, 0(sp) // 恢复sum_them_double的返回地址 addi sp, sp, 16 ret

2024-02-25 · 1 min

xv6 Misc

环境安装 https://pdos.csail.mit.edu/6.828/2023/tools.html $ sudo apt-get update && sudo apt-get upgrade sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu 测试环境: $ riscv64-unknown-elf-gcc --version $ qemu-system-riscv64 --version 在 ubuntu22.04 上的输出 log 为: ~ ❯ qemu-system-riscv64 --version QEMU emulator version 6.2.0 (Debian 1:6.2+dfsg-2ubuntu6.24) Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers ~ ❯ riscv64-linux-gnu-gcc --version riscv64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions....

2024-02-01 · 1 min

xv6_lab3 pgtbl

Q1 Speed up system call 这个实验的目的是将用户程序的虚拟地址USYSCALL映射到保存有进程pid的物理地址。 这样不用通过系统调用getpid()的方式,直接通过ugetpid()访问虚拟地址就可以直接得到映射的进程pid。 #define USYSCALL (TRAPFRAME - PGSIZE) // USYSCALL位于虚拟地址顶部Trapframe下面一个page int ugetpid(void) { struct usyscall *u = (struct usyscall *)USYSCALL; // 直接访问虚拟地址 return u->pid; } 在struct proc进程结构体中增加struct usyscall *usyscall, 在分配进程函数allocproc中初始化, 分配p->pid给p->usyscall->pid: if ((p->usyscall = (struct usyscall *)kalloc()) == 0) { freeproc(p); release(&p->lock); return 0; } p->usyscall->pid = p->pid; 在给进程分配页表的函数proc_pagetable()中映射指定的虚拟地址。 注意要加上PTE_U p->pagetable = proc_pagetable(p); pagetable_t proc_pagetable(struct proc *p) { // ... // map the USYSCALL just below trapframe....

2024-02-01 · 2 min