linux-user changes since 2.7 release

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIVAwUAV+PJ7bRIkN7ePJvAAQjvYRAAnX95B4PPTzCCImLUOsAWg/B6ImlZ1YFG
 d7SVCXyjbyCvoP4/tgHuajYUTHiIQ9H7mCyZXJWSkqO/h23TFrbtxofN0e+dWl1s
 t+Hot7y/WqRKnuZoXy+ww8Oc0uyEQYoPMlhaPz8CqNxnKPaihBVVWbWFn+yDp0k9
 DMfsEqUWQ+/kLkaMpOzInDbuZDAq8/36MUE/cw1+rFZ3MYYs9TSHwVxgXZjX89Cs
 d2xyNj8hxlQDfcG9rWWS7UrqzYqejD9j3cuvP7Q874aXdIPDIHkEbRGPVIPdYen7
 QaIJ0xOpryaOqRmGW5+sLkoQFDTo6FOOxGB0MsKOghSSdv8ET+W0+Y+hTC637FEO
 Eqj2OtrKvN/TlTRV6fDqfov5NXbM63N1rRQdondLUopSnGal7FBIkZL7WfSyYzif
 DTkLwtff3dNiOM7gLPC3tP9BTSdQuXvSXHeqDVHvtopQa04IwE3LD4DbBQdMj5BU
 MzmdVgwW2kkWej5BKlIrG3JzhKe6u2E/S3MPd3z6lJzERdaIgJIoZv1W2lJOSAaO
 aw0E1BOcQLMGSjdh2Gj+La3YVZeMqu2gMyqPS6vjd6UzyTfu8i1AR1bGtYeacZSz
 jEfFcMESo7WjpbsrA5V8ch5Hw95s0YU3qhsG3AsDjj9ChE9QKj7v3wYJY2l9Fi4t
 UY3zOajB0eY=
 =w4/p
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20160915' into staging

linux-user changes since 2.7 release

# gpg: Signature made Thu 22 Sep 2016 13:09:17 BST
# gpg:                using RSA key 0xB44890DEDE3C9BC0
# gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>"
# gpg:                 aka "Riku Voipio <riku.voipio@linaro.org>"
# Primary key fingerprint: FF82 03C8 C391 98AE 0581  41EF B448 90DE DE3C 9BC0

* remotes/riku/tags/pull-linux-user-20160915: (26 commits)
  linux-user: fix TARGET_NR_select
  linux-user: Fix incorrect offset of tuc_stack in ARM do_sigframe_return_v2
  linux-user: Sanity check clone flags
  linux-user: Remove unnecessary nptl_flags variable from do_fork()
  linux-user: Implement force_sigsegv() via force_sig()
  linux-user: SIGSEGV from sigreturn need not be fatal
  linux-user: ARM: Give SIGSEGV if signal frame setup fails
  linux-user: SIGSEGV on signal entry need not be fatal
  linux-user: Pass si_type information to queue_signal() explicitly
  linux-user: Recheck for pending synchronous signals too
  linux-user: ppc64: set MSR_CM bit for BookE 2.06 MMU
  linux-user: Use correct target SHMLBA in shmat()
  linux-user: Use glib malloc functions in load_symbols()
  linux-user: Check dump_write() return in elf_core_dump()
  linux-user: Fix error handling in flatload.c target_pread()
  linux-user: Fix incorrect use of host errno in do_ioctl_dm()
  linux-user: Check lock_user() return value for NULL
  linux-user: Pass missing MAP_ANONYMOUS to target_mmap() call
  linux-user: report signals being taken in strace output
  linux-user: Range check the nfds argument to ppoll syscall
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-09-22 15:39:54 +01:00
commit 430da7a81d
21 changed files with 581 additions and 213 deletions

View File

@ -32,5 +32,13 @@ struct target_pt_regs {
#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MINSIGSTKSZ 2048
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_WANT_OLD_SYS_SELECT
#define TARGET_FORCE_SHMLBA
static inline abi_ulong target_shmlba(CPUARMState *env)
{
return 4 * 4096;
}
#endif /* ARM_TARGET_SYSCALL_H */ #endif /* ARM_TARGET_SYSCALL_H */

View File

@ -2111,19 +2111,19 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
found: found:
/* Now know where the strtab and symtab are. Snarf them. */ /* Now know where the strtab and symtab are. Snarf them. */
s = malloc(sizeof(*s)); s = g_try_new(struct syminfo, 1);
if (!s) { if (!s) {
goto give_up; goto give_up;
} }
i = shdr[str_idx].sh_size; i = shdr[str_idx].sh_size;
s->disas_strtab = strings = malloc(i); s->disas_strtab = strings = g_try_malloc(i);
if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) { if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
goto give_up; goto give_up;
} }
i = shdr[sym_idx].sh_size; i = shdr[sym_idx].sh_size;
syms = malloc(i); syms = g_try_malloc(i);
if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) { if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
goto give_up; goto give_up;
} }
@ -2157,7 +2157,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
that we threw away. Whether or not this has any effect on the that we threw away. Whether or not this has any effect on the
memory allocation depends on the malloc implementation and how memory allocation depends on the malloc implementation and how
many symbols we managed to discard. */ many symbols we managed to discard. */
new_syms = realloc(syms, nsyms * sizeof(*syms)); new_syms = g_try_renew(struct elf_sym, syms, nsyms);
if (new_syms == NULL) { if (new_syms == NULL) {
goto give_up; goto give_up;
} }
@ -2178,9 +2178,9 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
return; return;
give_up: give_up:
free(s); g_free(s);
free(strings); g_free(strings);
free(syms); g_free(syms);
} }
int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
@ -2233,7 +2233,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
we do not have the power to recompile these, we emulate we do not have the power to recompile these, we emulate
the SVr4 behavior. Sigh. */ the SVr4 behavior. Sigh. */
target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, -1, 0); MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
} }
} }
@ -3050,7 +3050,9 @@ static int elf_core_dump(int signr, const CPUArchState *env)
phdr.p_align = ELF_EXEC_PAGESIZE; phdr.p_align = ELF_EXEC_PAGESIZE;
bswap_phdr(&phdr, 1); bswap_phdr(&phdr, 1);
dump_write(fd, &phdr, sizeof (phdr)); if (dump_write(fd, &phdr, sizeof(phdr)) != 0) {
goto out;
}
} }
/* /*

View File

@ -95,7 +95,13 @@ static int target_pread(int fd, abi_ulong ptr, abi_ulong len,
int ret; int ret;
buf = lock_user(VERIFY_WRITE, ptr, len, 0); buf = lock_user(VERIFY_WRITE, ptr, len, 0);
if (!buf) {
return -EFAULT;
}
ret = pread(fd, buf, len, offset); ret = pread(fd, buf, len, offset);
if (ret < 0) {
ret = -errno;
}
unlock_user(buf, ptr, len); unlock_user(buf, ptr, len);
return ret; return ret;
} }

View File

@ -153,5 +153,6 @@ struct target_vm86plus_struct {
#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MINSIGSTKSZ 2048
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_WANT_OLD_SYS_SELECT
#endif /* I386_TARGET_SYSCALL_H */ #endif /* I386_TARGET_SYSCALL_H */

View File

@ -120,6 +120,9 @@
MK_PTR(MK_STRUCT(STRUCT_fiemap))) MK_PTR(MK_STRUCT(STRUCT_fiemap)))
#endif #endif
IOCTL(FS_IOC_GETFLAGS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(FS_IOC_SETFLAGS, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT)) IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))

View File

@ -24,6 +24,8 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_WANT_OLD_SYS_SELECT
void do_m68k_simcall(CPUM68KState *, int); void do_m68k_simcall(CPUM68KState *, int);
#endif /* M68K_TARGET_SYSCALL_H */ #endif /* M68K_TARGET_SYSCALL_H */

View File

@ -339,7 +339,7 @@ void cpu_loop(CPUX86State *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL; info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP0D_GPF: case EXCP0D_GPF:
/* XXX: potential problem if ABI32 */ /* XXX: potential problem if ABI32 */
@ -353,7 +353,7 @@ void cpu_loop(CPUX86State *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL; info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP0E_PAGE: case EXCP0E_PAGE:
@ -364,7 +364,7 @@ void cpu_loop(CPUX86State *env)
else else
info.si_code = TARGET_SEGV_ACCERR; info.si_code = TARGET_SEGV_ACCERR;
info._sifields._sigfault._addr = env->cr[2]; info._sifields._sigfault._addr = env->cr[2];
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP00_DIVZ: case EXCP00_DIVZ:
#ifndef TARGET_X86_64 #ifndef TARGET_X86_64
@ -378,7 +378,7 @@ void cpu_loop(CPUX86State *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_FPE_INTDIV; info.si_code = TARGET_FPE_INTDIV;
info._sifields._sigfault._addr = env->eip; info._sifields._sigfault._addr = env->eip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP01_DB: case EXCP01_DB:
@ -398,7 +398,7 @@ void cpu_loop(CPUX86State *env)
info.si_code = TARGET_SI_KERNEL; info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
} }
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP04_INTO: case EXCP04_INTO:
@ -413,7 +413,7 @@ void cpu_loop(CPUX86State *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL; info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP06_ILLOP: case EXCP06_ILLOP:
@ -421,7 +421,7 @@ void cpu_loop(CPUX86State *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN; info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->eip; info._sifields._sigfault._addr = env->eip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
@ -436,7 +436,7 @@ void cpu_loop(CPUX86State *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -576,7 +576,7 @@ segv:
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->exception.vaddress; info._sifields._sigfault._addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
/* Handle a jump to the kernel code page. */ /* Handle a jump to the kernel code page. */
@ -755,7 +755,7 @@ void cpu_loop(CPUARMState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN; info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->regs[15]; info._sifields._sigfault._addr = env->regs[15];
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} else if (rc < 0) { /* FP exception */ } else if (rc < 0) { /* FP exception */
int arm_fpe=0; int arm_fpe=0;
@ -786,7 +786,7 @@ void cpu_loop(CPUARMState *env)
if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
info._sifields._sigfault._addr = env->regs[15]; info._sifields._sigfault._addr = env->regs[15];
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} else { } else {
env->regs[15] += 4; env->regs[15] += 4;
} }
@ -907,7 +907,7 @@ void cpu_loop(CPUARMState *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = addr; info._sifields._sigfault._addr = addr;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
@ -921,7 +921,7 @@ void cpu_loop(CPUARMState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -1099,7 +1099,7 @@ void cpu_loop(CPUARMState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN; info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_STREX: case EXCP_STREX:
if (!do_strex_a64(env)) { if (!do_strex_a64(env)) {
@ -1113,7 +1113,7 @@ void cpu_loop(CPUARMState *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->exception.vaddress; info._sifields._sigfault._addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
case EXCP_BKPT: case EXCP_BKPT:
@ -1122,7 +1122,7 @@ void cpu_loop(CPUARMState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_SEMIHOST: case EXCP_SEMIHOST:
@ -1202,7 +1202,7 @@ void cpu_loop(CPUUniCore32State *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->cp0.c4_faultaddr; info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
@ -1216,7 +1216,7 @@ void cpu_loop(CPUUniCore32State *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -1431,7 +1431,7 @@ void cpu_loop (CPUSPARCState *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->mmuregs[4]; info._sifields._sigfault._addr = env->mmuregs[4];
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
#else #else
@ -1452,7 +1452,7 @@ void cpu_loop (CPUSPARCState *env)
info._sifields._sigfault._addr = env->dmmuregs[4]; info._sifields._sigfault._addr = env->dmmuregs[4];
else else
info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
#ifndef TARGET_ABI32 #ifndef TARGET_ABI32
@ -1475,7 +1475,7 @@ void cpu_loop (CPUSPARCState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC; info.si_code = TARGET_ILL_ILLOPC;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
@ -1488,7 +1488,7 @@ void cpu_loop (CPUSPARCState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -1679,7 +1679,7 @@ void cpu_loop(CPUPPCState *env)
break; break;
} }
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_ISI: /* Instruction storage exception */ case POWERPC_EXCP_ISI: /* Instruction storage exception */
/* XXX: check this */ /* XXX: check this */
@ -1705,7 +1705,7 @@ void cpu_loop(CPUPPCState *env)
break; break;
} }
info._sifields._sigfault._addr = env->nip - 4; info._sifields._sigfault._addr = env->nip - 4;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_EXTERNAL: /* External input */ case POWERPC_EXCP_EXTERNAL: /* External input */
cpu_abort(cs, "External interrupt while in user mode. " cpu_abort(cs, "External interrupt while in user mode. "
@ -1717,7 +1717,7 @@ void cpu_loop(CPUPPCState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN; info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_PROGRAM: /* Program exception */ case POWERPC_EXCP_PROGRAM: /* Program exception */
case POWERPC_EXCP_HV_EMU: /* HV emulation */ case POWERPC_EXCP_HV_EMU: /* HV emulation */
@ -1808,14 +1808,14 @@ void cpu_loop(CPUPPCState *env)
break; break;
} }
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
info.si_signo = TARGET_SIGILL; info.si_signo = TARGET_SIGILL;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC; info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_SYSCALL: /* System call exception */ case POWERPC_EXCP_SYSCALL: /* System call exception */
cpu_abort(cs, "Syscall exception while in user mode. " cpu_abort(cs, "Syscall exception while in user mode. "
@ -1826,7 +1826,7 @@ void cpu_loop(CPUPPCState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC; info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_DECR: /* Decrementer exception */ case POWERPC_EXCP_DECR: /* Decrementer exception */
cpu_abort(cs, "Decrementer interrupt while in user mode. " cpu_abort(cs, "Decrementer interrupt while in user mode. "
@ -1853,7 +1853,7 @@ void cpu_loop(CPUPPCState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC; info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
@ -1916,7 +1916,7 @@ void cpu_loop(CPUPPCState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC; info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
cpu_abort(cs, "Programmable interval timer interrupt " cpu_abort(cs, "Programmable interval timer interrupt "
@ -2010,7 +2010,7 @@ void cpu_loop(CPUPPCState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->nip; info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
@ -2022,7 +2022,7 @@ void cpu_loop(CPUPPCState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -2456,13 +2456,13 @@ static int do_break(CPUMIPSState *env, target_siginfo_t *info,
info->si_signo = TARGET_SIGFPE; info->si_signo = TARGET_SIGFPE;
info->si_errno = 0; info->si_errno = 0;
info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
queue_signal(env, info->si_signo, &*info); queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
ret = 0; ret = 0;
break; break;
default: default:
info->si_signo = TARGET_SIGTRAP; info->si_signo = TARGET_SIGTRAP;
info->si_errno = 0; info->si_errno = 0;
queue_signal(env, info->si_signo, &*info); queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
ret = 0; ret = 0;
break; break;
} }
@ -2560,14 +2560,14 @@ done_syscall:
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->CP0_BadVAddr; info._sifields._sigfault._addr = env->CP0_BadVAddr;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_CpU: case EXCP_CpU:
case EXCP_RI: case EXCP_RI:
info.si_signo = TARGET_SIGILL; info.si_signo = TARGET_SIGILL;
info.si_errno = 0; info.si_errno = 0;
info.si_code = 0; info.si_code = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
@ -2582,7 +2582,7 @@ done_syscall:
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -2592,14 +2592,14 @@ done_syscall:
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->active_tc.PC; info._sifields._sigfault._addr = env->active_tc.PC;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_DSPDIS: case EXCP_DSPDIS:
info.si_signo = TARGET_SIGILL; info.si_signo = TARGET_SIGILL;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC; info.si_code = TARGET_ILL_ILLOPC;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
/* The code below was inspired by the MIPS Linux kernel trap /* The code below was inspired by the MIPS Linux kernel trap
* handling code in arch/mips/kernel/traps.c. * handling code in arch/mips/kernel/traps.c.
@ -2850,7 +2850,7 @@ void cpu_loop(CPUSH4State *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -2860,7 +2860,7 @@ void cpu_loop(CPUSH4State *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->tea; info._sifields._sigfault._addr = env->tea;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
default: default:
@ -2892,7 +2892,7 @@ void cpu_loop(CPUCRISState *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->pregs[PR_EDA]; info._sifields._sigfault._addr = env->pregs[PR_EDA];
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
@ -2924,7 +2924,7 @@ void cpu_loop(CPUCRISState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -2957,7 +2957,7 @@ void cpu_loop(CPUMBState *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
@ -3006,7 +3006,7 @@ void cpu_loop(CPUMBState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_FPE_FLTDIV; info.si_code = TARGET_FPE_FLTDIV;
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case ESR_EC_FPU: case ESR_EC_FPU:
info.si_signo = TARGET_SIGFPE; info.si_signo = TARGET_SIGFPE;
@ -3018,7 +3018,7 @@ void cpu_loop(CPUMBState *env)
info.si_code = TARGET_FPE_FLTDIV; info.si_code = TARGET_FPE_FLTDIV;
} }
info._sifields._sigfault._addr = 0; info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
default: default:
printf ("Unhandled hw-exception: 0x%x\n", printf ("Unhandled hw-exception: 0x%x\n",
@ -3038,7 +3038,7 @@ void cpu_loop(CPUMBState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -3092,7 +3092,7 @@ void cpu_loop(CPUM68KState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN; info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_TRAP0: case EXCP_TRAP0:
{ {
@ -3126,7 +3126,7 @@ void cpu_loop(CPUM68KState *env)
/* XXX: check env->error_code */ /* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->mmu.ar; info._sifields._sigfault._addr = env->mmu.ar;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
@ -3139,7 +3139,7 @@ void cpu_loop(CPUM68KState *env)
info.si_signo = sig; info.si_signo = sig;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -3195,7 +3195,7 @@ static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = addr; info._sifields._sigfault._addr = addr;
queue_signal(env, TARGET_SIGSEGV, &info); queue_signal(env, TARGET_SIGSEGV, QEMU_SI_FAULT, &info);
} }
void cpu_loop(CPUAlphaState *env) void cpu_loop(CPUAlphaState *env)
@ -3237,7 +3237,7 @@ void cpu_loop(CPUAlphaState *env)
info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
info._sifields._sigfault._addr = env->trap_arg0; info._sifields._sigfault._addr = env->trap_arg0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_UNALIGN: case EXCP_UNALIGN:
env->lock_addr = -1; env->lock_addr = -1;
@ -3245,7 +3245,7 @@ void cpu_loop(CPUAlphaState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN; info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = env->trap_arg0; info._sifields._sigfault._addr = env->trap_arg0;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_OPCDEC: case EXCP_OPCDEC:
do_sigill: do_sigill:
@ -3254,7 +3254,7 @@ void cpu_loop(CPUAlphaState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC; info.si_code = TARGET_ILL_ILLOPC;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ARITH: case EXCP_ARITH:
env->lock_addr = -1; env->lock_addr = -1;
@ -3262,7 +3262,7 @@ void cpu_loop(CPUAlphaState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_FPE_FLTINV; info.si_code = TARGET_FPE_FLTINV;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_FEN: case EXCP_FEN:
/* No-op. Linux simply re-enables the FPU. */ /* No-op. Linux simply re-enables the FPU. */
@ -3276,7 +3276,7 @@ void cpu_loop(CPUAlphaState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case 0x81: case 0x81:
/* BUGCHK */ /* BUGCHK */
@ -3284,7 +3284,7 @@ void cpu_loop(CPUAlphaState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = 0; info.si_code = 0;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case 0x83: case 0x83:
/* CALLSYS */ /* CALLSYS */
@ -3356,7 +3356,7 @@ void cpu_loop(CPUAlphaState *env)
} }
info.si_errno = 0; info.si_errno = 0;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
default: default:
goto do_sigill; goto do_sigill;
@ -3368,7 +3368,7 @@ void cpu_loop(CPUAlphaState *env)
env->lock_addr = -1; env->lock_addr = -1;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT; info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
break; break;
case EXCP_STL_C: case EXCP_STL_C:
@ -3502,7 +3502,7 @@ void cpu_loop(CPUS390XState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = n; info.si_code = n;
info._sifields._sigfault._addr = addr; info._sifields._sigfault._addr = addr;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
default: default:
@ -3526,7 +3526,7 @@ static void gen_sigill_reg(CPUTLGState *env)
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_ILL_PRVREG; info.si_code = TARGET_ILL_PRVREG;
info._sifields._sigfault._addr = env->pc; info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
static void do_signal(CPUTLGState *env, int signo, int sigcode) static void do_signal(CPUTLGState *env, int signo, int sigcode)
@ -3550,7 +3550,7 @@ static void do_signal(CPUTLGState *env, int signo, int sigcode)
} }
info.si_code = sigcode; info.si_code = sigcode;
queue_signal(env, info.si_signo, &info); queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
} }
static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr) static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr)
@ -4615,10 +4615,11 @@ int main(int argc, char **argv, char **envp)
int i; int i;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF;
#if defined(TARGET_ABI32) #if defined(TARGET_ABI32)
env->msr &= ~((target_ulong)1 << MSR_SF); env->msr &= ~((target_ulong)1 << flag);
#else #else
env->msr |= (target_ulong)1 << MSR_SF; env->msr |= (target_ulong)1 << flag;
#endif #endif
#endif #endif
env->nip = regs->nip; env->nip = regs->nip;

View File

@ -53,4 +53,6 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_WANT_NI_OLD_SELECT
#endif #endif

View File

@ -230,4 +230,11 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_FORCE_SHMLBA
static inline abi_ulong target_shmlba(CPUMIPSState *env)
{
return 0x40000;
}
#endif /* MIPS_TARGET_SYSCALL_H */ #endif /* MIPS_TARGET_SYSCALL_H */

View File

@ -227,4 +227,11 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_FORCE_SHMLBA
static inline abi_ulong target_shmlba(CPUMIPSState *env)
{
return 0x40000;
}
#endif /* MIPS64_TARGET_SYSCALL_H */ #endif /* MIPS64_TARGET_SYSCALL_H */

View File

@ -459,8 +459,6 @@
#define TARGET_NR_getdents 1065 #define TARGET_NR_getdents 1065
#define __ARCH_WANT_SYS_GETDENTS #define __ARCH_WANT_SYS_GETDENTS
#define TARGET_NR_futimesat 1066 #define TARGET_NR_futimesat 1066
#define TARGET_NR_select 1067
#define __ARCH_WANT_SYS_SELECT
#define TARGET_NR_poll 1068 #define TARGET_NR_poll 1068
#define TARGET_NR_epoll_wait 1069 #define TARGET_NR_epoll_wait 1069
#define TARGET_NR_ustat 1070 #define TARGET_NR_ustat 1070

View File

@ -74,5 +74,6 @@ struct target_revectored_struct {
#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MINSIGSTKSZ 2048
#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 #define TARGET_MLOCKALL_MCL_FUTURE 0x4000
#define TARGET_WANT_NI_OLD_SELECT
#endif /* PPC_TARGET_SYSCALL_H */ #endif /* PPC_TARGET_SYSCALL_H */

View File

@ -362,12 +362,23 @@ void print_syscall(int num,
abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6); abi_long arg4, abi_long arg5, abi_long arg6);
void print_syscall_ret(int num, abi_long arg1); void print_syscall_ret(int num, abi_long arg1);
/**
* print_taken_signal:
* @target_signum: target signal being taken
* @tinfo: target_siginfo_t which will be passed to the guest for the signal
*
* Print strace output indicating that this signal is being taken by the guest,
* in a format similar to:
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
*/
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo);
extern int do_strace; extern int do_strace;
/* signal.c */ /* signal.c */
void process_pending_signals(CPUArchState *cpu_env); void process_pending_signals(CPUArchState *cpu_env);
void signal_init(void); void signal_init(void);
int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info); int queue_signal(CPUArchState *env, int sig, int si_type,
target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
int target_to_host_signal(int sig); int target_to_host_signal(int sig);

View File

@ -84,7 +84,7 @@
#define TARGET_NR_settimeofday 79 #define TARGET_NR_settimeofday 79
#define TARGET_NR_getgroups 80 #define TARGET_NR_getgroups 80
#define TARGET_NR_setgroups 81 #define TARGET_NR_setgroups 81
#define TARGET_NR_select 82 /* 82 was sys_oldselect */
#define TARGET_NR_symlink 83 #define TARGET_NR_symlink 83
#define TARGET_NR_oldlstat 84 #define TARGET_NR_oldlstat 84
#define TARGET_NR_readlink 85 #define TARGET_NR_readlink 85

View File

@ -19,4 +19,11 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2 #define TARGET_MLOCKALL_MCL_FUTURE 2
#define TARGET_FORCE_SHMLBA
static inline abi_ulong target_shmlba(CPUSH4State *env)
{
return 0x4000;
}
#endif /* SH4_TARGET_SYSCALL_H */ #endif /* SH4_TARGET_SYSCALL_H */

View File

@ -512,9 +512,43 @@ void signal_init(void)
} }
} }
#if !(defined(TARGET_X86_64) || defined(TARGET_UNICORE32))
/* Force a synchronously taken signal. The kernel force_sig() function
* also forces the signal to "not blocked, not ignored", but for QEMU
* that work is done in process_pending_signals().
*/
static void force_sig(int sig)
{
CPUState *cpu = thread_cpu;
CPUArchState *env = cpu->env_ptr;
target_siginfo_t info;
info.si_signo = sig;
info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL;
info._sifields._kill._pid = 0;
info._sifields._kill._uid = 0;
queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
}
/* Force a SIGSEGV if we couldn't write to memory trying to set
* up the signal frame. oldsig is the signal we were trying to handle
* at the point of failure.
*/
static void force_sigsegv(int oldsig)
{
if (oldsig == SIGSEGV) {
/* Make sure we don't try to deliver the signal again; this will
* end up with handle_pending_signal() calling dump_core_and_abort().
*/
sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
}
force_sig(TARGET_SIGSEGV);
}
#endif
/* abort execution with signal */ /* abort execution with signal */
static void QEMU_NORETURN force_sig(int target_sig) static void QEMU_NORETURN dump_core_and_abort(int target_sig)
{ {
CPUState *cpu = thread_cpu; CPUState *cpu = thread_cpu;
CPUArchState *env = cpu->env_ptr; CPUArchState *env = cpu->env_ptr;
@ -569,19 +603,15 @@ static void QEMU_NORETURN force_sig(int target_sig)
/* queue a signal so that it will be send to the virtual CPU as soon /* queue a signal so that it will be send to the virtual CPU as soon
as possible */ as possible */
int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) int queue_signal(CPUArchState *env, int sig, int si_type,
target_siginfo_t *info)
{ {
CPUState *cpu = ENV_GET_CPU(env); CPUState *cpu = ENV_GET_CPU(env);
TaskState *ts = cpu->opaque; TaskState *ts = cpu->opaque;
trace_user_queue_signal(env, sig); trace_user_queue_signal(env, sig);
/* Currently all callers define siginfo structures which info->si_code = deposit32(info->si_code, 16, 16, si_type);
* use the _sifields._sigfault union member, so we can
* set the type here. If that changes we should push this
* out so the si_type is passed in by callers.
*/
info->si_code = deposit32(info->si_code, 16, 16, QEMU_SI_FAULT);
ts->sync_signal.info = *info; ts->sync_signal.info = *info;
ts->sync_signal.pending = sig; ts->sync_signal.pending = sig;
@ -1015,10 +1045,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == TARGET_SIGSEGV) { force_sigsegv(sig);
ka->_sa_handler = TARGET_SIG_DFL;
}
force_sig(TARGET_SIGSEGV /* , current */);
} }
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */ /* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
@ -1088,10 +1115,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == TARGET_SIGSEGV) { force_sigsegv(sig);
ka->_sa_handler = TARGET_SIG_DFL;
}
force_sig(TARGET_SIGSEGV /* , current */);
} }
static int static int
@ -1165,7 +1189,7 @@ long do_sigreturn(CPUX86State *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUX86State *env) long do_rt_sigreturn(CPUX86State *env)
@ -1196,7 +1220,7 @@ long do_rt_sigreturn(CPUX86State *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_AARCH64) #elif defined(TARGET_AARCH64)
@ -1420,7 +1444,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
give_sigsegv: give_sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV); force_sigsegv(usig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -1466,7 +1490,7 @@ long do_rt_sigreturn(CPUARMState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_sigreturn(CPUARMState *env) long do_sigreturn(CPUARMState *env)
@ -1772,7 +1796,7 @@ static void setup_frame_v1(int usig, struct target_sigaction *ka,
trace_user_setup_frame(regs, frame_addr); trace_user_setup_frame(regs, frame_addr);
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
return; goto sigsegv;
} }
setup_sigcontext(&frame->sc, regs, set->sig[0]); setup_sigcontext(&frame->sc, regs, set->sig[0]);
@ -1785,6 +1809,9 @@ static void setup_frame_v1(int usig, struct target_sigaction *ka,
frame_addr + offsetof(struct sigframe_v1, retcode)); frame_addr + offsetof(struct sigframe_v1, retcode));
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
force_sigsegv(usig);
} }
static void setup_frame_v2(int usig, struct target_sigaction *ka, static void setup_frame_v2(int usig, struct target_sigaction *ka,
@ -1795,7 +1822,7 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka,
trace_user_setup_frame(regs, frame_addr); trace_user_setup_frame(regs, frame_addr);
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
return; goto sigsegv;
} }
setup_sigframe_v2(&frame->uc, set, regs); setup_sigframe_v2(&frame->uc, set, regs);
@ -1804,6 +1831,9 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka,
frame_addr + offsetof(struct sigframe_v2, retcode)); frame_addr + offsetof(struct sigframe_v2, retcode));
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
force_sigsegv(usig);
} }
static void setup_frame(int usig, struct target_sigaction *ka, static void setup_frame(int usig, struct target_sigaction *ka,
@ -1829,7 +1859,7 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
trace_user_setup_rt_frame(env, frame_addr); trace_user_setup_rt_frame(env, frame_addr);
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
return /* 1 */; goto sigsegv;
} }
info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info); info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
@ -1859,6 +1889,9 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
env->regs[2] = uc_addr; env->regs[2] = uc_addr;
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
force_sigsegv(usig);
} }
static void setup_rt_frame_v2(int usig, struct target_sigaction *ka, static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
@ -1871,7 +1904,7 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
trace_user_setup_rt_frame(env, frame_addr); trace_user_setup_rt_frame(env, frame_addr);
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
return /* 1 */; goto sigsegv;
} }
info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info); info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
@ -1887,6 +1920,9 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
env->regs[2] = uc_addr; env->regs[2] = uc_addr;
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
force_sigsegv(usig);
} }
static void setup_rt_frame(int usig, struct target_sigaction *ka, static void setup_rt_frame(int usig, struct target_sigaction *ka,
@ -1976,8 +2012,8 @@ static long do_sigreturn_v1(CPUARMState *env)
return -TARGET_QEMU_ESIGRETURN; return -TARGET_QEMU_ESIGRETURN;
badframe: badframe:
force_sig(TARGET_SIGSEGV /* , current */); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace) static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
@ -2035,7 +2071,8 @@ static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
return (abi_ulong*)(iwmmxtframe + 1); return (abi_ulong*)(iwmmxtframe + 1);
} }
static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr, static int do_sigframe_return_v2(CPUARMState *env,
target_ulong context_addr,
struct target_ucontext_v2 *uc) struct target_ucontext_v2 *uc)
{ {
sigset_t host_set; sigset_t host_set;
@ -2062,8 +2099,11 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
} }
} }
if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) if (do_sigaltstack(context_addr
+ offsetof(struct target_ucontext_v2, tuc_stack),
0, get_sp_from_cpustate(env)) == -EFAULT) {
return 1; return 1;
}
#if 0 #if 0
/* Send SIGTRAP if we're single-stepping */ /* Send SIGTRAP if we're single-stepping */
@ -2094,7 +2134,10 @@ static long do_sigreturn_v2(CPUARMState *env)
goto badframe; goto badframe;
} }
if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) { if (do_sigframe_return_v2(env,
frame_addr
+ offsetof(struct sigframe_v2, uc),
&frame->uc)) {
goto badframe; goto badframe;
} }
@ -2103,8 +2146,8 @@ static long do_sigreturn_v2(CPUARMState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV /* , current */); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_sigreturn(CPUARMState *env) long do_sigreturn(CPUARMState *env)
@ -2157,8 +2200,8 @@ static long do_rt_sigreturn_v1(CPUARMState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV /* , current */); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
static long do_rt_sigreturn_v2(CPUARMState *env) static long do_rt_sigreturn_v2(CPUARMState *env)
@ -2181,7 +2224,10 @@ static long do_rt_sigreturn_v2(CPUARMState *env)
goto badframe; goto badframe;
} }
if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) { if (do_sigframe_return_v2(env,
frame_addr
+ offsetof(struct rt_sigframe_v2, uc),
&frame->uc)) {
goto badframe; goto badframe;
} }
@ -2190,8 +2236,8 @@ static long do_rt_sigreturn_v2(CPUARMState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV /* , current */); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUARMState *env) long do_rt_sigreturn(CPUARMState *env)
@ -2445,7 +2491,7 @@ sigill_and_return:
#endif #endif
sigsegv: sigsegv:
unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -2525,6 +2571,7 @@ long do_sigreturn(CPUSPARCState *env)
segv_and_exit: segv_and_exit:
unlock_user_struct(sf, sf_addr, 0); unlock_user_struct(sf, sf_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUSPARCState *env) long do_rt_sigreturn(CPUSPARCState *env)
@ -3037,7 +3084,7 @@ static void setup_frame(int sig, struct target_sigaction * ka,
return; return;
give_sigsegv: give_sigsegv:
force_sig(TARGET_SIGSEGV/*, current*/); force_sigsegv(sig);
} }
long do_sigreturn(CPUMIPSState *regs) long do_sigreturn(CPUMIPSState *regs)
@ -3082,8 +3129,8 @@ long do_sigreturn(CPUMIPSState *regs)
return -TARGET_QEMU_ESIGRETURN; return -TARGET_QEMU_ESIGRETURN;
badframe: badframe:
force_sig(TARGET_SIGSEGV/*, current*/); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
# endif /* O32 */ # endif /* O32 */
@ -3146,7 +3193,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv: give_sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV/*, current*/); force_sigsegv(sig);
} }
long do_rt_sigreturn(CPUMIPSState *env) long do_rt_sigreturn(CPUMIPSState *env)
@ -3179,8 +3226,8 @@ long do_rt_sigreturn(CPUMIPSState *env)
return -TARGET_QEMU_ESIGRETURN; return -TARGET_QEMU_ESIGRETURN;
badframe: badframe:
force_sig(TARGET_SIGSEGV/*, current*/); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_SH4) #elif defined(TARGET_SH4)
@ -3349,7 +3396,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
give_sigsegv: give_sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -3409,7 +3456,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv: give_sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
long do_sigreturn(CPUSH4State *regs) long do_sigreturn(CPUSH4State *regs)
@ -3446,7 +3493,7 @@ long do_sigreturn(CPUSH4State *regs)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUSH4State *regs) long do_rt_sigreturn(CPUSH4State *regs)
@ -3478,7 +3525,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_MICROBLAZE) #elif defined(TARGET_MICROBLAZE)
@ -3656,7 +3703,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
return; return;
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -3697,6 +3744,7 @@ long do_sigreturn(CPUMBState *env)
return -TARGET_QEMU_ESIGRETURN; return -TARGET_QEMU_ESIGRETURN;
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUMBState *env) long do_rt_sigreturn(CPUMBState *env)
@ -3826,7 +3874,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
return; return;
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -3864,6 +3912,7 @@ long do_sigreturn(CPUCRISState *env)
return -TARGET_QEMU_ESIGRETURN; return -TARGET_QEMU_ESIGRETURN;
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUCRISState *env) long do_rt_sigreturn(CPUCRISState *env)
@ -4065,10 +4114,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv: give_sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
if (sig == TARGET_SIGSEGV) { force_sigsegv(sig);
ka->_sa_handler = TARGET_SIG_DFL;
}
force_sig(TARGET_SIGSEGV);
} }
long do_sigreturn(CPUOpenRISCState *env) long do_sigreturn(CPUOpenRISCState *env)
@ -4249,7 +4295,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -4304,7 +4350,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static int static int
@ -4358,7 +4404,7 @@ long do_sigreturn(CPUS390XState *env)
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUS390XState *env) long do_rt_sigreturn(CPUS390XState *env)
@ -4389,7 +4435,7 @@ long do_rt_sigreturn(CPUS390XState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_PPC) #elif defined(TARGET_PPC)
@ -4815,7 +4861,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
sigsegv: sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static void setup_rt_frame(int sig, struct target_sigaction *ka, static void setup_rt_frame(int sig, struct target_sigaction *ka,
@ -4910,7 +4956,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
sigsegv: sigsegv:
unlock_user_struct(rt_sf, rt_sf_addr, 1); unlock_user_struct(rt_sf, rt_sf_addr, 1);
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
@ -4948,7 +4994,7 @@ sigsegv:
unlock_user_struct(sr, sr_addr, 1); unlock_user_struct(sr, sr_addr, 1);
unlock_user_struct(sc, sc_addr, 1); unlock_user_struct(sc, sc_addr, 1);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
/* See arch/powerpc/kernel/signal_32.c. */ /* See arch/powerpc/kernel/signal_32.c. */
@ -5003,7 +5049,7 @@ long do_rt_sigreturn(CPUPPCState *env)
sigsegv: sigsegv:
unlock_user_struct(rt_sf, rt_sf_addr, 1); unlock_user_struct(rt_sf, rt_sf_addr, 1);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_M68K) #elif defined(TARGET_M68K)
@ -5159,7 +5205,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
static inline int target_rt_setup_ucontext(struct target_ucontext *uc, static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
@ -5298,7 +5344,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv: give_sigsegv:
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV); force_sigsegv(sig);
} }
long do_sigreturn(CPUM68KState *env) long do_sigreturn(CPUM68KState *env)
@ -5333,7 +5379,7 @@ long do_sigreturn(CPUM68KState *env)
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUM68KState *env) long do_rt_sigreturn(CPUM68KState *env)
@ -5366,7 +5412,7 @@ long do_rt_sigreturn(CPUM68KState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return 0; return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_ALPHA) #elif defined(TARGET_ALPHA)
@ -5505,10 +5551,8 @@ static void setup_frame(int sig, struct target_sigaction *ka,
if (err) { if (err) {
give_sigsegv: give_sigsegv:
if (sig == TARGET_SIGSEGV) { force_sigsegv(sig);
ka->_sa_handler = TARGET_SIG_DFL; return;
}
force_sig(TARGET_SIGSEGV);
} }
env->ir[IR_RA] = r26; env->ir[IR_RA] = r26;
@ -5562,10 +5606,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
if (err) { if (err) {
give_sigsegv: give_sigsegv:
if (sig == TARGET_SIGSEGV) { force_sigsegv(sig);
ka->_sa_handler = TARGET_SIG_DFL; return;
}
force_sig(TARGET_SIGSEGV);
} }
env->ir[IR_RA] = r26; env->ir[IR_RA] = r26;
@ -5599,6 +5641,7 @@ long do_sigreturn(CPUAlphaState *env)
badframe: badframe:
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
} }
long do_rt_sigreturn(CPUAlphaState *env) long do_rt_sigreturn(CPUAlphaState *env)
@ -5628,6 +5671,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
} }
#elif defined(TARGET_TILEGX) #elif defined(TARGET_TILEGX)
@ -5762,10 +5806,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return; return;
give_sigsegv: give_sigsegv:
if (sig == TARGET_SIGSEGV) { force_sigsegv(sig);
ka->_sa_handler = TARGET_SIG_DFL;
}
force_sig(TARGET_SIGSEGV /* , current */);
} }
long do_rt_sigreturn(CPUTLGState *env) long do_rt_sigreturn(CPUTLGState *env)
@ -5795,6 +5836,7 @@ long do_rt_sigreturn(CPUTLGState *env)
badframe: badframe:
unlock_user_struct(frame, frame_addr, 0); unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
} }
#else #else
@ -5849,6 +5891,10 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
handler = sa->_sa_handler; handler = sa->_sa_handler;
} }
if (do_strace) {
print_taken_signal(sig, &k->info);
}
if (handler == TARGET_SIG_DFL) { if (handler == TARGET_SIG_DFL) {
/* default handler : ignore some signal. The other are job control or fatal */ /* default handler : ignore some signal. The other are job control or fatal */
if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
@ -5857,12 +5903,12 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
sig != TARGET_SIGURG && sig != TARGET_SIGURG &&
sig != TARGET_SIGWINCH && sig != TARGET_SIGWINCH &&
sig != TARGET_SIGCONT) { sig != TARGET_SIGCONT) {
force_sig(sig); dump_core_and_abort(sig);
} }
} else if (handler == TARGET_SIG_IGN) { } else if (handler == TARGET_SIG_IGN) {
/* ignore sig */ /* ignore sig */
} else if (handler == TARGET_SIG_ERR) { } else if (handler == TARGET_SIG_ERR) {
force_sig(sig); dump_core_and_abort(sig);
} else { } else {
/* compute the blocked signals during the handler execution */ /* compute the blocked signals during the handler execution */
sigset_t *blocked_set; sigset_t *blocked_set;
@ -5921,6 +5967,7 @@ void process_pending_signals(CPUArchState *cpu_env)
sigfillset(&set); sigfillset(&set);
sigprocmask(SIG_SETMASK, &set, 0); sigprocmask(SIG_SETMASK, &set, 0);
restart_scan:
sig = ts->sync_signal.pending; sig = ts->sync_signal.pending;
if (sig) { if (sig) {
/* Synchronous signals are forced, /* Synchronous signals are forced,
@ -5948,8 +5995,10 @@ void process_pending_signals(CPUArchState *cpu_env)
(!sigismember(blocked_set, (!sigismember(blocked_set,
target_to_host_signal_table[sig]))) { target_to_host_signal_table[sig]))) {
handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]); handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
/* Restart scan from the beginning */ /* Restart scan from the beginning, as handle_pending_signal
sig = 1; * might have resulted in a new synchronous signal (eg SIGSEGV).
*/
goto restart_scan;
} }
} }

View File

@ -22,4 +22,20 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 #define TARGET_MLOCKALL_MCL_FUTURE 0x4000
/* For SPARC SHMLBA is determined at runtime in the kernel, and
* libc has to runtime-detect it using the hwcaps (see glibc
* sysdeps/unix/sysv/linux/sparc/getshmlba; we follow the same
* logic here, though we know we're not the sparc v9 64-bit case).
*/
#define TARGET_FORCE_SHMLBA
static inline abi_ulong target_shmlba(CPUSPARCState *env)
{
if (!(env->def->features & CPU_FEATURE_FLUSH)) {
return 64 * 1024;
} else {
return 256 * 1024;
}
}
#endif /* SPARC_TARGET_SYSCALL_H */ #endif /* SPARC_TARGET_SYSCALL_H */

View File

@ -154,6 +154,100 @@ print_signal(abi_ulong arg, int last)
gemu_log("%s%s", signal_name, get_comma(last)); gemu_log("%s%s", signal_name, get_comma(last));
} }
static void print_si_code(int arg)
{
const char *codename = NULL;
switch (arg) {
case SI_USER:
codename = "SI_USER";
break;
case SI_KERNEL:
codename = "SI_KERNEL";
break;
case SI_QUEUE:
codename = "SI_QUEUE";
break;
case SI_TIMER:
codename = "SI_TIMER";
break;
case SI_MESGQ:
codename = "SI_MESGQ";
break;
case SI_ASYNCIO:
codename = "SI_ASYNCIO";
break;
case SI_SIGIO:
codename = "SI_SIGIO";
break;
case SI_TKILL:
codename = "SI_TKILL";
break;
default:
gemu_log("%d", arg);
return;
}
gemu_log("%s", codename);
}
static void print_siginfo(const target_siginfo_t *tinfo)
{
/* Print a target_siginfo_t in the format desired for printing
* signals being taken. We assume the target_siginfo_t is in the
* internal form where the top 16 bits of si_code indicate which
* part of the union is valid, rather than in the guest-visible
* form where the bottom 16 bits are sign-extended into the top 16.
*/
int si_type = extract32(tinfo->si_code, 16, 16);
int si_code = sextract32(tinfo->si_code, 0, 16);
gemu_log("{si_signo=");
print_signal(tinfo->si_signo, 1);
gemu_log(", si_code=");
print_si_code(si_code);
switch (si_type) {
case QEMU_SI_KILL:
gemu_log(", si_pid = %u, si_uid = %u",
(unsigned int)tinfo->_sifields._kill._pid,
(unsigned int)tinfo->_sifields._kill._uid);
break;
case QEMU_SI_TIMER:
gemu_log(", si_timer1 = %u, si_timer2 = %u",
tinfo->_sifields._timer._timer1,
tinfo->_sifields._timer._timer2);
break;
case QEMU_SI_POLL:
gemu_log(", si_band = %d, si_fd = %d",
tinfo->_sifields._sigpoll._band,
tinfo->_sifields._sigpoll._fd);
break;
case QEMU_SI_FAULT:
gemu_log(", si_addr = ");
print_pointer(tinfo->_sifields._sigfault._addr, 1);
break;
case QEMU_SI_CHLD:
gemu_log(", si_pid = %u, si_uid = %u, si_status = %d"
", si_utime=" TARGET_ABI_FMT_ld
", si_stime=" TARGET_ABI_FMT_ld,
(unsigned int)(tinfo->_sifields._sigchld._pid),
(unsigned int)(tinfo->_sifields._sigchld._uid),
tinfo->_sifields._sigchld._status,
tinfo->_sifields._sigchld._utime,
tinfo->_sifields._sigchld._stime);
break;
case QEMU_SI_RT:
gemu_log(", si_pid = %u, si_uid = %u, si_sigval = " TARGET_ABI_FMT_ld,
(unsigned int)tinfo->_sifields._rt._pid,
(unsigned int)tinfo->_sifields._rt._uid,
tinfo->_sifields._rt._sigval.sival_ptr);
break;
default:
g_assert_not_reached();
}
gemu_log("}");
}
static void static void
print_sockaddr(abi_ulong addr, abi_long addrlen) print_sockaddr(abi_ulong addr, abi_long addrlen)
{ {
@ -2190,3 +2284,15 @@ print_syscall_ret(int num, abi_long ret)
break; break;
} }
} }
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
{
/* Print the strace output for a signal being taken:
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
*/
gemu_log("--- ");
print_signal(target_signum, 1);
gemu_log(" ");
print_siginfo(tinfo);
gemu_log(" ---\n");
}

View File

@ -112,8 +112,56 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include "qemu.h" #include "qemu.h"
#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ #ifndef CLONE_IO
CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) #define CLONE_IO 0x80000000 /* Clone io context */
#endif
/* We can't directly call the host clone syscall, because this will
* badly confuse libc (breaking mutexes, for example). So we must
* divide clone flags into:
* * flag combinations that look like pthread_create()
* * flag combinations that look like fork()
* * flags we can implement within QEMU itself
* * flags we can't support and will return an error for
*/
/* For thread creation, all these flags must be present; for
* fork, none must be present.
*/
#define CLONE_THREAD_FLAGS \
(CLONE_VM | CLONE_FS | CLONE_FILES | \
CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
/* These flags are ignored:
* CLONE_DETACHED is now ignored by the kernel;
* CLONE_IO is just an optimisation hint to the I/O scheduler
*/
#define CLONE_IGNORED_FLAGS \
(CLONE_DETACHED | CLONE_IO)
/* Flags for fork which we can implement within QEMU itself */
#define CLONE_OPTIONAL_FORK_FLAGS \
(CLONE_SETTLS | CLONE_PARENT_SETTID | \
CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
/* Flags for thread creation which we can implement within QEMU itself */
#define CLONE_OPTIONAL_THREAD_FLAGS \
(CLONE_SETTLS | CLONE_PARENT_SETTID | \
CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
#define CLONE_INVALID_FORK_FLAGS \
(~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
#define CLONE_INVALID_THREAD_FLAGS \
(~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
CLONE_IGNORED_FLAGS))
/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
* have almost all been allocated. We cannot support any of
* CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
* CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
* The checks against the invalid thread masks above will catch these.
* (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
*/
//#define DEBUG //#define DEBUG
/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted /* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
@ -520,16 +568,7 @@ static int sys_getcwd1(char *buf, size_t size)
} }
#ifdef TARGET_NR_utimensat #ifdef TARGET_NR_utimensat
#ifdef CONFIG_UTIMENSAT #if defined(__NR_utimensat)
static int sys_utimensat(int dirfd, const char *pathname,
const struct timespec times[2], int flags)
{
if (pathname == NULL)
return futimens(dirfd, times);
else
return utimensat(dirfd, pathname, times, flags);
}
#elif defined(__NR_utimensat)
#define __NR_sys_utimensat __NR_utimensat #define __NR_sys_utimensat __NR_utimensat
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
const struct timespec *,tsp,int,flags) const struct timespec *,tsp,int,flags)
@ -1405,6 +1444,29 @@ static abi_long do_select(int n,
return ret; return ret;
} }
#if defined(TARGET_WANT_OLD_SYS_SELECT)
static abi_long do_old_select(abi_ulong arg1)
{
struct target_sel_arg_struct *sel;
abi_ulong inp, outp, exp, tvp;
long nsel;
if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
return -TARGET_EFAULT;
}
nsel = tswapal(sel->n);
inp = tswapal(sel->inp);
outp = tswapal(sel->outp);
exp = tswapal(sel->exp);
tvp = tswapal(sel->tvp);
unlock_user_struct(sel, arg1, 0);
return do_select(nsel, inp, outp, exp, tvp);
}
#endif
#endif #endif
static abi_long do_pipe2(int host_pipe[], int flags) static abi_long do_pipe2(int host_pipe[], int flags)
@ -3119,7 +3181,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
} }
static struct iovec *lock_iovec(int type, abi_ulong target_addr, static struct iovec *lock_iovec(int type, abi_ulong target_addr,
int count, int copy) abi_ulong count, int copy)
{ {
struct target_iovec *target_vec; struct target_iovec *target_vec;
struct iovec *vec; struct iovec *vec;
@ -3132,7 +3194,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
errno = 0; errno = 0;
return NULL; return NULL;
} }
if (count < 0 || count > IOV_MAX) { if (count > IOV_MAX) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
@ -3207,7 +3269,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
} }
static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
int count, int copy) abi_ulong count, int copy)
{ {
struct target_iovec *target_vec; struct target_iovec *target_vec;
int i; int i;
@ -3462,7 +3524,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
{ {
abi_long ret, len; abi_long ret, len;
struct msghdr msg; struct msghdr msg;
int count; abi_ulong count;
struct iovec *vec; struct iovec *vec;
abi_ulong target_vec; abi_ulong target_vec;
@ -3472,7 +3534,14 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
ret = target_to_host_sockaddr(fd, msg.msg_name, ret = target_to_host_sockaddr(fd, msg.msg_name,
tswapal(msgp->msg_name), tswapal(msgp->msg_name),
msg.msg_namelen); msg.msg_namelen);
if (ret) { if (ret == -TARGET_EFAULT) {
/* For connected sockets msg_name and msg_namelen must
* be ignored, so returning EFAULT immediately is wrong.
* Instead, pass a bad msg_name to the host kernel, and
* let it decide whether to return EFAULT or not.
*/
msg.msg_name = (void *)-1;
} else if (ret) {
goto out2; goto out2;
} }
} else { } else {
@ -3485,6 +3554,15 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
count = tswapal(msgp->msg_iovlen); count = tswapal(msgp->msg_iovlen);
target_vec = tswapal(msgp->msg_iov); target_vec = tswapal(msgp->msg_iov);
if (count > IOV_MAX) {
/* sendrcvmsg returns a different errno for this condition than
* readv/writev, so we must catch it here before lock_iovec() does.
*/
ret = -TARGET_EMSGSIZE;
goto out2;
}
vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
target_vec, count, send); target_vec, count, send);
if (vec == NULL) { if (vec == NULL) {
@ -3525,7 +3603,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
} }
if (!is_error(ret)) { if (!is_error(ret)) {
msgp->msg_namelen = tswap32(msg.msg_namelen); msgp->msg_namelen = tswap32(msg.msg_namelen);
if (msg.msg_name != NULL) { if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
ret = host_to_target_sockaddr(tswapal(msgp->msg_name), ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
msg.msg_name, msg.msg_namelen); msg.msg_name, msg.msg_namelen);
if (ret) { if (ret) {
@ -4568,12 +4646,34 @@ static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
return ret; return ret;
} }
static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg) #ifndef TARGET_FORCE_SHMLBA
/* For most architectures, SHMLBA is the same as the page size;
* some architectures have larger values, in which case they should
* define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
* This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
* and defining its own value for SHMLBA.
*
* The kernel also permits SHMLBA to be set by the architecture to a
* value larger than the page size without setting __ARCH_FORCE_SHMLBA;
* this means that addresses are rounded to the large size if
* SHM_RND is set but addresses not aligned to that size are not rejected
* as long as they are at least page-aligned. Since the only architecture
* which uses this is ia64 this code doesn't provide for that oddity.
*/
static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
{
return TARGET_PAGE_SIZE;
}
#endif
static inline abi_ulong do_shmat(CPUArchState *cpu_env,
int shmid, abi_ulong shmaddr, int shmflg)
{ {
abi_long raddr; abi_long raddr;
void *host_raddr; void *host_raddr;
struct shmid_ds shm_info; struct shmid_ds shm_info;
int i,ret; int i,ret;
abi_ulong shmlba;
/* find out the length of the shared memory segment */ /* find out the length of the shared memory segment */
ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
@ -4582,6 +4682,16 @@ static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
return ret; return ret;
} }
shmlba = target_shmlba(cpu_env);
if (shmaddr & (shmlba - 1)) {
if (shmflg & SHM_RND) {
shmaddr &= ~(shmlba - 1);
} else {
return -TARGET_EINVAL;
}
}
mmap_lock(); mmap_lock();
if (shmaddr) if (shmaddr)
@ -4640,7 +4750,8 @@ static inline abi_long do_shmdt(abi_ulong shmaddr)
#ifdef TARGET_NR_ipc #ifdef TARGET_NR_ipc
/* ??? This only works with linear mappings. */ /* ??? This only works with linear mappings. */
/* do_ipc() must return target values and target errnos. */ /* do_ipc() must return target values and target errnos. */
static abi_long do_ipc(unsigned int call, abi_long first, static abi_long do_ipc(CPUArchState *cpu_env,
unsigned int call, abi_long first,
abi_long second, abi_long third, abi_long second, abi_long third,
abi_long ptr, abi_long fifth) abi_long ptr, abi_long fifth)
{ {
@ -4709,7 +4820,7 @@ static abi_long do_ipc(unsigned int call, abi_long first,
default: default:
{ {
abi_ulong raddr; abi_ulong raddr;
raddr = do_shmat(first, ptr, second); raddr = do_shmat(cpu_env, first, ptr, second);
if (is_error(raddr)) if (is_error(raddr))
return get_errno(raddr); return get_errno(raddr);
if (put_user_ual(raddr, third)) if (put_user_ual(raddr, third))
@ -4994,13 +5105,18 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
guest_data = arg + host_dm->data_start; guest_data = arg + host_dm->data_start;
if ((guest_data - arg) < 0) { if ((guest_data - arg) < 0) {
ret = -EINVAL; ret = -TARGET_EINVAL;
goto out; goto out;
} }
guest_data_size = host_dm->data_size - host_dm->data_start; guest_data_size = host_dm->data_size - host_dm->data_start;
host_data = (char*)host_dm + host_dm->data_start; host_data = (char*)host_dm + host_dm->data_start;
argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1); argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
if (!argptr) {
ret = -TARGET_EFAULT;
goto out;
}
switch (ie->host_cmd) { switch (ie->host_cmd) {
case DM_REMOVE_ALL: case DM_REMOVE_ALL:
case DM_LIST_DEVICES: case DM_LIST_DEVICES:
@ -5966,9 +6082,10 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
TaskState *ts; TaskState *ts;
CPUState *new_cpu; CPUState *new_cpu;
CPUArchState *new_env; CPUArchState *new_env;
unsigned int nptl_flags;
sigset_t sigmask; sigset_t sigmask;
flags &= ~CLONE_IGNORED_FLAGS;
/* Emulate vfork() with fork() */ /* Emulate vfork() with fork() */
if (flags & CLONE_VFORK) if (flags & CLONE_VFORK)
flags &= ~(CLONE_VFORK | CLONE_VM); flags &= ~(CLONE_VFORK | CLONE_VM);
@ -5978,6 +6095,11 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
new_thread_info info; new_thread_info info;
pthread_attr_t attr; pthread_attr_t attr;
if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
(flags & CLONE_INVALID_THREAD_FLAGS)) {
return -TARGET_EINVAL;
}
ts = g_new0(TaskState, 1); ts = g_new0(TaskState, 1);
init_task_state(ts); init_task_state(ts);
/* we create a new CPU instance. */ /* we create a new CPU instance. */
@ -5989,15 +6111,14 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
ts->bprm = parent_ts->bprm; ts->bprm = parent_ts->bprm;
ts->info = parent_ts->info; ts->info = parent_ts->info;
ts->signal_mask = parent_ts->signal_mask; ts->signal_mask = parent_ts->signal_mask;
nptl_flags = flags;
flags &= ~CLONE_NPTL_FLAGS2;
if (nptl_flags & CLONE_CHILD_CLEARTID) { if (flags & CLONE_CHILD_CLEARTID) {
ts->child_tidptr = child_tidptr; ts->child_tidptr = child_tidptr;
} }
if (nptl_flags & CLONE_SETTLS) if (flags & CLONE_SETTLS) {
cpu_set_tls (new_env, newtls); cpu_set_tls (new_env, newtls);
}
/* Grab a mutex so that thread setup appears atomic. */ /* Grab a mutex so that thread setup appears atomic. */
pthread_mutex_lock(&clone_lock); pthread_mutex_lock(&clone_lock);
@ -6007,10 +6128,12 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pthread_mutex_lock(&info.mutex); pthread_mutex_lock(&info.mutex);
pthread_cond_init(&info.cond, NULL); pthread_cond_init(&info.cond, NULL);
info.env = new_env; info.env = new_env;
if (nptl_flags & CLONE_CHILD_SETTID) if (flags & CLONE_CHILD_SETTID) {
info.child_tidptr = child_tidptr; info.child_tidptr = child_tidptr;
if (nptl_flags & CLONE_PARENT_SETTID) }
if (flags & CLONE_PARENT_SETTID) {
info.parent_tidptr = parent_tidptr; info.parent_tidptr = parent_tidptr;
}
ret = pthread_attr_init(&attr); ret = pthread_attr_init(&attr);
ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE); ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
@ -6029,8 +6152,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
/* Wait for the child to initialize. */ /* Wait for the child to initialize. */
pthread_cond_wait(&info.cond, &info.mutex); pthread_cond_wait(&info.cond, &info.mutex);
ret = info.tid; ret = info.tid;
if (flags & CLONE_PARENT_SETTID)
put_user_u32(ret, parent_tidptr);
} else { } else {
ret = -1; ret = -1;
} }
@ -6040,7 +6161,12 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pthread_mutex_unlock(&clone_lock); pthread_mutex_unlock(&clone_lock);
} else { } else {
/* if no CLONE_VM, we consider it is a fork */ /* if no CLONE_VM, we consider it is a fork */
if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) { if (flags & CLONE_INVALID_FORK_FLAGS) {
return -TARGET_EINVAL;
}
/* We can't support custom termination signals */
if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
return -TARGET_EINVAL; return -TARGET_EINVAL;
} }
@ -8565,24 +8691,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break; break;
#if defined(TARGET_NR_select) #if defined(TARGET_NR_select)
case TARGET_NR_select: case TARGET_NR_select:
#if defined(TARGET_S390X) || defined(TARGET_ALPHA) #if defined(TARGET_WANT_NI_OLD_SELECT)
ret = do_select(arg1, arg2, arg3, arg4, arg5); /* some architectures used to have old_select here
* but now ENOSYS it.
*/
ret = -TARGET_ENOSYS;
#elif defined(TARGET_WANT_OLD_SYS_SELECT)
ret = do_old_select(arg1);
#else #else
{ ret = do_select(arg1, arg2, arg3, arg4, arg5);
struct target_sel_arg_struct *sel;
abi_ulong inp, outp, exp, tvp;
long nsel;
if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
goto efault;
nsel = tswapal(sel->n);
inp = tswapal(sel->inp);
outp = tswapal(sel->outp);
exp = tswapal(sel->exp);
tvp = tswapal(sel->tvp);
unlock_user_struct(sel, arg1, 0);
ret = do_select(nsel, inp, outp, exp, tvp);
}
#endif #endif
break; break;
#endif #endif
@ -9292,8 +9409,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break; break;
#ifdef TARGET_NR_ipc #ifdef TARGET_NR_ipc
case TARGET_NR_ipc: case TARGET_NR_ipc:
ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); ret = do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
break; break;
#endif #endif
#ifdef TARGET_NR_semget #ifdef TARGET_NR_semget
case TARGET_NR_semget: case TARGET_NR_semget:
@ -9342,7 +9459,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif #endif
#ifdef TARGET_NR_shmat #ifdef TARGET_NR_shmat
case TARGET_NR_shmat: case TARGET_NR_shmat:
ret = do_shmat(arg1, arg2, arg3); ret = do_shmat(cpu_env, arg1, arg2, arg3);
break; break;
#endif #endif
#ifdef TARGET_NR_shmdt #ifdef TARGET_NR_shmdt
@ -9654,6 +9771,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
pfd = NULL; pfd = NULL;
target_pfd = NULL; target_pfd = NULL;
if (nfds) { if (nfds) {
if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
ret = -TARGET_EINVAL;
break;
}
target_pfd = lock_user(VERIFY_WRITE, arg1, target_pfd = lock_user(VERIFY_WRITE, arg1,
sizeof(struct target_pollfd) * nfds, 1); sizeof(struct target_pollfd) * nfds, 1);
if (!target_pfd) { if (!target_pfd) {
@ -10527,7 +10649,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
info.si_code = si_code; info.si_code = si_code;
info._sifields._sigfault._addr info._sifields._sigfault._addr
= ((CPUArchState *)cpu_env)->pc; = ((CPUArchState *)cpu_env)->pc;
queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); queue_signal((CPUArchState *)cpu_env, info.si_signo,
QEMU_SI_FAULT, &info);
} }
} }
break; break;
@ -11259,6 +11382,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_mq_unlink: case TARGET_NR_mq_unlink:
p = lock_user_string(arg1 - 1); p = lock_user_string(arg1 - 1);
if (!p) {
ret = -TARGET_EFAULT;
break;
}
ret = get_errno(mq_unlink(p)); ret = get_errno(mq_unlink(p));
unlock_user (p, arg1, 0); unlock_user (p, arg1, 0);
break; break;
@ -11494,6 +11621,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int maxevents = arg3; int maxevents = arg3;
int timeout = arg4; int timeout = arg4;
if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
ret = -TARGET_EINVAL;
break;
}
target_ep = lock_user(VERIFY_WRITE, arg2, target_ep = lock_user(VERIFY_WRITE, arg2,
maxevents * sizeof(struct target_epoll_event), 1); maxevents * sizeof(struct target_epoll_event), 1);
if (!target_ep) { if (!target_ep) {
@ -11606,7 +11738,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
info.si_errno = 0; info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR; info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = arg6; info._sifields._sigfault._addr = arg6;
queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); queue_signal((CPUArchState *)cpu_env, info.si_signo,
QEMU_SI_FAULT, &info);
ret = 0xdeadbeef; ret = 0xdeadbeef;
} }

View File

@ -998,6 +998,12 @@ struct target_pollfd {
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */ #define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */ #define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
/* Note that the ioctl numbers claim type "long" but the actual type
* used by the kernel is "int".
*/
#define TARGET_FS_IOC_GETFLAGS TARGET_IOR('f', 1, long)
#define TARGET_FS_IOC_SETFLAGS TARGET_IOW('f', 2, long)
#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap) #define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
/* cdrom commands */ /* cdrom commands */
@ -2579,6 +2585,9 @@ struct target_epoll_event {
abi_uint events; abi_uint events;
target_epoll_data_t data; target_epoll_data_t data;
} TARGET_EPOLL_PACKED; } TARGET_EPOLL_PACKED;
#define TARGET_EP_MAX_EVENTS (INT_MAX / sizeof(struct target_epoll_event))
#endif #endif
struct target_rlimit64 { struct target_rlimit64 {
uint64_t rlim_cur; uint64_t rlim_cur;

View File

@ -311,7 +311,6 @@
#define TARGET_NR_creat 1064 #define TARGET_NR_creat 1064
#define TARGET_NR_getdents 1065 #define TARGET_NR_getdents 1065
#define TARGET_NR_futimesat 1066 #define TARGET_NR_futimesat 1066
#define TARGET_NR_select 1067
#define TARGET_NR_poll 1068 #define TARGET_NR_poll 1068
#define TARGET_NR_epoll_wait 1069 #define TARGET_NR_epoll_wait 1069
#define TARGET_NR_ustat 1070 #define TARGET_NR_ustat 1070