【问题标题】:Pintos - syscalls project 2Pintos - 系统调用项目 2
【发布时间】:2018-10-04 02:30:12
【问题描述】:

我正在进行 Pintos 项目,以了解有关操作系统的更多信息。我完成了项目 1 并开始了第二个项目。我已经验证了设置堆栈并且可以正常工作(通过 hex_dump)。现在我在获取正确的系统调用参数时遇到问题。

在 user/syscall.c 中有 4 个程序集存根(0 - 4 个存根)由用户系统调用包装。

 #define syscall3(NUMBER, ARG0, ARG1, ARG2)                      \
    ({                                                      \
      int retval;                                           \
      asm volatile                                          \
        ("pushl %[arg2]; pushl %[arg1]; pushl %[arg0]; "    \
         "pushl %[number]; int $0x30; addl $16, %%esp"      \
           : "=a" (retval)                                  \
           : [number] "i" (NUMBER),                         \
             [arg0] "g" (ARG0),                             \
             [arg1] "g" (ARG1),                             \
             [arg2] "g" (ARG2)                              \
           : "memory");                                     \
      retval;                                               \
    }) (this code is given to us)

我的 syscall_handler 中有一些代码可以调用内核中的正确函数。

static void syscall_handler (struct intr_frame *f) {

  uint32_t *args = f->esp;
  if (args[0] == SYS_WRITE) {
    f->eax = write(args);
  }

在我的 write 函数中,我打印出 FD 和 Size

int sysCallNumber = (int) args[0];
  int fd = (int) args[1];
  const char *buffer = (char *) args[2];
  unsigned size = (unsigned) args[3];

  printf("FD is %d\n", fd);
  printf("Size is %d\n", size);

运行“echo hello stack overflow 1 22 333”将产生以下结果。注意我在括号中添加了注释。 ()

FD is 6    (hello)
Size is 6
FD is 6     (stack)
Size is 6
FD is 9    (overflow)
Size is 9
FD is 2    (1)
Size is 2
FD is 3    (22)
Size is 3
FD is 4    (333)
Size is 4
FD is 1   (this is from the printf("\n") in echo.c)
Size is 1

我在 GDB 设置断点和转储帧的情况下运行了此程序,但无法弄清楚。有没有人遇到过类似的事情?如果有,您是如何解决的?

谢谢!

【问题讨论】:

    标签: pintos


    【解决方案1】:

    我最近在user/syscall.c 中发现了一个可能会影响您的错误。尝试将此补丁应用于user/syscall.c

    diff --git a/src/lib/user/syscall.c b/src/lib/user/syscall.c
    index a9c5bc8..efeb38c 100644
    --- a/src/lib/user/syscall.c
    +++ b/src/lib/user/syscall.c
    @@ -10,7 +10,7 @@
                 ("pushl %[number]; int $0x30; addl $4, %%esp"       \
                    : "=a" (retval)                                  \
                    : [number] "i" (NUMBER)                          \
    -               : "memory");                                     \
    +               : "memory", "esp");                              \
               retval;                                               \
             })
    
    @@ -24,7 +24,7 @@
                    : "=a" (retval)                                           \
                    : [number] "i" (NUMBER),                                  \
                      [arg0] "g" (ARG0)                                       \
    -               : "memory");                                              \
    +               : "memory", "esp");                                       \
               retval;                                                        \
             })
    
    @@ -40,7 +40,7 @@
                    : [number] "i" (NUMBER),                         \
                      [arg0] "g" (ARG0),                             \
                      [arg1] "g" (ARG1)                              \
    -               : "memory");                                     \
    +               : "memory", "esp");                              \
               retval;                                               \
             })
    
    @@ -57,7 +57,7 @@
                      [arg0] "g" (ARG0),                             \
                      [arg1] "g" (ARG1),                             \
                      [arg2] "g" (ARG2)                              \
    -               : "memory");                                     \
    +               : "memory", "esp" );                             \
               retval;                                               \
             })
    

    说来话长……

    例如,在宏 syscall3 中,预期生成的汇编代码如下所示

    pushl ARG2
    pushl ARG1
    pushl ARG0
    pushl NUMBER
    int  $0x30
    addl $16, %esp
    

    只要堆栈看起来完全符合预期,这应该可以工作,只需推送中断指令。下面是反汇编的write 函数在测试程序中的样子(由objdump -d pintos/src/userprog/build/tests/userprog/args-many 生成):

    0804a1a5 <write>:
     804a1a5:       ff 74 24 0c             pushl  0xc(%esp)
     804a1a9:       ff 74 24 08             pushl  0x8(%esp)
     804a1ad:       ff 74 24 04             pushl  0x4(%esp)
     804a1b1:       6a 09                   push   $0x9
     804a1b3:       cd 30                   int    $0x30
     804a1b5:       83 c4 10                add    $0x10,%esp
     804a1b8:       c3                      ret
    

    这些说明存在很大问题。因为相对于堆栈指针%esp,参数被压入堆栈,所以错误的参数被压入堆栈!这是因为%esp 在每条pushl 指令之后都会发生变化。

    在对 gcc 的扩展 asm 语法进行了一些挖掘之后,我想我找到了正确的解决方法。需要将%esp 寄存器添加到每个syscall* 的扩展asm 指令中的Clobbers 列表中。这是因为每个pushl指令都间接修改了%esp,所以我们需要通知gcc这个修改,这样它就不会在生成的指令中错误地使用%esp

    【讨论】:

    • 反响非常好!非常感谢,这为我节省了很多时间。我刚刚完成了虚拟内存并开始 FS :)
    • 没问题。终于有时间完成userprog了,所以今天开始做vm。
    • 你能标记我的回答回答了你的问题吗?我是堆栈交换的新手,但我认为我因提供好的答案而受到赞誉。 =]
    猜你喜欢
    • 1970-01-01
    • 2012-08-22
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多