Argument Passing은
두 기능을 포함한다고 할 수 있다.
예를 들어, 아래와 같이
run 'args-single onearg'라는 명령이 터미널에 입력되면, run이란 명령어가 뒤에 입력되는 'args-single onearg'을 실행하는 것이라고 생각하면 된다.
argument[0]에 해당하는 args-single은 파일명이 될 것이고, onearg는 인자가 될 것이다.
process_exec() 함수 내에서 구현하면 된다.
아래 while문과 argument_stack() 함수를 주목하면 된다.
argument_stack() 함수는 구현해야 한다.
int process_exec(void *f_name)
{
char *file_name = f_name;
bool success;
char *next_ptr;
char *save_ptr = NULL;
char *save_arg[128];
int token_cnt = 1;
save_ptr = strtok_r(f_name, " ", &next_ptr);
save_arg[0] = save_ptr;
while (save_ptr != NULL)
{
token_cnt++;
save_ptr = strtok_r(NULL, " ", &next_ptr);
save_arg[token_cnt - 1] = save_ptr;
// printf("save_ptr : %s, %d\n", save_ptr, token_cnt);
// printf("........ : %s, %d\n", save_arg[token_cnt-1], token_cnt);
}
/* We cannot use the intr_frame in the thread structure.
* This is because when current thread rescheduled,
* it stores the execution information to the member. */
struct intr_frame _if;
_if.ds = _if.es = _if.ss = SEL_UDSEG;
_if.cs = SEL_UCSEG;
_if.eflags = FLAG_IF | FLAG_MBS;
/* We first kill the current context */
process_cleanup();
/* And then load the binary */
success = load(file_name, &_if);
/* If load failed, quit. */
if (!success)
return -1;
// printf("%d", token_cnt);
argument_stack(save_arg, token_cnt, &_if.rsp);
_if.R.rdi = token_cnt - 1;
_if.R.rsi = (uintptr_t *)_if.rsp + 1;
// hex_dump(_if.rsp, _if.rsp, USER_STACK - _if.rsp, true);
/* Start switched process. */
do_iret(&_if);
palloc_free_page(file_name);
NOT_REACHED();
}
위에서 parsing한 문자열들을 User stack 영역에 잘 쌓도록 넘겨준다.
argument_stack() 함수로 구현하여, 나타내볼 것이다.
USER_STACK이 정의되어 있어서 아래 표와 같은 결과값이 나온다.
명령어 예시 : /bin/ls -l foo bar
void argument_stack(char **parse, int count, void **rsp)
{
char *word_address[128];
int for_word_align = 0;
//! 문자열 저장
for (int i = count - 2; i > -1; i--)
{
for_word_align = for_word_align + strlen(parse[i]);
for (int j = strlen(parse[i]); j > -1; j--)
{
*rsp = (char *)*rsp - 1;
**(char **)rsp = parse[i][j];
}
word_address[i] = (char *)*rsp;
}
//! word_align 처리
*rsp = *(uintptr_t *)rsp & ~(uintptr_t)7;
// argv[cnt+1]에 0(NULL) 추가
*rsp = (uintptr_t *)*rsp - 1;
**(uint64_t **)rsp = NULL;
//!argv[0~cnt] 저장
for (int i = count - 2; i > -1; i--)
{
*rsp = (uintptr_t *)*rsp - 1;
**(uint64_t **)rsp = word_address[i];
}
//! return address 저장
*rsp = (uintptr_t *)*rsp - 1;
**(uint64_t **)rsp = 0;
}
추가적으로, 인자 수와 argv[0]의 주소값을 저장해줘야 한다.
process_exec() 함수에서 아래 두 줄을 추가해주면 된다.
int process_exec(void *f_name){
...
_if.R.rdi = token_cnt - 1;
_if.R.rsi = (uintptr_t *)_if.rsp + 1;
...
}