1

嗨,我正在做有关使用 Pintos 的操作系统的作业。我被要求在一项测试中找出错误指令。测试框架期望 Pintos 输出“do-nothing: exit(162)”。这是进程退出时 Pintos 打印的标准消息。但是,Pintos 没有输出此消息;相反,由于内存访问冲突(分段错误),无操作程序在用户空间中崩溃。

#include "tests/lib.h"

int
main (int argc UNUSED, char *argv[] UNUSED)
{
  return 162;
}

我查看了这个测试的结果,

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=0x8048757
+  cr2=c0000008 error=00000005
+  eax=00000000 ebx=00000000 ecx=00000000 edx=00000000
+  esi=00000000 edi=00000000 esp=bfffffe4 ebp=00000000
+  cs=001b ds=0023 es=0023 ss=0023

问题:

  1. 程序试图从用户空间访问哪个虚拟地址导致它崩溃? A:从结果文件来看,我认为是 0xc000008
  2. 导致崩溃的指令的虚拟地址是什么? A:eip = 0x8048757,是指令的虚拟地址。
  3. 要进行调查,请使用 objdump 反汇编无操作的二进制文件。程序崩溃时所在的函数的名称是什么?将该函数的反汇编代码复制到 Gradescope 上,并确定程序崩溃的指令。

我不知道如何找到 3. 问题的答案,“objdump -S do-nothing.o”的输出非常简单:

Disassembly of section .text:

00000000 <main>:

int
main (int argc UNUSED, char *argv[] UNUSED)
{
  return 162;
}
   0:   b8 a2 00 00 00          mov    $0xa2,%eax
   5:   c3                      ret    

A:

void
_start (int argc, char *argv[])
{
 8048754:   83 ec 1c                sub    $0x1c,%esp
  exit (main (argc, argv));
 8048757:   8b 44 24 24             mov    0x24(%esp),%eax
 804875b:   89 44 24 04             mov    %eax,0x4(%esp)
 804875f:   8b 44 24 20             mov    0x20(%esp),%eax
 8048763:   89 04 24                mov    %eax,(%esp)
 8048766:   e8 35 f9 ff ff          call   80480a0 <main>
 804876b:   89 04 24                mov    %eax,(%esp)
 804876e:   e8 49 1b 00 00          call   804a2bc <exit>
  1. 找到您在上面确定的函数的 C 代码。对于#3 中反汇编函数中的每条指令,用几句话解释为什么它是必要的和/或它试图做什么。
#include <syscall.h>

int main (int, char *[]);
void _start (int argc, char *argv[]);

void
_start (int argc, char *argv[])
{
  exit (main (argc, argv));
}
  1. Why did the instruction you identified in #3 try to access memory at the virtual address you identified in #1? Don’t explain this in terms of the values of registers; we’re looking for a higher level explanation. A: I found the faulting instruction but I'm even more confused,
8048757:    8b 44 24 24             mov    0x24(%esp),%eax

**why would this instruction lead to segmentation fault? **

sub    $0x1c,%esp
mov    0x24(%esp),%eax

Firstly it allocated some stack space (0x1c), then move the argument argv at 0x24(%esp) [which was 0x8 before stack pointer changed] to %eax, why would this simple instruction lead to segmentation fault?

4

1 回答 1

2

I am not an expert in PintOS, but I can offer some insight. You are using OBJDUMP on an object file (.o). These are unlinked ELF object files without any VMA (Virtual Memory Address) starting point (aka Origin Point) and doesn't include any of the user mode runtime code in each PintOS program. Things like a C startup that sets up the user mode application and starts the code at main with the argc and argv parameters.

What you need to do is build the object file into a user mode program with the normal PintOS build processes. The userland executables have the same name as the .o file with the .o removed. do-nothing is the name of the executable and it appears these can be found in the directory pintos/src/userprog/build/tests/userprog/. Run OBJDUMP on this executable, search for address 0x8048757. You should be able to readily find the function name and all the code for it easily. With that information you should be able to answer the 3rd question. The answer you have for question 1 and 2 is correct.

于 2020-12-02T20:22:52.877 回答