aboutsummaryrefslogtreecommitdiff
path: root/sim/common
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2021-11-16 00:03:50 -0500
committerMike Frysinger <vapier@gentoo.org>2021-11-16 02:09:46 -0500
commitfab6939b01da06e1b5f423a8c7f72160b0a1e35d (patch)
tree7e47092831bee6c4413a3a382ce4cae6b19b36ba /sim/common
parent8cfc9a1895d9f720e2cc38fd57b94ca5efba07b1 (diff)
downloadgdb-fab6939b01da06e1b5f423a8c7f72160b0a1e35d.zip
gdb-fab6939b01da06e1b5f423a8c7f72160b0a1e35d.tar.gz
gdb-fab6939b01da06e1b5f423a8c7f72160b0a1e35d.tar.bz2
sim: syscall: fix argvlen & argv implementation
Now that we have access to the argv & envp strings, finish implementing these syscalls. Delete unused variables, fix tbuf by incrementing the pointer instead of setting to the length, and make sure we don't write more data than the bufsize says is available.
Diffstat (limited to 'sim/common')
-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. */