summaryrefslogtreecommitdiffstats
path: root/linux-user
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/alpha/target_signal.h7
-rw-r--r--linux-user/arm/nwfpe/double_cpdo.c2
-rw-r--r--linux-user/arm/nwfpe/extended_cpdo.c2
-rw-r--r--linux-user/arm/nwfpe/fpa11.h2
-rw-r--r--linux-user/arm/nwfpe/fpa11_cpdt.c2
-rw-r--r--linux-user/arm/nwfpe/fpa11_cprt.c2
-rw-r--r--linux-user/arm/nwfpe/fpopcode.c2
-rw-r--r--linux-user/arm/nwfpe/single_cpdo.c2
-rw-r--r--linux-user/arm/syscall_nr.h4
-rw-r--r--linux-user/cris/syscall.h5
-rw-r--r--linux-user/elfload.c14
-rw-r--r--linux-user/i386/syscall_nr.h4
-rw-r--r--linux-user/linuxload.c8
-rw-r--r--linux-user/main.c56
-rw-r--r--linux-user/microblaze/syscall.h6
-rw-r--r--linux-user/qemu-types.h36
-rw-r--r--linux-user/qemu.h60
-rw-r--r--linux-user/signal.c61
-rw-r--r--linux-user/sparc/syscall_nr.h4
-rw-r--r--linux-user/strace.list6
-rw-r--r--linux-user/syscall.c251
-rw-r--r--linux-user/syscall_defs.h14
-rw-r--r--linux-user/unicore32/syscall_nr.h4
23 files changed, 296 insertions, 258 deletions
diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h
index 94f15f612f..d3822da60e 100644
--- a/linux-user/alpha/target_signal.h
+++ b/linux-user/alpha/target_signal.h
@@ -6,9 +6,10 @@
/* this struct defines a stack used during syscall handling */
typedef struct target_sigaltstack {
- abi_ulong ss_sp;
- abi_long ss_flags;
- abi_ulong ss_size;
+ abi_ulong ss_sp;
+ int32_t ss_flags;
+ int32_t dummy;
+ abi_ulong ss_size;
} target_stack_t;
diff --git a/linux-user/arm/nwfpe/double_cpdo.c b/linux-user/arm/nwfpe/double_cpdo.c
index 8e9b28fa68..41c28f3096 100644
--- a/linux-user/arm/nwfpe/double_cpdo.c
+++ b/linux-user/arm/nwfpe/double_cpdo.c
@@ -19,7 +19,7 @@
*/
#include "fpa11.h"
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#include "fpopcode.h"
float64 float64_exp(float64 Fm);
diff --git a/linux-user/arm/nwfpe/extended_cpdo.c b/linux-user/arm/nwfpe/extended_cpdo.c
index 880ce030a5..48eca3b4a6 100644
--- a/linux-user/arm/nwfpe/extended_cpdo.c
+++ b/linux-user/arm/nwfpe/extended_cpdo.c
@@ -19,7 +19,7 @@
*/
#include "fpa11.h"
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#include "fpopcode.h"
floatx80 floatx80_exp(floatx80 Fm);
diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h
index 002b3cbb82..bb9ac6554e 100644
--- a/linux-user/arm/nwfpe/fpa11.h
+++ b/linux-user/arm/nwfpe/fpa11.h
@@ -43,7 +43,7 @@ extern CPUARMState *user_registers;
/* includes */
#include "fpsr.h" /* FP control and status register definitions */
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#define typeNone 0x00
#define typeSingle 0x01
diff --git a/linux-user/arm/nwfpe/fpa11_cpdt.c b/linux-user/arm/nwfpe/fpa11_cpdt.c
index 3e7a938253..007a3d6505 100644
--- a/linux-user/arm/nwfpe/fpa11_cpdt.c
+++ b/linux-user/arm/nwfpe/fpa11_cpdt.c
@@ -20,7 +20,7 @@
*/
#include "fpa11.h"
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#include "fpopcode.h"
//#include "fpmodule.h"
//#include "fpmodule.inl"
diff --git a/linux-user/arm/nwfpe/fpa11_cprt.c b/linux-user/arm/nwfpe/fpa11_cprt.c
index 801189798b..7be93fa54f 100644
--- a/linux-user/arm/nwfpe/fpa11_cprt.c
+++ b/linux-user/arm/nwfpe/fpa11_cprt.c
@@ -20,7 +20,7 @@
*/
#include "fpa11.h"
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#include "fpopcode.h"
#include "fpa11.inl"
//#include "fpmodule.h"
diff --git a/linux-user/arm/nwfpe/fpopcode.c b/linux-user/arm/nwfpe/fpopcode.c
index 82ac92f0ce..0dc5c9cd5d 100644
--- a/linux-user/arm/nwfpe/fpopcode.c
+++ b/linux-user/arm/nwfpe/fpopcode.c
@@ -19,7 +19,7 @@
*/
#include "fpa11.h"
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#include "fpopcode.h"
#include "fpsr.h"
//#include "fpmodule.h"
diff --git a/linux-user/arm/nwfpe/single_cpdo.c b/linux-user/arm/nwfpe/single_cpdo.c
index 26168e2201..2bfb359eb6 100644
--- a/linux-user/arm/nwfpe/single_cpdo.c
+++ b/linux-user/arm/nwfpe/single_cpdo.c
@@ -19,7 +19,7 @@
*/
#include "fpa11.h"
-#include "softfloat.h"
+#include "fpu/softfloat.h"
#include "fpopcode.h"
float32 float32_exp(float32 Fm);
diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index 5356395659..42d68550dc 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -182,8 +182,8 @@
#define TARGET_NR_rt_sigtimedwait (177)
#define TARGET_NR_rt_sigqueueinfo (178)
#define TARGET_NR_rt_sigsuspend (179)
-#define TARGET_NR_pread (180)
-#define TARGET_NR_pwrite (181)
+#define TARGET_NR_pread64 (180)
+#define TARGET_NR_pwrite64 (181)
#define TARGET_NR_chown (182)
#define TARGET_NR_getcwd (183)
#define TARGET_NR_capget (184)
diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
index 24f92ba421..50e50b4f3f 100644
--- a/linux-user/cris/syscall.h
+++ b/linux-user/cris/syscall.h
@@ -1,3 +1,6 @@
+#ifndef CRIS_SYSCALL_H
+#define CRIS_SYSCALL_H 1
+
#define UNAME_MACHINE "cris"
@@ -34,3 +37,5 @@ struct target_pt_regs {
unsigned long exs;
unsigned long eda;
};
+
+#endif
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 819fdd515a..89db49ccaa 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -14,7 +14,7 @@
#include <time.h>
#include "qemu.h"
-#include "disas.h"
+#include "disas/disas.h"
#ifdef _ARCH_PPC64
#undef ARCH_DLINFO
@@ -2442,7 +2442,7 @@ static void fill_prstatus(struct target_elf_prstatus *prstatus,
static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
{
- char *filename, *base_filename;
+ char *base_filename;
unsigned int i, len;
(void) memset(psinfo, 0, sizeof (*psinfo));
@@ -2464,13 +2464,15 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
psinfo->pr_uid = getuid();
psinfo->pr_gid = getgid();
- filename = strdup(ts->bprm->filename);
- base_filename = strdup(basename(filename));
+ base_filename = g_path_get_basename(ts->bprm->filename);
+ /*
+ * Using strncpy here is fine: at max-length,
+ * this field is not NUL-terminated.
+ */
(void) strncpy(psinfo->pr_fname, base_filename,
sizeof(psinfo->pr_fname));
- free(base_filename);
- free(filename);
+ g_free(base_filename);
bswap_psinfo(psinfo);
return (0);
}
diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h
index 74abfcacb4..f0803050d8 100644
--- a/linux-user/i386/syscall_nr.h
+++ b/linux-user/i386/syscall_nr.h
@@ -182,8 +182,8 @@
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
-#define TARGET_NR_pread 180
-#define TARGET_NR_pwrite 181
+#define TARGET_NR_pread64 180
+#define TARGET_NR_pwrite64 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index b47025f08a..381ab8914b 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -140,8 +140,9 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
memset(bprm->page, 0, sizeof(bprm->page));
retval = open(filename, O_RDONLY);
- if (retval < 0)
- return retval;
+ if (retval < 0) {
+ return -errno;
+ }
bprm->fd = retval;
bprm->filename = (char *)filename;
bprm->argc = count(argv);
@@ -165,8 +166,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
retval = load_flt_binary(bprm,regs,infop);
#endif
} else {
- fprintf(stderr, "Unknown binary format\n");
- return -1;
+ return -ENOEXEC;
}
}
diff --git a/linux-user/main.c b/linux-user/main.c
index 7dea084873..9ade1bfabd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -28,11 +28,11 @@
#include "qemu.h"
#include "qemu-common.h"
-#include "cache-utils.h"
+#include "qemu/cache-utils.h"
#include "cpu.h"
#include "tcg.h"
-#include "qemu-timer.h"
-#include "envlist.h"
+#include "qemu/timer.h"
+#include "qemu/envlist.h"
#include "elf.h"
#define DEBUG_LOGFILE "/tmp/qemu.log"
@@ -57,7 +57,12 @@ int have_guest_base;
* This way we will never overlap with our own libraries or binaries or stack
* or anything else that QEMU maps.
*/
+# ifdef TARGET_MIPS
+/* MIPS only supports 31 bits of virtual address space for user space */
+unsigned long reserved_va = 0x77000000;
+# else
unsigned long reserved_va = 0xf7000000;
+# endif
#else
unsigned long reserved_va;
#endif
@@ -89,19 +94,6 @@ int cpu_get_pic_interrupt(CPUX86State *env)
}
#endif
-/* timers for rdtsc */
-
-#if 0
-
-static uint64_t emu_time;
-
-int64_t cpu_get_real_ticks(void)
-{
- return emu_time++;
-}
-
-#endif
-
#if defined(CONFIG_USE_NPTL)
/***********************************************************/
/* Helper routines for implementing atomic operations. */
@@ -1127,6 +1119,11 @@ void cpu_loop (CPUSPARCState *env)
while (1) {
trapnr = cpu_sparc_exec (env);
+ /* Compute PSR before exposing state. */
+ if (env->cc_op != CC_OP_FLAGS) {
+ cpu_get_psr(env);
+ }
+
switch (trapnr) {
#ifndef TARGET_SPARC64
case 0x88:
@@ -2294,6 +2291,12 @@ done_syscall:
queue_signal(env, info.si_signo, &info);
}
break;
+ case EXCP_DSPDIS:
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPC;
+ queue_signal(env, info.si_signo, &info);
+ break;
default:
// error:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
@@ -2535,6 +2538,7 @@ void cpu_loop(CPUMBState *env)
case EXCP_BREAK:
/* Return address is 4 bytes after the call. */
env->regs[14] += 4;
+ env->sregs[SR_PC] = env->regs[14];
ret = do_syscall(env,
env->regs[12],
env->regs[5],
@@ -2545,7 +2549,6 @@ void cpu_loop(CPUMBState *env)
env->regs[10],
0, 0);
env->regs[3] = ret;
- env->sregs[SR_PC] = env->regs[14];
break;
case EXCP_HW_EXCP:
env->regs[17] = env->sregs[SR_PC] + 4;
@@ -3143,10 +3146,8 @@ static void handle_arg_cpu(const char *arg)
cpu_model = strdup(arg);
if (cpu_model == NULL || is_help_option(cpu_model)) {
/* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list_id)
- cpu_list_id(stdout, &fprintf, "");
-#elif defined(cpu_list)
- cpu_list(stdout, &fprintf); /* deprecated */
+#if defined(cpu_list)
+ cpu_list(stdout, &fprintf);
#endif
exit(1);
}
@@ -3222,7 +3223,7 @@ struct qemu_argument {
const char *help;
};
-struct qemu_argument arg_table[] = {
+static const struct qemu_argument arg_table[] = {
{"h", "", false, handle_arg_help,
"", "print this help"},
{"g", "QEMU_GDB", true, handle_arg_gdb,
@@ -3264,7 +3265,7 @@ struct qemu_argument arg_table[] = {
static void usage(void)
{
- struct qemu_argument *arginfo;
+ const struct qemu_argument *arginfo;
int maxarglen;
int maxenvlen;
@@ -3330,7 +3331,7 @@ static int parse_args(int argc, char **argv)
{
const char *r;
int optind;
- struct qemu_argument *arginfo;
+ const struct qemu_argument *arginfo;
for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
if (arginfo->env == NULL) {
@@ -3519,7 +3520,10 @@ int main(int argc, char **argv, char **envp)
guest_base = init_guest_space(guest_base, reserved_va, 0,
have_guest_base);
if (guest_base == (unsigned long)-1) {
- fprintf(stderr, "Unable to reserve guest address space\n");
+ fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
+ "space for use as guest address space (check your virtual "
+ "memory ulimit setting or reserve less using -R option)\n",
+ reserved_va);
exit(1);
}
@@ -3581,7 +3585,7 @@ int main(int argc, char **argv, char **envp)
ret = loader_exec(filename, target_argv, target_environ, regs,
info, &bprm);
if (ret != 0) {
- printf("Error %d while loading %s\n", ret, filename);
+ printf("Error while loading %s: %s\n", filename, strerror(-ret));
_exit(1);
}
diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h
index db1f98ae69..c3e5c55b3d 100644
--- a/linux-user/microblaze/syscall.h
+++ b/linux-user/microblaze/syscall.h
@@ -1,3 +1,7 @@
+#ifndef MICROBLAZE_SYSCALLS_H
+#define MICROBLAZE_SYSCALLS_H 1
+
+
#define UNAME_MACHINE "microblaze"
/* We use microblaze_reg_t to keep things similar to the kernel sources. */
@@ -43,3 +47,5 @@ struct target_pt_regs {
microblaze_reg_t fsr;
uint32_t kernel_mode;
};
+
+#endif
diff --git a/linux-user/qemu-types.h b/linux-user/qemu-types.h
deleted file mode 100644
index fe7f6624f9..0000000000
--- a/linux-user/qemu-types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef QEMU_TYPES_H
-#define QEMU_TYPES_H
-#include "cpu.h"
-
-#ifdef TARGET_ABI32
-typedef uint32_t abi_ulong;
-typedef int32_t abi_long;
-#define TARGET_ABI_FMT_lx "%08x"
-#define TARGET_ABI_FMT_ld "%d"
-#define TARGET_ABI_FMT_lu "%u"
-#define TARGET_ABI_BITS 32
-
-static inline abi_ulong tswapal(abi_ulong v)
-{
- return tswap32(v);
-}
-
-#else
-typedef target_ulong abi_ulong;
-typedef target_long abi_long;
-#define TARGET_ABI_FMT_lx TARGET_FMT_lx
-#define TARGET_ABI_FMT_ld TARGET_FMT_ld
-#define TARGET_ABI_FMT_lu TARGET_FMT_lu
-#define TARGET_ABI_BITS TARGET_LONG_BITS
-/* for consistency, define ABI32 too */
-#if TARGET_ABI_BITS == 32
-#define TARGET_ABI32 1
-#endif
-
-static inline abi_ulong tswapal(abi_ulong v)
-{
- return tswapl(v);
-}
-
-#endif
-#endif
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 69b27d7146..8a3538c631 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -11,14 +11,14 @@
#include <stdlib.h>
#endif /* DEBUG_REMAP */
-#include "qemu-types.h"
+#include "exec/user/abitypes.h"
-#include "thunk.h"
+#include "exec/user/thunk.h"
#include "syscall_defs.h"
#include "syscall.h"
#include "target_signal.h"
-#include "gdbstub.h"
-#include "qemu-queue.h"
+#include "exec/gdbstub.h"
+#include "qemu/queue.h"
#if defined(CONFIG_USE_NPTL)
#define THREAD __thread
@@ -217,7 +217,10 @@ unsigned long init_guest_space(unsigned long host_start,
unsigned long guest_start,
bool fixed);
-#include "qemu-log.h"
+#include "qemu/log.h"
+
+/* syscall.c */
+int host_to_target_waitstatus(int status);
/* strace.c */
void print_syscall(int num,
@@ -289,46 +292,29 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
* struct has been locked - usually with lock_user_struct().
*/
#define __put_user(x, hptr)\
-({\
+({ __typeof(*hptr) pu_ = (x);\
switch(sizeof(*hptr)) {\
- case 1:\
- *(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\
- break;\
- case 2:\
- *(uint16_t *)(hptr) = tswap16((uint16_t)(typeof(*hptr))(x));\
- break;\
- case 4:\
- *(uint32_t *)(hptr) = tswap32((uint32_t)(typeof(*hptr))(x));\
- break;\
- case 8:\
- *(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\
- break;\
- default:\
- abort();\
+ case 1: break;\
+ case 2: pu_ = tswap16(pu_); break; \
+ case 4: pu_ = tswap32(pu_); break; \
+ case 8: pu_ = tswap64(pu_); break; \
+ default: abort();\
}\
+ memcpy(hptr, &pu_, sizeof(pu_)); \
0;\
})
#define __get_user(x, hptr) \
-({\
+({ __typeof(*hptr) gu_; \
+ memcpy(&gu_, hptr, sizeof(gu_)); \
switch(sizeof(*hptr)) {\
- case 1:\
- x = (typeof(*hptr))*(uint8_t *)(hptr);\
- break;\
- case 2:\
- x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\
- break;\
- case 4:\
- x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\
- break;\
- case 8:\
- x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\
- break;\
- default:\
- /* avoid warning */\
- x = 0;\
- abort();\
+ case 1: break; \
+ case 2: gu_ = tswap16(gu_); break; \
+ case 4: gu_ = tswap32(gu_); break; \
+ case 8: gu_ = tswap64(gu_); break; \
+ default: abort();\
}\
+ (x) = gu_; \
0;\
})
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 78691473fa..95e2ffa007 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -202,46 +202,67 @@ void target_to_host_old_sigset(sigset_t *sigset,
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
const siginfo_t *info)
{
- int sig;
- sig = host_to_target_signal(info->si_signo);
+ int sig = host_to_target_signal(info->si_signo);
tinfo->si_signo = sig;
tinfo->si_errno = 0;
tinfo->si_code = info->si_code;
- if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
- sig == SIGBUS || sig == SIGTRAP) {
- /* should never come here, but who knows. The information for
- the target is irrelevant */
+
+ if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
+ || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
+ /* Should never come here, but who knows. The information for
+ the target is irrelevant. */
tinfo->_sifields._sigfault._addr = 0;
- } else if (sig == SIGIO) {
+ } else if (sig == TARGET_SIGIO) {
+ tinfo->_sifields._sigpoll._band = info->si_band;
tinfo->_sifields._sigpoll._fd = info->si_fd;
+ } else if (sig == TARGET_SIGCHLD) {
+ tinfo->_sifields._sigchld._pid = info->si_pid;
+ tinfo->_sifields._sigchld._uid = info->si_uid;
+ tinfo->_sifields._sigchld._status
+ = host_to_target_waitstatus(info->si_status);
+ tinfo->_sifields._sigchld._utime = info->si_utime;
+ tinfo->_sifields._sigchld._stime = info->si_stime;
} else if (sig >= TARGET_SIGRTMIN) {
tinfo->_sifields._rt._pid = info->si_pid;
tinfo->_sifields._rt._uid = info->si_uid;
/* XXX: potential problem if 64 bit */
- tinfo->_sifields._rt._sigval.sival_ptr =
- (abi_ulong)(unsigned long)info->si_value.sival_ptr;
+ tinfo->_sifields._rt._sigval.sival_ptr
+ = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
}
}
static void tswap_siginfo(target_siginfo_t *tinfo,
const target_siginfo_t *info)
{
- int sig;
- sig = info->si_signo;
+ int sig = info->si_signo;
tinfo->si_signo = tswap32(sig);
tinfo->si_errno = tswap32(info->si_errno);
tinfo->si_code = tswap32(info->si_code);
- if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
- sig == SIGBUS || sig == SIGTRAP) {
- tinfo->_sifields._sigfault._addr =
- tswapal(info->_sifields._sigfault._addr);
- } else if (sig == SIGIO) {
- tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
+
+ if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
+ || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
+ tinfo->_sifields._sigfault._addr
+ = tswapal(info->_sifields._sigfault._addr);
+ } else if (sig == TARGET_SIGIO) {
+ tinfo->_sifields._sigpoll._band
+ = tswap32(info->_sifields._sigpoll._band);
+ tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
+ } else if (sig == TARGET_SIGCHLD) {
+ tinfo->_sifields._sigchld._pid
+ = tswap32(info->_sifields._sigchld._pid);
+ tinfo->_sifields._sigchld._uid
+ = tswap32(info->_sifields._sigchld._uid);
+ tinfo->_sifields._sigchld._status
+ = tswap32(info->_sifields._sigchld._status);
+ tinfo->_sifields._sigchld._utime
+ = tswapal(info->_sifields._sigchld._utime);
+ tinfo->_sifields._sigchld._stime
+ = tswapal(info->_sifields._sigchld._stime);
} else if (sig >= TARGET_SIGRTMIN) {
tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
- tinfo->_sifields._rt._sigval.sival_ptr =
- tswapal(info->_sifields._rt._sigval.sival_ptr);
+ tinfo->_sifields._rt._sigval.sival_ptr
+ = tswapal(info->_sifields._rt._sigval.sival_ptr);
}
}
@@ -2762,7 +2783,6 @@ static void setup_frame(int sig, struct target_sigaction * ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV/*, current*/);
- return;
}
long do_sigreturn(CPUMIPSState *regs)
@@ -2871,7 +2891,6 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV/*, current*/);
- return;
}
long do_rt_sigreturn(CPUMIPSState *env)
diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h
index f201f9f788..061711cc03 100644
--- a/linux-user/sparc/syscall_nr.h
+++ b/linux-user/sparc/syscall_nr.h
@@ -62,8 +62,8 @@
#define TARGET_NR_getpagesize 64 /* Common */
#define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
#define TARGET_NR_vfork 66 /* Common */
-#define TARGET_NR_pread 67 /* Linux Specific */
-#define TARGET_NR_pwrite 68 /* Linux Specific */
+#define TARGET_NR_pread64 67 /* Linux Specific */
+#define TARGET_NR_pwrite64 68 /* Linux Specific */
#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
#define TARGET_NR_mmap 71 /* Common */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index af3c6a0cce..08f115d843 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -972,9 +972,6 @@
#ifdef TARGET_NR_prctl
{ TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
#endif
-#ifdef TARGET_NR_pread
-{ TARGET_NR_pread, "pread" , NULL, NULL, NULL },
-#endif
#ifdef TARGET_NR_pread64
{ TARGET_NR_pread64, "pread64" , NULL, NULL, NULL },
#endif
@@ -993,9 +990,6 @@
#ifdef TARGET_NR_putpmsg
{ TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL },
#endif
-#ifdef TARGET_NR_pwrite
-{ TARGET_NR_pwrite, "pwrite" , NULL, NULL, NULL },
-#endif
#ifdef TARGET_NR_pwrite64
{ TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL },
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41c869bfe0..3167a87549 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -28,6 +28,7 @@
#include <fcntl.h>
#include <time.h>
#include <limits.h>
+#include <grp.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
@@ -35,6 +36,9 @@
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mount.h>
+#include <sys/file.h>
+#include <sys/fsuid.h>
+#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/mman.h>
@@ -72,7 +76,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include <sys/epoll.h>
#endif
#ifdef CONFIG_ATTR
-#include "qemu-xattr.h"
+#include "qemu/xattr.h"
#endif
#define termios host_termios
@@ -580,19 +584,18 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
struct host_rlimit64 *, old_limit)
#endif
-extern int personality(int);
-extern int flock(int, int);
-extern int setfsuid(int);
-extern int setfsgid(int);
-extern int setgroups(int, gid_t *);
-
/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
-#ifdef TARGET_ARM
+#ifdef TARGET_ARM
static inline int regpairs_aligned(void *cpu_env) {
return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
}
#elif defined(TARGET_MIPS)
static inline int regpairs_aligned(void *cpu_env) { return 1; }
+#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
+/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
+ * of registers which translates to the same as ARM/MIPS, because we start with
+ * r3 as arg1 */
+static inline int regpairs_aligned(void *cpu_env) { return 1; }
#else
static inline int regpairs_aligned(void *cpu_env) { return 0; }
#endif
@@ -1744,55 +1747,96 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
return ret;
}
-/* FIXME
- * lock_iovec()/unlock_iovec() have a return code of 0 for success where
- * other lock functions have a return code of 0 for failure.
- */
-static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
- int count, int copy)
+static struct iovec *lock_iovec(int type, abi_ulong target_addr,
+ int count, int copy)
{
struct target_iovec *target_vec;
- abi_ulong base;
+ struct iovec *vec;
+ abi_ulong total_len, max_len;
int i;
- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
- if (!target_vec)
- return -TARGET_EFAULT;
- for(i = 0;i < count; i++) {
- base = tswapal(target_vec[i].iov_base);
- vec[i].iov_len = tswapal(target_vec[i].iov_len);
- if (vec[i].iov_len != 0) {
- vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
- /* Don't check lock_user return value. We must call writev even
- if a element has invalid base address. */
+ if (count == 0) {
+ errno = 0;
+ return NULL;
+ }
+ if (count > IOV_MAX) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ vec = calloc(count, sizeof(struct iovec));
+ if (vec == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ target_vec = lock_user(VERIFY_READ, target_addr,
+ count * sizeof(struct target_iovec), 1);
+ if (target_vec == NULL) {
+ errno = EFAULT;
+ goto fail2;
+ }
+
+ /* ??? If host page size > target page size, this will result in a
+ value larger than what we can actually support. */
+ max_len = 0x7fffffff & TARGET_PAGE_MASK;
+ total_len = 0;
+
+ for (i = 0; i < count; i++) {
+ abi_ulong base = tswapal(target_vec[i].iov_base);
+ abi_long len = tswapal(target_vec[i].iov_len);
+
+ if (len < 0) {
+ errno = EINVAL;
+ goto fail;
+ } else if (len == 0) {
+ /* Zero length pointer is ignored. */
+ vec[i].iov_base = 0;
} else {
- /* zero length pointer is ignored */
- vec[i].iov_base = NULL;
+ vec[i].iov_base = lock_user(type, base, len, copy);
+ if (!vec[i].iov_base) {
+ errno = EFAULT;
+ goto fail;
+ }
+ if (len > max_len - total_len) {
+ len = max_len - total_len;
+ }
}
+ vec[i].iov_len = len;
+ total_len += len;
}
- unlock_user (target_vec, target_addr, 0);
- return 0;
+
+ unlock_user(target_vec, target_addr, 0);
+ return vec;
+
+ fail:
+ free(vec);
+ fail2:
+ unlock_user(target_vec, target_addr, 0);
+ return NULL;
}
-static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
- int count, int copy)
+static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+ int count, int copy)
{
struct target_iovec *target_vec;
- abi_ulong base;
int i;
- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
- if (!target_vec)
- return -TARGET_EFAULT;
- for(i = 0;i < count; i++) {
- if (target_vec[i].iov_base) {
- base = tswapal(target_vec[i].iov_base);
+ target_vec = lock_user(VERIFY_READ, target_addr,
+ count * sizeof(struct target_iovec), 1);
+ if (target_vec) {
+ for (i = 0; i < count; i++) {
+ abi_ulong base = tswapal(target_vec[i].iov_base);
+ abi_long len = tswapal(target_vec[i].iov_base);
+ if (len < 0) {
+ break;
+ }
unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
}
+ unlock_user(target_vec, target_addr, 0);
}
- unlock_user (target_vec, target_addr, 0);
- return 0;
+ free(vec);
}
/* do_socket() Must return target values and target errnos. */
@@ -1888,8 +1932,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
msg.msg_namelen);
if (ret) {
- unlock_user_struct(msgp, target_msg, send ? 0 : 1);
- return ret;
+ goto out2;
}
} else {
msg.msg_name = NULL;
@@ -1900,9 +1943,13 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
msg.msg_flags = tswap32(msgp->msg_flags);
count = tswapal(msgp->msg_iovlen);
- vec = alloca(count * sizeof(struct iovec));
target_vec = tswapal(msgp->msg_iov);
- lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
+ vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
+ target_vec, count, send);
+ if (vec == NULL) {
+ ret = -host_to_target_errno(errno);
+ goto out2;
+ }
msg.msg_iovlen = count;
msg.msg_iov = vec;
@@ -1932,6 +1979,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
out:
unlock_iovec(vec, target_vec, count, !send);
+out2:
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
return ret;
}
@@ -2848,7 +2896,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
return -TARGET_EFAULT;
- host_mb = malloc(msgsz+sizeof(long));
+ host_mb = g_malloc(msgsz+sizeof(long));
ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
if (ret > 0) {
@@ -2863,11 +2911,11 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
}
target_mb->mtype = tswapal(host_mb->mtype);
- free(host_mb);
end:
if (target_mb)
unlock_user_struct(target_mb, msgp, 1);
+ g_free(host_mb);
return ret;
}
@@ -3628,9 +3676,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
unlock_user(argptr, arg, target_size);
}
out:
- if (big_buf) {
- free(big_buf);
- }
+ g_free(big_buf);
return ret;
}
@@ -4875,7 +4921,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
/* Map host to target signal numbers for the wait family of syscalls.
Assume all other status bits are the same. */
-static int host_to_target_waitstatus(int status)
+int host_to_target_waitstatus(int status)
{
if (WIFSIGNALED(status)) {
return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
@@ -4964,8 +5010,8 @@ static int open_self_maps(void *cpu_env, int fd)
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
(unsigned long long)ts->info->stack_limit,
- (unsigned long long)(ts->stack_base + (TARGET_PAGE_SIZE - 1))
- & TARGET_PAGE_MASK,
+ (unsigned long long)(ts->info->start_stack +
+ (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK,
(unsigned long long)0);
#endif
@@ -6531,6 +6577,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
+ __put_user(stfs.f_frsize, &target_stfs->f_frsize);
+ memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
unlock_user_struct(target_stfs, arg2, 1);
}
break;
@@ -6559,6 +6607,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
+ __put_user(stfs.f_frsize, &target_stfs->f_frsize);
+ memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
unlock_user_struct(target_stfs, arg3, 1);
}
break;
@@ -6890,6 +6940,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#elif defined(TARGET_CRIS)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
+#elif defined(TARGET_MICROBLAZE)
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
#elif defined(TARGET_S390X)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
#else
@@ -7025,15 +7077,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
tde = target_dirp;
while (len > 0) {
reclen = de->d_reclen;
- treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
+ tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+ assert(tnamelen >= 0);
+ treclen = tnamelen + offsetof(struct target_dirent, d_name);
+ assert(count1 + treclen <= count);
tde->d_reclen = tswap16(treclen);
tde->d_ino = tswapal(de->d_ino);
tde->d_off = tswapal(de->d_off);
- tnamelen = treclen - (2 * sizeof(abi_long) + 2);
- if (tnamelen > 256)
- tnamelen = 256;
- /* XXX: may not be correct */
- pstrcpy(tde->d_name, tnamelen, de->d_name);
+ memcpy(tde->d_name, de->d_name, tnamelen);
de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
tde = (struct target_dirent *)((char *)tde + treclen);
@@ -7187,26 +7238,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
case TARGET_NR_readv:
{
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
- goto efault;
- ret = get_errno(readv(arg1, vec, count));
- unlock_iovec(vec, arg2, count, 1);
+ struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
+ if (vec != NULL) {
+ ret = get_errno(readv(arg1, vec, arg3));
+ unlock_iovec(vec, arg2, arg3, 1);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
}
break;
case TARGET_NR_writev:
{
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
- goto efault;
- ret = get_errno(writev(arg1, vec, count));
- unlock_iovec(vec, arg2, count, 0);
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
+ if (vec != NULL) {
+ ret = get_errno(writev(arg1, vec, arg3));
+ unlock_iovec(vec, arg2, arg3, 0);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
}
break;
case TARGET_NR_getsid:
@@ -7398,32 +7447,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto unimplemented;
#endif
#endif
-#ifdef TARGET_NR_pread
- case TARGET_NR_pread:
- if (regpairs_aligned(cpu_env))
- arg4 = arg5;
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(pread(arg1, p, arg3, arg4));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_NR_pwrite:
- if (regpairs_aligned(cpu_env))
- arg4 = arg5;
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(pwrite(arg1, p, arg3, arg4));
- unlock_user(p, arg2, 0);
- break;
-#endif
#ifdef TARGET_NR_pread64
case TARGET_NR_pread64:
+ if (regpairs_aligned(cpu_env)) {
+ arg4 = arg5;
+ arg5 = arg6;
+ }
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
goto efault;
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
unlock_user(p, arg2, ret);
break;
case TARGET_NR_pwrite64:
+ if (regpairs_aligned(cpu_env)) {
+ arg4 = arg5;
+ arg5 = arg6;
+ }
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
goto efault;
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
@@ -8631,14 +8670,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_vmsplice
case TARGET_NR_vmsplice:
{
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
- goto efault;
- ret = get_errno(vmsplice(arg1, vec, count, arg4));
- unlock_iovec(vec, arg2, count, 0);
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
+ if (vec != NULL) {
+ ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
+ unlock_iovec(vec, arg2, arg3, 0);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
}
break;
#endif
@@ -8825,6 +8863,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
}
#endif
+#ifdef TARGET_NR_gethostname
+ case TARGET_NR_gethostname:
+ {
+ char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+ if (name) {
+ ret = get_errno(gethostname(name, arg2));
+ unlock_user(name, arg1, arg2);
+ } else {
+ ret = -TARGET_EFAULT;
+ }
+ break;
+ }
+#endif
default:
unimplemented:
gemu_log("qemu: Unsupported syscall: %d\n", num);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2cfda5afd5..d4589e7906 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -4,6 +4,10 @@
most of them stay the same, so we handle it by putting ifdefs if
necessary */
+#ifndef SYSCALL_DEFS_H
+#define SYSCALL_DEFS_H 1
+
+
#include "syscall_nr.h"
#define SOCKOP_socket 1
@@ -255,10 +259,10 @@ struct kernel_statfs {
};
struct target_dirent {
- abi_long d_ino;
- abi_long d_off;
- unsigned short d_reclen;
- char d_name[256]; /* We must not include limits.h! */
+ abi_long d_ino;
+ abi_long d_off;
+ unsigned short d_reclen;
+ char d_name[];
};
struct target_dirent64 {
@@ -2425,3 +2429,5 @@ struct target_ucred {
uint32_t uid;
uint32_t gid;
};
+
+#endif
diff --git a/linux-user/unicore32/syscall_nr.h b/linux-user/unicore32/syscall_nr.h
index 9c72d84d80..486b8c45a0 100644
--- a/linux-user/unicore32/syscall_nr.h
+++ b/linux-user/unicore32/syscall_nr.h
@@ -187,8 +187,8 @@
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
-#define TARGET_NR_pread 180
-#define TARGET_NR_pwrite 181
+#define TARGET_NR_pread64 180
+#define TARGET_NR_pwrite64 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184