• Project0:小游戏


    2.1 找到故障指令

    FAIL
    Test output failed to match any acceptable form.
    
    Acceptable output:
      do-nothing: exit(162)
    Differences in `diff -u' format:
    - do-nothing: exit(162)
    + Page fault at 0xc0000008: rights violation error reading page in user context.
    + do-nothing: dying due to interrupt 0x0e (#PF Page-Fault Exception).
    + Interrupt 0x0e (#PF Page-Fault Exception) at eip=0x80488ee
    +  cr2=c0000008 error=00000005
    +  eax=00000000 ebx=00000000 ecx=00000000 edx=00000000
    +  esi=00000000 edi=00000000 esp=bfffffe4 ebp=bffffffc
    +  cs=001b ds=0023 es=0023 ss=0023
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 程序试图从用户空间访问哪个虚拟地址导致它崩溃?
      0xc0000008
    2. 导致崩溃的指令的虚拟地址是什么?
      0x80488ee
    3. 要进行调查,请使用 objdump 反汇编 do-nothing 二进制文件。程序崩溃时所在的函数的名称是什么?,并确定程序崩溃的指令。
    080488e8 <_start>:
     80488e8:       55                      push   %ebp
     80488e9:       89 e5                   mov    %esp,%ebp
     80488eb:       83 ec 18                sub    $0x18,%esp
     80488ee:       8b 45 0c                mov    0xc(%ebp),%eax    ;argv
     80488f1:       89 44 24 04             mov    %eax,0x4(%esp)
     80488f5:       8b 45 08                mov    0x8(%ebp),%eax    ;argc
     80488f8:       89 04 24                mov    %eax,(%esp)
     80488fb:       e8 94 f7 ff ff          call   8048094 <main>
     8048900:       89 04 24                mov    %eax,(%esp)
     8048903:       e8 d3 21 00 00          call   804aadb <exit>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 找到您在上面确定的函数的 C 代码(提示:它是在用户空间中执行的,因此它位于 do-nothing.c 或 proj-pregame/src/lib 或 proj-pregame/src/lib/user 中的文件之一)。对于 #3 中反汇编函数中的每条指令,用几句话解释为什么它是必要的和/或它试图做什么。提示:参见 80x86 调用约定。
      向 main 函数传递参数。80x86 的函数参数都是通过栈传送,而80x86_64 的前 6 个参数通过寄存器传送。
    //proj-pregame/src/lib/user/entry.c
    #include <syscall.h>
    
    int main(int, char* []);
    void _start(int argc, char* argv[]);
    
    void _start(int argc, char* argv[]) { exit(main(argc, argv)); }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 为什么您在 #3 中确定的指令尝试访问您在 #1 中确定的虚拟地址处的内存?不要用寄存器的值来解释这个;我们正在寻找更高层次的解释。
      此时指令想要将参数 argv 作为调用 main 函数的参数,而 ebp 指向它的旧值,ebp + 4 指向返回地址,ebp + 8 指向 argc,ebp + 12 指向 argv,因此该指令试图访问该虚拟地址。

    2.2 单步调试崩溃

    1. 进入进程执行功能。运行此函数的线程的名称和地址是什么?目前 Pintos 中还有哪些其他线程?复制他们的线程结构。
      名称为 main,地址为 0xc000e000
    pintos-debug: dumplist #0: 0xc000e000 {tid = 1, status = THREAD_RUNNING, name = "main", '\000' <repeats 11 times>, stack = 0xc000e
    dbc "\001", priority = 31, allelem = {prev = 0xc0039cf8 <all_list>, next = 0xc0104020}, elem = {prev = 0xc0039ce8 <fifo_ready_list
    >, next = 0xc0039cf0 <fifo_ready_list+8>}, pcb = 0xc010500c, magic = 3446325067}
    pintos-debug: dumplist #1: 0xc0104000 {tid = 2, status = THREAD_BLOCKED, name = "idle", '\000' <repeats 11 times>, stack = 0xc0104
    f14 "", priority = 0, allelem = {prev = 0xc000e020, next = 0xc0039d00 <all_list+8>}, elem = {prev = 0xc0039ce8 <fifo_ready_list>,
    next = 0xc0039cf0 <fifo_ready_list+8>}, pcb = 0x0, magic = 3446325067}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 当前线程的回溯是什么?从 GDB 复制回溯作为您的答案,并复制对应于每个函数调用的 C 代码行。
    #0  process_execute (file_name=0xc0007d50 "do-nothing") at ../../userprog/process.c:55
    #1  0xc0020a19 in run_task (argv=0xc0039bec <argv+12>) at ../../threads/init.c:317
    #2  0xc0020b8f in run_actions (argv=0xc0039bec <argv+12>) at ../../threads/init.c:390
    #3  0xc00203d9 in main () at ../../threads/init.c:138
    
    • 1
    • 2
    • 3
    • 4
    process_wait(process_execute(task));
    a->function(argv);
    run_actions(argv);
    
    • 1
    • 2
    • 3
    1. 在 start_process 处设置断点并继续运行到该点。运行此函数的线程的名称和地址是什么?目前 Pintos 中还有哪些其他线程?复制他们的结构线程。
      do-nothing,0xc010b000。
    pintos-debug: dumplist #0: 0xc000e000 {tid = 1, status = THREAD_BLOCKED, name = "main", '\000' <repeats 11 times>, stack = 0xc000e
    e7c "", priority = 31, allelem = {prev = 0xc0039cf8 <all_list>, next = 0xc0104020}, elem = {prev = 0xc003b718 <temporary+4>, next
    = 0xc003b720 <temporary+12>}, pcb = 0xc010500c, magic = 3446325067}
    pintos-debug: dumplist #1: 0xc0104000 {tid = 2, status = THREAD_BLOCKED, name = "idle", '\000' <repeats 11 times>, stack = 0xc0104
    f14 "", priority = 0, allelem = {prev = 0xc000e020, next = 0xc010b020}, elem = {prev = 0xc0039ce8 <fifo_ready_list>, next = 0xc003
    9cf0 <fifo_ready_list+8>}, pcb = 0x0, magic = 3446325067}
    pintos-debug: dumplist #2: 0xc010b000 {tid = 3, status = THREAD_RUNNING, name = "do-nothing\000\000\000\000\000", stack = 0xc010bf
    d4 "", priority = 31, allelem = {prev = 0xc0104020, next = 0xc0039d00 <all_list+8>}, elem = {prev = 0xc0039ce8 <fifo_ready_list>,
    next = 0xc0039cf0 <fifo_ready_list+8>}, pcb = 0x0, magic = 3446325067}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. 单步执行 start_process 函数,直到您跨过对 load 的调用。注意 load 设置 if_ 结构中的 eip 和 esp 字段。打印出 if_ 结构的值,以十六进制显示值(提示: p/x if )。
    {edi = 0x0, esi = 0x0, ebp = 0x0, esp_dummy = 0x0, ebx = 0x0, edx = 0x0, ecx = 0x0, eax = 0x0, gs = 0x23, fs = 0x23, es = 0x2
    3, ds = 0x23, vec_no = 0x0, error_code = 0x0, frame_pointer = 0x0, eip = 0x80488e8, cs = 0x1b, eflags = 0x202, esp = 0xc0000000, s
    s = 0x23}
    
    • 1
    • 2
    • 3
    1. asm volatile 语句中的第一条指令将堆栈指针设置为 if_ 结构的底部。第二条指令跳转到 intr_exit。代码中的注释解释了这里发生了什么。单步执行 asm volatile 语句,然后单步执行指令。当您逐步执行 iret 指令时,观察到函数“返回”到用户空间。为什么在执行此函数时处理器会切换模式?请随时根据 iret 时内存和/或寄存器中的值来解释这一点执行,以及 iret 指令的功能。
    intr_exit:
     52/* Restore caller's registers. */
     53│         popal
     54│         popl %gs
     55│         popl %fs
     56│         popl %es
     57│         popl %ds
     5859/* Discard `struct intr_frame' vec_no, error_code,
     60│            frame_pointer members. */
     61│         addl $12, %esp
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    java计算机毕业设计ssm美食视频教学网站element 前后端分离
    Java通过反射机制获取数据类对象的属性及方法
    LeetCode(25)验证回文串【双指针】【简单】
    Python —— 深拷贝&浅拷贝
    【重铸Java根基】理解Java反射机制
    Vue3 + ts +vite + elementplus
    【Hack The Box】windows练习-- Reel
    从零开始学习软件测试-第46天笔记
    2022年数学建模国赛--赛后总结
    2023年世界机器人大会回顾
  • 原文地址:https://blog.csdn.net/Ingsuifon/article/details/125507849