aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/common/syscall.c92
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. */