Merge tag 'linux-user-for-7.1-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging

Pull request linux-user 20220525

s390x fixes
CPUArchState cleanup
elfload cleanup
fix for uclibc-ng and by musl

# -----BEGIN PGP SIGNATURE-----
#
# iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmKOB6ISHGxhdXJlbnRA
# dml2aWVyLmV1AAoJEPMMOL0/L748UooP/38pbx20Zz1ZJcT5jkfJNOScg2mlHmeJ
# 2pr+8HRXyGXjkFsqNLKPSDB5/bEa9reCBIuVFR3kLxFdERE8G8PQqAH7tp8Sd3LT
# HFEGQ3nK6DGRNRnLQqpzSyG6ZpktpJrHmXpdh3HxGM2r/gPnWV/XKM87YvG+kOKe
# XU75Yx9F8VMYUjbDoAYuUOPOPvvrnTpLnFOedss6WXOJJFJvE7jzPMx4mwiYlXIj
# IrjHAd+rK3yUXziqM4gqZjrNvRw7+UhaNv1gDJGHFw+aSRrrDSl5OiNHZstAcRUD
# Kx4TVMCm2m8vYxtX2QKBz6DSonOVe0/w6aRKiqZmDfxPfxPvtjtfnREZGqyb211T
# 3uMbtWI/kkqL9Fw1nNVJyzdKCqf0YSDzmfWdgqhYq568IX1DUZgIMgDMPfBo3N5N
# euH4UVaFwy+s/pq5lW2EIZm6TAKllpseMyDPUrva8Wis9hAEV4CTMq6Z8XlnzxSd
# Jwwizxt0pItpmiPPGr4eGSM9uY1aFKgqiMFyCZATTrmHe4AQrssEV2cH5Wg6veaY
# cE7VaA5grwUlToYSQaRNRjqTqW64uDxhz8wTfsAe9hRT2dNFJdHibtBrOeepl35R
# 5cWQzHas3pTUx9D/gzUtkstoWIKlDSppxpIHcFKxcEKOLreUFEwYVLJuA9+IgLVl
# /vcZHcEAjz/k
# =B9Rm
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 25 May 2022 03:40:34 AM PDT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [undefined]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [undefined]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* tag 'linux-user-for-7.1-pull-request' of https://gitlab.com/laurent_vivier/qemu:
  linux-user/host/s390: Treat EX and EXRL as writes
  tests/tcg/s390x: Test unwinding from signal handlers
  linux-user/s390x: Fix unwinding from signal handlers
  linux-user: Remove pointless CPU{ARCH}State casts
  linux-user: Have do_syscall() use CPUArchState* instead of void*
  linux-user/elfload: Remove pointless non-const CPUArchState cast
  linux-user/syscall.c: fix build without RLIMIT_RTTIME
  linux-user: Clean up arg_start/arg_end confusion

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2022-05-25 09:32:38 -07:00
14 changed files with 252 additions and 186 deletions
+7 -5
View File
@@ -1516,8 +1516,8 @@ static inline void init_thread(struct target_pt_regs *regs,
regs->iaoq[0] = infop->entry;
regs->iaoq[1] = infop->entry + 4;
regs->gr[23] = 0;
regs->gr[24] = infop->arg_start;
regs->gr[25] = (infop->arg_end - infop->arg_start) / sizeof(abi_ulong);
regs->gr[24] = infop->argv;
regs->gr[25] = infop->argc;
/* The top-of-stack contains a linkage buffer. */
regs->gr[30] = infop->start_stack + 64;
regs->gr[31] = infop->entry;
@@ -2120,8 +2120,10 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
u_envp = u_argv + (argc + 1) * n;
u_auxv = u_envp + (envc + 1) * n;
info->saved_auxv = u_auxv;
info->arg_start = u_argv;
info->arg_end = u_argv + argc * n;
info->argc = argc;
info->envc = envc;
info->argv = u_argv;
info->envp = u_envp;
/* This is correct because Linux defines
* elf_addr_t as Elf32_Off / Elf64_Off
@@ -3971,7 +3973,7 @@ static int fill_note_info(struct elf_note_info *info,
if (cpu == thread_cpu) {
continue;
}
fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
fill_thread_info(info, cpu->env_ptr);
}
cpu_list_unlock();
@@ -50,6 +50,7 @@ static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
case 0x50: /* ST */
case 0x42: /* STC */
case 0x40: /* STH */
case 0x44: /* EX */
case 0xba: /* CS */
case 0xbb: /* CDS */
return true;
@@ -61,6 +62,12 @@ static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
return true;
}
break;
case 0xc6: /* RIL-b format insns */
switch (pinsn[0] & 0xf) {
case 0x0: /* EXRL */
return true;
}
break;
case 0xc8: /* SSF format insns */
switch (pinsn[0] & 0xf) {
case 0x2: /* CSST */
+10 -2
View File
@@ -92,6 +92,11 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
envp = sp;
sp -= (argc + 1) * n;
argv = sp;
ts->info->envp = envp;
ts->info->envc = envc;
ts->info->argv = argv;
ts->info->argc = argc;
if (push_ptr) {
/* FIXME - handle put_user() failures */
sp -= n;
@@ -99,19 +104,22 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
sp -= n;
put_user_ual(argv, sp);
}
sp -= n;
/* FIXME - handle put_user() failures */
put_user_ual(argc, sp);
ts->info->arg_start = stringp;
ts->info->arg_strings = stringp;
while (argc-- > 0) {
/* FIXME - handle put_user() failures */
put_user_ual(stringp, argv);
argv += n;
stringp += target_strlen(stringp) + 1;
}
ts->info->arg_end = stringp;
/* FIXME - handle put_user() failures */
put_user_ual(0, argv);
ts->info->env_strings = stringp;
while (envc-- > 0) {
/* FIXME - handle put_user() failures */
put_user_ual(stringp, envp);
+2 -2
View File
@@ -878,9 +878,9 @@ int main(int argc, char **argv, char **envp)
fprintf(f, "entry 0x" TARGET_ABI_FMT_lx "\n",
info->entry);
fprintf(f, "argv_start 0x" TARGET_ABI_FMT_lx "\n",
info->arg_start);
info->argv);
fprintf(f, "env_start 0x" TARGET_ABI_FMT_lx "\n",
info->arg_end + (abi_ulong)sizeof(abi_ulong));
info->envp);
fprintf(f, "auxv_start 0x" TARGET_ABI_FMT_lx "\n",
info->saved_auxv);
qemu_log_unlock(f);
+8 -4
View File
@@ -40,15 +40,19 @@ struct image_info {
abi_ulong data_offset;
abi_ulong saved_auxv;
abi_ulong auxv_len;
abi_ulong arg_start;
abi_ulong arg_end;
abi_ulong arg_strings;
abi_ulong env_strings;
abi_ulong argc;
abi_ulong argv;
abi_ulong envc;
abi_ulong envp;
abi_ulong file_string;
uint32_t elf_flags;
int personality;
abi_ulong alignment;
/* Generic semihosting knows about these pointers. */
abi_ulong arg_strings; /* strings for argv */
abi_ulong env_strings; /* strings for envp; ends arg_strings */
/* The fields below are used in FDPIC mode. */
abi_ulong loadmap_addr;
uint16_t nsegs;
+5
View File
@@ -84,6 +84,11 @@ struct target_ucontext {
typedef struct {
uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
/*
* This field is no longer initialized by the kernel, but it's still a part
* of the ABI.
*/
uint16_t svc_insn;
struct target_siginfo info;
struct target_ucontext uc;
} rt_sigframe;
+101 -101
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -18,10 +18,10 @@
#ifndef LINUX_USER_STRACE_H
#define LINUX_USER_STRACE_H
void print_syscall(void *cpu_env, int num,
void print_syscall(CPUArchState *cpu_env, int num,
abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6);
void print_syscall_ret(void *cpu_env, int num, abi_long ret,
void print_syscall_ret(CPUArchState *cpu_env, int num, abi_long ret,
abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6);
/**
+41 -42
View File
@@ -1053,8 +1053,10 @@ static inline int target_to_host_resource(int code)
return RLIMIT_RSS;
case TARGET_RLIMIT_RTPRIO:
return RLIMIT_RTPRIO;
#ifdef RLIMIT_RTTIME
case TARGET_RLIMIT_RTTIME:
return RLIMIT_RTTIME;
#endif
case TARGET_RLIMIT_SIGPENDING:
return RLIMIT_SIGPENDING;
case TARGET_RLIMIT_STACK:
@@ -1596,7 +1598,7 @@ static abi_long do_pipe2(int host_pipe[], int flags)
#endif
}
static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
int flags, int is_pipe2)
{
int host_pipe[2];
@@ -1610,16 +1612,16 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
pipe syscall, but didn't replicate this into the pipe2 syscall. */
if (!is_pipe2) {
#if defined(TARGET_ALPHA)
((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
cpu_env->ir[IR_A4] = host_pipe[1];
return host_pipe[0];
#elif defined(TARGET_MIPS)
((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
cpu_env->active_tc.gpr[3] = host_pipe[1];
return host_pipe[0];
#elif defined(TARGET_SH4)
((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
cpu_env->gregs[1] = host_pipe[1];
return host_pipe[0];
#elif defined(TARGET_SPARC)
((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
cpu_env->regwptr[1] = host_pipe[1];
return host_pipe[0];
#endif
}
@@ -7250,7 +7252,7 @@ void syscall_init(void)
}
#ifdef TARGET_NR_truncate64
static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
abi_long arg2,
abi_long arg3,
abi_long arg4)
@@ -7264,7 +7266,7 @@ static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
#endif
#ifdef TARGET_NR_ftruncate64
static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
abi_long arg2,
abi_long arg3,
abi_long arg4)
@@ -7559,12 +7561,12 @@ static inline int target_to_host_mlockall_arg(int arg)
#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
defined(TARGET_NR_newfstatat))
static inline abi_long host_to_target_stat64(void *cpu_env,
static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
abi_ulong target_addr,
struct stat *host_st)
{
#if defined(TARGET_ARM) && defined(TARGET_ABI32)
if (((CPUARMState *)cpu_env)->eabi) {
if (cpu_env->eabi) {
struct target_eabi_stat64 *target_st;
if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
@@ -7961,9 +7963,9 @@ int host_to_target_waitstatus(int status)
return status;
}
static int open_self_cmdline(void *cpu_env, int fd)
static int open_self_cmdline(CPUArchState *cpu_env, int fd)
{
CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
CPUState *cpu = env_cpu(cpu_env);
struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
int i;
@@ -7978,9 +7980,9 @@ static int open_self_cmdline(void *cpu_env, int fd)
return 0;
}
static int open_self_maps(void *cpu_env, int fd)
static int open_self_maps(CPUArchState *cpu_env, int fd)
{
CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
CPUState *cpu = env_cpu(cpu_env);
TaskState *ts = cpu->opaque;
GSList *map_info = read_self_maps();
GSList *s;
@@ -8040,9 +8042,9 @@ static int open_self_maps(void *cpu_env, int fd)
return 0;
}
static int open_self_stat(void *cpu_env, int fd)
static int open_self_stat(CPUArchState *cpu_env, int fd)
{
CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
CPUState *cpu = env_cpu(cpu_env);
TaskState *ts = cpu->opaque;
g_autoptr(GString) buf = g_string_new(NULL);
int i;
@@ -8078,9 +8080,9 @@ static int open_self_stat(void *cpu_env, int fd)
return 0;
}
static int open_self_auxv(void *cpu_env, int fd)
static int open_self_auxv(CPUArchState *cpu_env, int fd)
{
CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
CPUState *cpu = env_cpu(cpu_env);
TaskState *ts = cpu->opaque;
abi_ulong auxv = ts->info->saved_auxv;
abi_ulong len = ts->info->auxv_len;
@@ -8141,7 +8143,7 @@ static int is_proc(const char *filename, const char *entry)
#endif
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
static int open_net_route(void *cpu_env, int fd)
static int open_net_route(CPUArchState *cpu_env, int fd)
{
FILE *fp;
char *line = NULL;
@@ -8186,7 +8188,7 @@ static int open_net_route(void *cpu_env, int fd)
#endif
#if defined(TARGET_SPARC)
static int open_cpuinfo(void *cpu_env, int fd)
static int open_cpuinfo(CPUArchState *cpu_env, int fd)
{
dprintf(fd, "type\t\t: sun4u\n");
return 0;
@@ -8194,7 +8196,7 @@ static int open_cpuinfo(void *cpu_env, int fd)
#endif
#if defined(TARGET_HPPA)
static int open_cpuinfo(void *cpu_env, int fd)
static int open_cpuinfo(CPUArchState *cpu_env, int fd)
{
dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
@@ -8206,18 +8208,18 @@ static int open_cpuinfo(void *cpu_env, int fd)
#endif
#if defined(TARGET_M68K)
static int open_hardware(void *cpu_env, int fd)
static int open_hardware(CPUArchState *cpu_env, int fd)
{
dprintf(fd, "Model:\t\tqemu-m68k\n");
return 0;
}
#endif
static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
{
struct fake_open {
const char *filename;
int (*fill)(void *cpu_env, int fd);
int (*fill)(CPUArchState *cpu_env, int fd);
int (*cmp)(const char *s1, const char *s2);
};
const struct fake_open *fake_open;
@@ -8529,7 +8531,7 @@ _syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
* of syscall results, can be performed.
* All errnos that do_syscall() returns must be -TARGET_<errcode>.
*/
static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8)
@@ -8890,7 +8892,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
/* Alpha specific */
case TARGET_NR_getxpid:
((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
cpu_env->ir[IR_A4] = getppid();
return get_errno(getpid());
#endif
#ifdef TARGET_NR_getpid
@@ -9413,7 +9415,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
cpu_env->ir[IR_V0] = 0; /* force no error */
}
#else
sigset_t set, oldset, *set_ptr;
@@ -10033,7 +10035,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
#ifdef TARGET_ALPHA
/* Return value is the unbiased priority. Signal no error. */
((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
cpu_env->ir[IR_V0] = 0;
#else
/* Return value is a biased priority to avoid negative numbers. */
ret = 20 - ret;
@@ -11413,7 +11415,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
{
uid_t euid;
euid=geteuid();
((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
cpu_env->ir[IR_A4]=euid;
}
return get_errno(getuid());
#endif
@@ -11423,7 +11425,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
{
uid_t egid;
egid=getegid();
((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
cpu_env->ir[IR_A4]=egid;
}
return get_errno(getgid());
#endif
@@ -11435,7 +11437,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
case TARGET_GSI_IEEE_FP_CONTROL:
{
uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
uint64_t swcr = ((CPUAlphaState *)cpu_env)->swcr;
uint64_t swcr = cpu_env->swcr;
swcr &= ~SWCR_STATUS_MASK;
swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
@@ -11477,8 +11479,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
* could be queried. Therefore, we store the status
* bits only in FPCR.
*/
((CPUAlphaState *)cpu_env)->swcr
= swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
fpcr = cpu_alpha_load_fpcr(cpu_env);
fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
@@ -11502,7 +11503,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
fex = alpha_ieee_fpcr_to_swcr(fpcr);
fex = exc & ~fex;
fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
fex &= ((CPUArchState *)cpu_env)->swcr;
fex &= (cpu_env)->swcr;
/* Update the hardware fpcr. */
fpcr |= alpha_ieee_swcr_to_fpcr(exc);
@@ -11534,9 +11535,8 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
info.si_signo = SIGFPE;
info.si_errno = 0;
info.si_code = si_code;
info._sifields._sigfault._addr
= ((CPUArchState *)cpu_env)->pc;
queue_signal((CPUArchState *)cpu_env, info.si_signo,
info._sifields._sigfault._addr = (cpu_env)->pc;
queue_signal(cpu_env, info.si_signo,
QEMU_SI_FAULT, &info);
}
ret = 0;
@@ -11822,7 +11822,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
to_flock64_fn *copyto = copy_to_user_flock64;
#ifdef TARGET_ARM
if (!((CPUARMState *)cpu_env)->eabi) {
if (!cpu_env->eabi) {
copyfrom = copy_from_user_oabi_flock64;
copyto = copy_to_user_oabi_flock64;
}
@@ -12050,13 +12050,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_set_thread_area
case TARGET_NR_set_thread_area:
#if defined(TARGET_MIPS)
((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
cpu_env->active_tc.CP0_UserLocal = arg1;
return 0;
#elif defined(TARGET_CRIS)
if (arg1 & 0xff)
ret = -TARGET_EINVAL;
else {
((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
cpu_env->pregs[PR_PID] = arg1;
ret = 0;
}
return ret;
@@ -12783,8 +12783,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = arg6;
queue_signal((CPUArchState *)cpu_env, info.si_signo,
QEMU_SI_FAULT, &info);
queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
ret = 0xdeadbeef;
}
@@ -13153,7 +13152,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
return ret;
}
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8)
+2 -2
View File
@@ -28,7 +28,7 @@
* NB: the default emulated CPU ("any") might not match any existing CPU, e.g.
* on ARM it has all features turned on, so there is no perfect arch string to
* return here */
const char *cpu_to_uname_machine(void *cpu_env)
const char *cpu_to_uname_machine(CPUArchState *cpu_env)
{
#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
@@ -54,7 +54,7 @@ const char *cpu_to_uname_machine(void *cpu_env)
return "armv5te" utsname_suffix;
#elif defined(TARGET_I386) && !defined(TARGET_X86_64)
/* see arch/x86/kernel/cpu/bugs.c: check_bugs(), 386, 486, 586, 686 */
CPUState *cpu = env_cpu((CPUX86State *)cpu_env);
CPUState *cpu = env_cpu(cpu_env);
int family = object_property_get_int(OBJECT(cpu), "family", NULL);
if (family == 4) {
return "i486";
+1 -1
View File
@@ -4,7 +4,7 @@
#include <sys/utsname.h>
#include <linux/utsname.h>
const char *cpu_to_uname_machine(void *cpu_env);
const char *cpu_to_uname_machine(CPUArchState *cpu_env);
int sys_uname(struct new_utsname *buf);
#endif /* UNAME_H */
+9 -9
View File
@@ -59,7 +59,7 @@ int info_is_fdpic(struct image_info *info);
void target_set_brk(abi_ulong new_brk);
void syscall_init(void);
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8);
@@ -132,22 +132,22 @@ void print_termios(void *arg);
/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
#ifdef TARGET_ARM
static inline int regpairs_aligned(void *cpu_env, int num)
static inline int regpairs_aligned(CPUArchState *cpu_env, int num)
{
return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
return cpu_env->eabi == 1;
}
#elif defined(TARGET_MIPS) && defined(TARGET_ABI_MIPSO32)
static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
static inline int regpairs_aligned(CPUArchState *cpu_env, int num) { 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, int num) { return 1; }
static inline int regpairs_aligned(CPUArchState *cpu_env, int num) { return 1; }
#elif defined(TARGET_SH4)
/* SH4 doesn't align register pairs, except for p{read,write}64 */
static inline int regpairs_aligned(void *cpu_env, int num)
static inline int regpairs_aligned(CPUArchState *cpu_env, int num)
{
switch (num) {
case TARGET_NR_pread64:
@@ -159,11 +159,11 @@ static inline int regpairs_aligned(void *cpu_env, int num)
}
}
#elif defined(TARGET_XTENSA)
static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
static inline int regpairs_aligned(CPUArchState *cpu_env, int num) { return 1; }
#elif defined(TARGET_HEXAGON)
static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
static inline int regpairs_aligned(CPUArchState *cpu_env, int num) { return 1; }
#else
static inline int regpairs_aligned(void *cpu_env, int num) { return 0; }
static inline int regpairs_aligned(CPUArchState *cpu_env, int num) { return 0; }
#endif
/**
+2 -2
View File
@@ -1106,7 +1106,7 @@ target_ulong do_common_semihosting(CPUState *cs)
#else
unsigned int i;
output_size = ts->info->arg_end - ts->info->arg_start;
output_size = ts->info->env_strings - ts->info->arg_strings;
if (!output_size) {
/*
* We special-case the "empty command line" case (argc==0).
@@ -1146,7 +1146,7 @@ target_ulong do_common_semihosting(CPUState *cs)
goto out;
}
if (copy_from_user(output_buffer, ts->info->arg_start,
if (copy_from_user(output_buffer, ts->info->arg_strings,
output_size)) {
errno = EFAULT;
status = set_swi_errno(cs, -1);
+55 -14
View File
@@ -1,4 +1,5 @@
#include <assert.h>
#include <execinfo.h>
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
@@ -11,22 +12,28 @@
* inline asm is used instead.
*/
#define DEFINE_ASM_FUNCTION(name, body) \
asm(".globl " #name "\n" \
#name ":\n" \
".cfi_startproc\n" \
body "\n" \
"br %r14\n" \
".cfi_endproc");
void illegal_op(void);
void after_illegal_op(void);
asm(".globl\tillegal_op\n"
"illegal_op:\t.byte\t0x00,0x00\n"
"\t.globl\tafter_illegal_op\n"
"after_illegal_op:\tbr\t%r14");
extern const char after_illegal_op;
DEFINE_ASM_FUNCTION(illegal_op,
".byte 0x00,0x00\n"
".globl after_illegal_op\n"
"after_illegal_op:")
void stg(void *dst, unsigned long src);
asm(".globl\tstg\n"
"stg:\tstg\t%r3,0(%r2)\n"
"\tbr\t%r14");
DEFINE_ASM_FUNCTION(stg, "stg %r3,0(%r2)")
void mvc_8(void *dst, void *src);
asm(".globl\tmvc_8\n"
"mvc_8:\tmvc\t0(8,%r2),0(%r3)\n"
"\tbr\t%r14");
DEFINE_ASM_FUNCTION(mvc_8, "mvc 0(8,%r2),0(%r3)")
extern const char return_from_main_1;
static void safe_puts(const char *s)
{
@@ -49,8 +56,9 @@ static struct {
static void handle_signal(int sig, siginfo_t *info, void *ucontext)
{
int err, i, n_frames;
void *frames[16];
void *page;
int err;
if (sig != expected.sig) {
safe_puts("[ FAILED ] wrong signal");
@@ -86,6 +94,17 @@ static void handle_signal(int sig, siginfo_t *info, void *ucontext)
default:
break;
}
n_frames = backtrace(frames, sizeof(frames) / sizeof(frames[0]));
for (i = 0; i < n_frames; i++) {
if (frames[i] == &return_from_main_1) {
break;
}
}
if (i == n_frames) {
safe_puts("[ FAILED ] backtrace() is broken");
_exit(1);
}
}
static void check_sigsegv(void *func, enum exception exception,
@@ -122,7 +141,7 @@ static void check_sigsegv(void *func, enum exception exception,
assert(err == 0);
}
int main(void)
int main_1(void)
{
struct sigaction act;
int err;
@@ -138,7 +157,7 @@ int main(void)
safe_puts("[ RUN ] Operation exception");
expected.sig = SIGILL;
expected.addr = illegal_op;
expected.psw_addr = (unsigned long)after_illegal_op;
expected.psw_addr = (unsigned long)&after_illegal_op;
expected.exception = exception_operation;
illegal_op();
safe_puts("[ OK ]");
@@ -163,3 +182,25 @@ int main(void)
_exit(0);
}
/*
* Define main() in assembly in order to test that unwinding from signal
* handlers until main() works. This way we can define a specific point that
* the unwinder should reach. This is also better than defining main() in C
* and using inline assembly to call main_1(), since it's not easy to get all
* the clobbers right.
*/
DEFINE_ASM_FUNCTION(main,
"stmg %r14,%r15,112(%r15)\n"
".cfi_offset 14,-48\n"
".cfi_offset 15,-40\n"
"lay %r15,-160(%r15)\n"
".cfi_def_cfa_offset 320\n"
"brasl %r14,main_1\n"
".globl return_from_main_1\n"
"return_from_main_1:\n"
"lmg %r14,%r15,272(%r15)\n"
".cfi_restore 15\n"
".cfi_restore 14\n"
".cfi_def_cfa_offset 160");