diff options
author | Mike Frysinger <vapier@gentoo.org> | 2021-11-16 00:03:50 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2021-11-16 02:09:46 -0500 |
commit | fab6939b01da06e1b5f423a8c7f72160b0a1e35d (patch) | |
tree | 7e47092831bee6c4413a3a382ce4cae6b19b36ba /sim/common | |
parent | 8cfc9a1895d9f720e2cc38fd57b94ca5efba07b1 (diff) | |
download | gdb-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.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. */ |