안태찬
안태찬

Reputation: 53

pintos userprogram-argument passing segmentation fault problem

I'm Working on Pintos Project 2 to prepare Operating System Course. After implementing argument passing, I enter below command.

pintos -q run 'echo x'

The result is like below.

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
========================================================================

In Program echo, it calls system call function 'write'. Below is my syscall_handler function in

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

However, there are no message "system call!" after I enter pintos -q run echo x.

I also tried to implement gdb debugger. The result is like below.

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) 

I don't know the cause of problem. Plz let me some help!!. Below is code of process_execute, start_process, construct_esp function.

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);
}

Upvotes: 1

Views: 958

Answers (0)

Related Questions