diff options
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/alpha/target_signal.h | 7 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/double_cpdo.c | 2 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/extended_cpdo.c | 2 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/fpa11.h | 2 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/fpa11_cpdt.c | 2 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/fpa11_cprt.c | 2 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/fpopcode.c | 2 | ||||
-rw-r--r-- | linux-user/arm/nwfpe/single_cpdo.c | 2 | ||||
-rw-r--r-- | linux-user/arm/syscall_nr.h | 4 | ||||
-rw-r--r-- | linux-user/cris/syscall.h | 5 | ||||
-rw-r--r-- | linux-user/elfload.c | 14 | ||||
-rw-r--r-- | linux-user/i386/syscall_nr.h | 4 | ||||
-rw-r--r-- | linux-user/linuxload.c | 8 | ||||
-rw-r--r-- | linux-user/main.c | 56 | ||||
-rw-r--r-- | linux-user/microblaze/syscall.h | 6 | ||||
-rw-r--r-- | linux-user/qemu-types.h | 36 | ||||
-rw-r--r-- | linux-user/qemu.h | 60 | ||||
-rw-r--r-- | linux-user/signal.c | 61 | ||||
-rw-r--r-- | linux-user/sparc/syscall_nr.h | 4 | ||||
-rw-r--r-- | linux-user/strace.list | 6 | ||||
-rw-r--r-- | linux-user/syscall.c | 251 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 14 | ||||
-rw-r--r-- | linux-user/unicore32/syscall_nr.h | 4 |
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 |