Operating Systems 2022F: Assignment 1

From Soma-notes

Please submit the answers to the following questions via Brightspace by September 28, 2022. There are 20 points in 9 questions.

Submit your answers as a plain text file following this template. Name your answer file "comp3000-assign1-<username>.txt" (where username is your MyCarletonOne username). Please make sure to use your correct student ID number otherwise your grades may not be properly recorded.

Your answers will be parsed by a script in order to help with grading so please preserve the format of the template. No other formats will be accepted.

Note that the file should be a UNIX text file, not a Windows text file (so LF line endings). See the Wikipedia page on text files to learn more. Most modern text editors can convert between different types of text files. Alternately, install the program dos2unix on the VM to convert.

You may use this validator page to make sure your answer file is properly named and formatted.

Don't forget to include what outside resources you used to complete each of your answers, including other students, man pages, and web resources. You do not need to list help from the instructor, TA, or information found in the textbook.

Introduction

In this assignment you will be looking at 3000menu.c and its corresponding assembly language version, 3000menu.s. You can download the C source, generate the assembly language code, and compile it with the following commands:

 wget https://homeostasis.scs.carleton.ca/~soma/os-2022f/code/3000menu.c
 gcc -O -S 3000menu.c
 gcc -O -z lazy 3000menu.c -o 3000menu

Note that you can also just compile the assembly code directly:

 gcc -O -z lazy 3000menu.s -o 3000menu  

We're using the "-z lazy" option so you can use ltrace properly.

Questions

Note that these questions do not depend on each other; for any modifications, assume you are starting with the original version.

  1. [2] There are three functions defined in 3000menu.c. Which lines in 3000menu.s implement each of those functions? How do you know those are the correct lines?
  2. [1] Why is environ referenced but not defined in 3000menu.s?
  3. [2] What lines in 3000menu.s define the menu array of character arrays (the declaration on line 10 of 3000menu.c)? What lines define the constant string arrays it points to?
  4. [2] Which lines of 3000menu.s correspond to lines 72-76 of 3000menu.c, inside of main()? What do each of these lines do? (You only need to consider actual instructions, not compiler directives.)
  5. [2] The call to getline on line 56 of 3000menu.c does an implicit malloc() call, requiring a call to free() on line 58. Do these calls result in additional system calls? How do you know?
  6. [2] If we replace line 27 of 3000menu.c with "pid = 0;" how does the behavior of the program change? Why?
  7. [2] In line 30 of 3000menu.c, we replace one of the string pointers in menu with NULL.
    1. [1] What is the purpose of this line?
    2. [1] This doesn't change the menu that is displayed to the user. Why not?
  8. [2] How does the 3000menu.c's behavior change if you delete line 34, the call to wait? Why?
  9. [5] Replace line 29 in 3000menu.s (the assembly code version) with the following two lines:
        mov $57,%eax
        syscall
    Create a new binary by compiling the modified assembly language code, calling it 3000menu-q9. It should run the same as before.
    1. [1] Is 3000menu-q9 statically or dynamically linked?
    2. [1] How does the library call behavior of 3000menu-q9 differ from 3000menu? Why?
    3. [1] How does the system call behavior of 3000menu-q9 differ from 3000menu? Why?
    4. [2] Could you modify 3000menu.c so that it compiled to essentially identical assembly as 3000menu-q9? Why or why not? (You only need to consider standard C functionality, without any libraries.)

Code

3000menu.c

/* 3000menu.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

extern char **environ;

char *menu[] = {
        "/usr/bin/ls",
        "/usr/bin/whoami",
        "/usr/bin/top",
        "QUIT",
        NULL
};

int QUIT = 3;

void run_program(int choice)
{
        pid_t pid;
        int status;
        
        printf("Running %s\n", menu[choice]);

        pid = fork();

        if (pid == 0) {
                menu[choice+1] = NULL;
                execve(menu[choice], menu + choice, environ);
                exit(-1);
        } else {
                pid = wait(&status);
        }
        
        return;
}

int choose_program(void)
{
        int i = 0;
        int choice;
        char *input = NULL;
        size_t result, n = 0;

        printf("\nChoose a program to run:\n\n");
        
        while (menu[i] != NULL) {
                printf("%d. %s\n", i + 1, menu[i]);
                i++;
        }

        printf("\nYour choice? ");

        result = getline(&input, &n, stdin);
        choice = atoi(input);
        free(input);

        if ((choice > 0) && (choice <= i)) {
                return choice - 1;
        } else {
                return -1;
        }
}

int main()
{
        int program;

        while (1) {
                program = choose_program();

                if (program == QUIT) {
                        return 0;
                }
                
                if (program != -1) {
                        run_program(program);
                }
        }
}

3000menu.s

	.file	"3000menu.c"
	.text
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"Running %s\n"
	.text
	.globl	run_program
	.type	run_program, @function
run_program:
.LFB51:
	.cfi_startproc
	endbr64
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	subq	$16, %rsp
	.cfi_def_cfa_offset 32
	movl	%edi, %ebx
	movq	%fs:40, %rax
	movq	%rax, 8(%rsp)
	xorl	%eax, %eax
	movslq	%edi, %rdx
	leaq	menu(%rip), %rax
	movq	(%rax,%rdx,8), %rdx
	leaq	.LC0(%rip), %rsi
	movl	$1, %edi
	movl	$0, %eax
	call	__printf_chk@PLT
	call	fork@PLT
	testl	%eax, %eax
	je	.L5
	leaq	4(%rsp), %rdi
	call	wait@PLT
	movq	8(%rsp), %rax
	subq	%fs:40, %rax
	jne	.L6
	addq	$16, %rsp
	.cfi_remember_state
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
.L5:
	.cfi_restore_state
	leaq	menu(%rip), %rax
	leal	1(%rbx), %edx
	movslq	%edx, %rdx
	movq	$0, (%rax,%rdx,8)
	movslq	%ebx, %rbx
	leaq	(%rax,%rbx,8), %rsi
	movq	(%rax,%rbx,8), %rdi
	movq	environ(%rip), %rdx
	call	execve@PLT
	movl	$-1, %edi
	call	exit@PLT
.L6:
	call	__stack_chk_fail@PLT
	.cfi_endproc
.LFE51:
	.size	run_program, .-run_program
	.section	.rodata.str1.1
.LC1:
	.string	"\nChoose a program to run:\n"
.LC2:
	.string	"%d. %s\n"
.LC3:
	.string	"\nYour choice? "
	.text
	.globl	choose_program
	.type	choose_program, @function
choose_program:
.LFB52:
	.cfi_startproc
	endbr64
	pushq	%r13
	.cfi_def_cfa_offset 16
	.cfi_offset 13, -16
	pushq	%r12
	.cfi_def_cfa_offset 24
	.cfi_offset 12, -24
	pushq	%rbp
	.cfi_def_cfa_offset 32
	.cfi_offset 6, -32
	pushq	%rbx
	.cfi_def_cfa_offset 40
	.cfi_offset 3, -40
	subq	$40, %rsp
	.cfi_def_cfa_offset 80
	movq	%fs:40, %rax
	movq	%rax, 24(%rsp)
	xorl	%eax, %eax
	movq	$0, 8(%rsp)
	movq	$0, 16(%rsp)
	leaq	.LC1(%rip), %rdi
	call	puts@PLT
	movq	menu(%rip), %rcx
	testq	%rcx, %rcx
	je	.L12
	movl	$1, %ebx
	leaq	.LC2(%rip), %r13
	leaq	-8+menu(%rip), %r12
.L9:
	movl	%ebx, %ebp
	movl	%ebx, %edx
	movq	%r13, %rsi
	movl	$1, %edi
	movl	$0, %eax
	call	__printf_chk@PLT
	addq	$1, %rbx
	movq	(%r12,%rbx,8), %rcx
	testq	%rcx, %rcx
	jne	.L9
.L8:
	leaq	.LC3(%rip), %rsi
	movl	$1, %edi
	movl	$0, %eax
	call	__printf_chk@PLT
	leaq	16(%rsp), %rsi
	leaq	8(%rsp), %rdi
	movq	stdin(%rip), %rdx
	call	getline@PLT
	movl	$10, %edx
	movl	$0, %esi
	movq	8(%rsp), %rdi
	call	strtol@PLT
	movq	%rax, %rbx
	movq	8(%rsp), %rdi
	call	free@PLT
	testl	%ebx, %ebx
	jle	.L13
	cmpl	%ebx, %ebp
	jl	.L13
	leal	-1(%rbx), %eax
.L7:
	movq	24(%rsp), %rdx
	subq	%fs:40, %rdx
	jne	.L16
	addq	$40, %rsp
	.cfi_remember_state
	.cfi_def_cfa_offset 40
	popq	%rbx
	.cfi_def_cfa_offset 32
	popq	%rbp
	.cfi_def_cfa_offset 24
	popq	%r12
	.cfi_def_cfa_offset 16
	popq	%r13
	.cfi_def_cfa_offset 8
	ret
.L12:
	.cfi_restore_state
	movl	$0, %ebp
	jmp	.L8
.L13:
	movl	$-1, %eax
	jmp	.L7
.L16:
	call	__stack_chk_fail@PLT
	.cfi_endproc
.LFE52:
	.size	choose_program, .-choose_program
	.globl	main
	.type	main, @function
main:
.LFB53:
	.cfi_startproc
	endbr64
	subq	$8, %rsp
	.cfi_def_cfa_offset 16
.L19:
	call	choose_program
	cmpl	%eax, QUIT(%rip)
	je	.L22
	cmpl	$-1, %eax
	je	.L19
	movl	%eax, %edi
	call	run_program
	jmp	.L19
.L22:
	movl	$0, %eax
	addq	$8, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE53:
	.size	main, .-main
	.globl	QUIT
	.data
	.align 4
	.type	QUIT, @object
	.size	QUIT, 4
QUIT:
	.long	3
	.globl	menu
	.section	.rodata.str1.1
.LC4:
	.string	"/usr/bin/ls"
.LC5:
	.string	"/usr/bin/whoami"
.LC6:
	.string	"/usr/bin/top"
.LC7:
	.string	"QUIT"
	.section	.data.rel.local,"aw"
	.align 32
	.type	menu, @object
	.size	menu, 40
menu:
	.quad	.LC4
	.quad	.LC5
	.quad	.LC6
	.quad	.LC7
	.quad	0
	.ident	"GCC: (Ubuntu 11.2.0-19ubuntu1) 11.2.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:

Assignment 1 Solutions

Assignment 1 solutions