Commit f0c88952 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-2.13-pull-request' into staging



# gpg: Signature made Thu 03 May 2018 22:38:35 BST
# gpg:                using RSA key F30C38BD3F2FBE3C
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>"
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>"
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>"
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-2.13-pull-request:
  linux-user: remove useless padding in flock64 structure
  linux-user: introduce target_sigsp() and target_save_altstack()
  linux-user: ARM-FDPIC: Add support for signals for FDPIC targets
  linux-user: ARM-FDPIC: Add support of FDPIC for ARM.
  linux-user: ARM-FDPIC: Identify ARM FDPIC binaries
  Remove CONFIG_USE_FDPIC.

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e2f557f9 7f254c5c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1483,6 +1483,7 @@ typedef struct elf64_shdr {
#define ELFOSABI_TRU64          10      /* Compaq TRU64 UNIX.  */
#define ELFOSABI_MODESTO        11      /* Novell Modesto.  */
#define ELFOSABI_OPENBSD        12      /* OpenBSD.  */
#define ELFOSABI_ARM_FDPIC      65      /* ARM FDPIC */
#define ELFOSABI_ARM            97      /* ARM */
#define ELFOSABI_STANDALONE     255     /* Standalone (embedded) application */

+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
#define ABI_LLONG_ALIGNMENT 2
#endif

#if defined(TARGET_I386) && !defined(TARGET_X86_64)
#if (defined(TARGET_I386) && !defined(TARGET_X86_64)) || defined(TARGET_SH4)
#define ABI_LLONG_ALIGNMENT 4
#endif

+2 −11
Original line number Diff line number Diff line
@@ -120,9 +120,7 @@ static void target_setup_general_frame(struct target_rt_sigframe *sf,
    __put_user(0, &sf->uc.tuc_flags);
    __put_user(0, &sf->uc.tuc_link);

    __put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp);
    __put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags);
    __put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size);
    target_save_altstack(&sf->uc.tuc_stack, env);

    for (i = 0; i < 31; i++) {
        __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
@@ -372,14 +370,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka,
{
    abi_ulong sp;

    sp = env->xregs[31];

    /*
     * This is the X/Open sanctioned signal stack switching.
     */
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
    }
    sp = target_sigsp(get_sp_from_cpustate(env), ka);

    sp = (sp - size) & ~15;

+6 −11
Original line number Diff line number Diff line
@@ -117,12 +117,10 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa,
                                     CPUAlphaState *env,
                                     unsigned long framesize)
{
    abi_ulong sp = env->ir[IR_SP];
    abi_ulong sp;

    sp = target_sigsp(get_sp_from_cpustate(env), sa);

    /* This is the X/Open sanctioned signal stack switching.  */
    if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
    }
    return (sp - framesize) & -32;
}

@@ -187,12 +185,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
    __put_user(0, &frame->uc.tuc_flags);
    __put_user(0, &frame->uc.tuc_link);
    __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
    __put_user(target_sigaltstack_used.ss_sp,
               &frame->uc.tuc_stack.ss_sp);
    __put_user(sas_ss_flags(env->ir[IR_SP]),
               &frame->uc.tuc_stack.ss_flags);
    __put_user(target_sigaltstack_used.ss_size,
               &frame->uc.tuc_stack.ss_size);

    target_save_altstack(&frame->uc.tuc_stack, env);

    setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
    for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
+93 −29
Original line number Diff line number Diff line
@@ -102,13 +102,13 @@ struct sigframe_v1
{
    struct target_sigcontext sc;
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
    abi_ulong retcode;
    abi_ulong retcode[4];
};

struct sigframe_v2
{
    struct target_ucontext_v2 uc;
    abi_ulong retcode;
    abi_ulong retcode[4];
};

struct rt_sigframe_v1
@@ -117,14 +117,14 @@ struct rt_sigframe_v1
    abi_ulong puc;
    struct target_siginfo info;
    struct target_ucontext_v1 uc;
    abi_ulong retcode;
    abi_ulong retcode[4];
};

struct rt_sigframe_v2
{
    struct target_siginfo info;
    struct target_ucontext_v2 uc;
    abi_ulong retcode;
    abi_ulong retcode[4];
};

#define TARGET_CONFIG_CPU_32 1
@@ -147,6 +147,21 @@ static const abi_ulong retcodes[4] = {
        SWI_SYS_RT_SIGRETURN,   SWI_THUMB_RT_SIGRETURN
};

/*
 * Stub needed to make sure the FD register (r9) contains the right
 * value.
 */
static const unsigned long sigreturn_fdpic_codes[3] = {
    0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */
    0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */
    0xe59cf000  /* ldr pc, [r12] to jump into restorer */
};

static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
    0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */
    0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */
    0xf000f8dc  /* ldr pc, [r12] to jump into restorer */
};

static inline int valid_user_regs(CPUARMState *regs)
{
@@ -186,27 +201,42 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
static inline abi_ulong
get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
{
    unsigned long sp = regs->regs[13];
    unsigned long sp;

    /*
     * This is the X/Open sanctioned signal stack switching.
     */
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
    }
    sp = target_sigsp(get_sp_from_cpustate(regs), ka);
    /*
     * ATPCS B01 mandates 8-byte alignment
     */
    return (sp - framesize) & ~7;
}

static void
static int
setup_return(CPUARMState *env, struct target_sigaction *ka,
             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
{
    abi_ulong handler = ka->_sa_handler;
    abi_ulong handler = 0;
    abi_ulong handler_fdpic_GOT = 0;
    abi_ulong retcode;
    int thumb = handler & 1;

    int thumb;
    int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);

    if (is_fdpic) {
        /* In FDPIC mode, ka->_sa_handler points to a function
         * descriptor (FD). The first word contains the address of the
         * handler. The second word contains the value of the PIC
         * register (r9).  */
        abi_ulong funcdesc_ptr = ka->_sa_handler;
        if (get_user_ual(handler, funcdesc_ptr)
            || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
            return 1;
        }
    } else {
        handler = ka->_sa_handler;
    }

    thumb = handler & 1;

    uint32_t cpsr = cpsr_read(env);

    cpsr &= ~CPSR_IT;
@@ -217,7 +247,28 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
    }

    if (ka->sa_flags & TARGET_SA_RESTORER) {
        if (is_fdpic) {
            /* For FDPIC we ensure that the restorer is called with a
             * correct r9 value.  For that we need to write code on
             * the stack that sets r9 and jumps back to restorer
             * value.
             */
            if (thumb) {
                __put_user(sigreturn_fdpic_thumb_codes[0], rc);
                __put_user(sigreturn_fdpic_thumb_codes[1], rc + 1);
                __put_user(sigreturn_fdpic_thumb_codes[2], rc + 2);
                __put_user((abi_ulong)ka->sa_restorer, rc + 3);
            } else {
                __put_user(sigreturn_fdpic_codes[0], rc);
                __put_user(sigreturn_fdpic_codes[1], rc + 1);
                __put_user(sigreturn_fdpic_codes[2], rc + 2);
                __put_user((abi_ulong)ka->sa_restorer, rc + 3);
            }

            retcode = rc_addr + thumb;
        } else {
            retcode = ka->sa_restorer;
        }
    } else {
        unsigned int idx = thumb;

@@ -231,10 +282,15 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
    }

    env->regs[0] = usig;
    if (is_fdpic) {
        env->regs[9] = handler_fdpic_GOT;
    }
    env->regs[13] = frame_addr;
    env->regs[14] = retcode;
    env->regs[15] = handler & (thumb ? ~1 : ~3);
    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);

    return 0;
}

static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
@@ -285,9 +341,7 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));

    memset(&stack, 0, sizeof(stack));
    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
    target_save_altstack(&stack, env);
    memcpy(&uc->tuc_stack, &stack, sizeof(stack));

    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
@@ -327,12 +381,15 @@ static void setup_frame_v1(int usig, struct target_sigaction *ka,
        __put_user(set->sig[i], &frame->extramask[i - 1]);
    }

    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
                 frame_addr + offsetof(struct sigframe_v1, retcode));
    if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct sigframe_v1, retcode))) {
        goto sigsegv;
    }

    unlock_user_struct(frame, frame_addr, 1);
    return;
sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sigsegv(usig);
}

@@ -349,12 +406,15 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka,

    setup_sigframe_v2(&frame->uc, set, regs);

    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
                 frame_addr + offsetof(struct sigframe_v2, retcode));
    if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct sigframe_v2, retcode))) {
        goto sigsegv;
    }

    unlock_user_struct(frame, frame_addr, 1);
    return;
sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sigsegv(usig);
}

@@ -394,9 +454,7 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));

    memset(&stack, 0, sizeof(stack));
    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
    target_save_altstack(&stack, env);
    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));

    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
@@ -404,8 +462,10 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
    }

    setup_return(env, ka, &frame->retcode, frame_addr, usig,
                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
        goto sigsegv;
    }

    env->regs[1] = info_addr;
    env->regs[2] = uc_addr;
@@ -413,6 +473,7 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
    unlock_user_struct(frame, frame_addr, 1);
    return;
sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sigsegv(usig);
}

@@ -435,8 +496,10 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,

    setup_sigframe_v2(&frame->uc, set, env);

    setup_return(env, ka, &frame->retcode, frame_addr, usig,
                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
        goto sigsegv;
    }

    env->regs[1] = info_addr;
    env->regs[2] = uc_addr;
@@ -444,6 +507,7 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
    unlock_user_struct(frame, frame_addr, 1);
    return;
sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sigsegv(usig);
}

Loading