Pintos UserProgram-Argument 传递分段错误问题

pintos userprogram-argument passing segmentation fault problem

提问人:안태찬 提问时间:8/20/2021 更新时间:8/20/2021 访问量:737

问:

我正在研究 Pintos Project 2 来准备操作系统课程。 实现参数传递后,我输入以下命令。

pintos -q run 'echo x'

结果如下。

0627antaechan@pintos-2:~/pintos/src/userprog/build$ pintos -q run 'echo x'
Use of literal control characters in variable names is deprecated at /home/0627antaechan/pintos/src/utils/pintos line 911.
Prototype mismatch: sub main::SIGVTALRM () vs none at /home/0627antaechan/pintos/src/utils/pintos line 935.
Constant subroutine SIGVTALRM redefined at /home/0627antaechan/pintos/src/utils/pintos line 927.
squish-pty bochs -q
========================================================================
                       Bochs x86 Emulator 2.6.2
                Built from SVN snapshot on May 26, 2013
                  Compiled on Aug  5 2021 at 07:51:40
========================================================================
00000000000i[     ] reading configuration from bochsrc.txt
00000000000e[     ] bochsrc.txt:8: 'user_shortcut' will be replaced by new 'keyboard' option.
00000000000i[     ] installing nogui module as the Bochs GUI
00000000000i[     ] using log file bochsout.txt
PiLo hda1
Loading.........
Kernel command line: -q run 'echo x'
Pintos booting with 4,096 kB RAM...
383 pages available in kernel pool.
383 pages available in user pool.
Calibrating timer...  204,600 loops/s.
hda: 1,008 sectors (504 kB), model "BXHD00011", serial "Generic 1234"
hda1: 147 sectors (73 kB), Pintos OS kernel (20)
hdb: 5,040 sectors (2 MB), model "BXHD00012", serial "Generic 1234"
hdb1: 4,096 sectors (2 MB), Pintos file system (21)
filesys: using hdb1
Boot complete.
Executing 'echo x':
Execution of 'echo' complete.
Timer: 127 ticks
Thread: 30 idle ticks, 96 kernel ticks, 8 user ticks
hdb1 (filesys): 28 reads, 0 writes
Console: 611 characters output
Keyboard: 0 keys pressed
Exception: 1 page faults
Powering off...
========================================================================
Bochs is exiting with the following message:
[UNMP ] Shutdown port: shutdown requested
========================================================================

在 Program echo 中,它调用系统调用函数“write”。 下面是syscall_handler我在

//userprog/syscall.c
static void
syscall_handler (struct intr_frame *f UNUSED) 
{
  printf ("system call!\n");
  thread_exit ();
}

但是,输入后没有消息“系统调用!pintos -q run echo x.

我还尝试实现 gdb 调试器。结果如下。

0627antaechan@pintos-2:~/pintos/src/userprog/build$ gdb kernel.o
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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"...
Reading symbols from kernel.o...done.
(gdb) run echo x
Starting program: /home/0627antaechan/pintos/src/userprog/build/kernel.o echo x

Program received signal SIGSEGV, Segmentation fault.
start () at ../../threads/start.S:30
30              mov %ax, %es
(gdb) 

我不知道问题的原因。请给我一些帮助!. 以下是process_execute、start_process construct_esp函数的代码。

tid_t
process_execute (const char *file_name) 
{
  char *fn_copy;
  tid_t tid;
  // make token to put in "thread_create"
  char *token;
  char *save_ptr;

  /* Make a copy of FILE_NAME.
     Otherwise there's a race between the caller and load(). */
  fn_copy = palloc_get_page (0);
  if (fn_copy == NULL)
    return TID_ERROR;
  strlcpy (fn_copy, file_name, PGSIZE);

  token = strtok_r(file_name, " ", &save_ptr);
  /* Create a new thread to execute FILE_NAME. */
  // modifying file_name to token
  tid = thread_create (token, PRI_DEFAULT, start_process, fn_copy);
  if (tid == TID_ERROR)
    palloc_free_page (fn_copy); 
  return tid;
}


/* A thread function that loads a user process and starts it
   running. */
static void
start_process (void *file_name_)
{
  char *cmd_line = file_name_;
  struct intr_frame if_;
  bool success;

  char fn_copy[MAX_ARGU_LENGTH];
  // char *argv[MAX_ARGUMENT];
  
  char ** argv = malloc(sizeof(char *)*MAX_ARGUMENT);
  char *save_ptr;
  int argc = 0;

  strlcpy(fn_copy, cmd_line, PGSIZE);
  argv[0] = strtok_r(fn_copy, " ", &save_ptr);

  while(argv[argc++] != NULL){
    argv[argc] = strtok_r(NULL, " ", &save_ptr);
  }

  /* Initialize interrupt frame and load executable. */
  memset (&if_, 0, sizeof if_);
  if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
  if_.cs = SEL_UCSEG;
  if_.eflags = FLAG_IF | FLAG_MBS;
  success = load (argv[0], &if_.eip, &if_.esp);

  // if success, construct esp
  if(success) construct_esp(argv, argc, &if_.esp);
  
  /* If load failed, quit. */
  palloc_free_page (cmd_line);
  free(argv);
  if (!success) 
    thread_exit ();

  /* Start the user process by simulating a return from an
     interrupt, implemented by intr_exit (in
     threads/intr-stubs.S).  Because intr_exit takes all of its
     arguments on the stack in the form of a `struct intr_frame',
     we just point the stack pointer (%esp) to our stack frame
     and jump to it. */
  asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory");
  NOT_REACHED ();
}


void construct_esp(char **argv, int argc, void **esp) {
  
  uint32_t *addrs[MAX_ARGUMENT];
  int i;

  for(i = argc-1; i >= 0; i--){
    *esp = *esp - (strlen(argv[i])+1);
    addrs[i] = (uint32_t *)*esp;
    memcpy(*esp, argv[i], (strlen(argv[i])+1)); 
  }

  //word-align
  while(((uintptr_t)(*esp) % WSIZE) != 0){
    *esp = *esp -1;
  }

  //argv[argc], namely NULL
  *esp = *esp - WSIZE;
  *(int32_t *)*esp = 0;

  for(i = argc-1; i >= 0; i--){
    *esp = *esp - WSIZE;
    *(uint32_t **)*esp = addrs[i]; 
  }

  *esp = *esp - WSIZE;
  *(uint32_t **)*esp = *esp + WSIZE;

  *esp = *esp - WSIZE;
  *(int32_t *)*esp = argc;

  *esp = *esp - WSIZE;
  *(int32_t *)*esp = 0;

  printf("your stack is like below\n");
  hex_dump((uintptr_t)*esp, *esp, 0xc0000000-(uintptr_t)*esp, true);
}
C 操作系统 分段 GDB Pintos

评论


答: 暂无答案