diff options
-rw-r--r-- | sim/common/syscall.c | 92 |
1 files changed, 50 insertions, 42 deletions
diff --git a/sim/common/syscall.c b/sim/common/syscall.c index e353d86..bad3b3b 100644 --- a/sim/common/syscall.c +++ b/sim/common/syscall.c @@ -141,16 +141,14 @@ cb_syscall (host_callback *cb, CB_SYSCALL *sc) switch (cb_target_to_host_syscall (cb, sc->func)) { -#if 0 /* FIXME: wip */ case CB_SYS_argvlen : { /* Compute how much space is required to store the argv,envp strings so that the program can allocate the space and then call SYS_argv to fetch the values. */ - int addr_size = cb->addr_size; - int argc,envc,arglen,envlen; - const char **argv = cb->init_argv; - const char **envp = cb->init_envp; + int argc, envc, arglen, envlen; + char **argv = cb->argv; + char **envp = cb->envp; argc = arglen = 0; if (argv) @@ -164,7 +162,7 @@ cb_syscall (host_callback *cb, CB_SYSCALL *sc) for ( ; envp[envc]; ++envc) envlen += strlen (envp[envc]) + 1; } - result = arglen + envlen; + result = arglen + 1 + envlen + 1; break; } @@ -174,63 +172,73 @@ cb_syscall (host_callback *cb, CB_SYSCALL *sc) TADDR tbuf = sc->arg1; /* Buffer size. */ int bufsize = sc->arg2; + int written = 0; /* Q is the target address of where all the strings go. */ TADDR q; - int word_size = cb->word_size; - int i,argc,envc,len; - const char **argv = cb->init_argv; - const char **envp = cb->init_envp; + int i, argc, envc, len, ret; + char **argv = cb->argv; + char **envp = cb->envp; + + result = -1; argc = 0; if (argv) { for ( ; argv[argc]; ++argc) { - int len = strlen (argv[argc]); - int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1); - if (written != len) - { - result = -1; - errcode = EINVAL; - goto FinishSyscall; - } - tbuf = len + 1; + len = strlen (argv[argc]) + 1; + if (written + len > bufsize) + goto efault; + + ret = (*sc->write_mem) (cb, sc, tbuf + written, argv[argc], + len); + if (ret != len) + goto einval; + + written += ret; } } - if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) - { - result = -1; - errcode = EINVAL; - goto FinishSyscall; - } - tbuf++; + /* Double NUL bytes indicates end of strings. */ + if (written >= bufsize) + goto efault; + if ((*sc->write_mem) (cb, sc, tbuf + written, "", 1) != 1) + goto einval; + ++written; + envc = 0; if (envp) { for ( ; envp[envc]; ++envc) { - int len = strlen (envp[envc]); - int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1); - if (written != len) - { - result = -1; - errcode = EINVAL; - goto FinishSyscall; - } - tbuf = len + 1; + len = strlen (envp[envc]) + 1; + if (written + len > bufsize) + goto efault; + + ret = (*sc->write_mem) (cb, sc, tbuf + written, envp[envc], + len); + if (ret != len) + goto einval; + written += ret; } } - if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) - { - result = -1; - errcode = EINVAL; - goto FinishSyscall; - } + /* Double NUL bytes indicates end of strings. */ + if (written >= bufsize) + goto efault; + if ((*sc->write_mem) (cb, sc, tbuf + written, "", 1) != 1) + goto einval; + result = argc; sc->result2 = envc; break; + + efault: + errcode = EFAULT; + goto FinishSyscall; + + einval: + errcode = EINVAL; + goto FinishSyscall; } -#endif /* wip */ case CB_SYS_exit : /* Caller must catch and handle; see sim_syscall as an example. */ |