⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
字号:
/* *  Emulation of Linux signals * *  Copyright (c) 2003 Fabrice Bellard * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdarg.h>#include <unistd.h>#include <signal.h>#include <errno.h>#include <sys/ucontext.h>#ifdef __ia64__#undef uc_mcontext#undef uc_sigmask#undef uc_stack#undef uc_link#endif#include <signal.h>#include "qemu.h"#define DEBUG_SIGNAL#define MAX_SIGQUEUE_SIZE 1024struct sigqueue {    struct sigqueue *next;    target_siginfo_t info;};struct emulated_sigaction {    struct target_sigaction sa;    int pending; /* true if signal is pending */    struct sigqueue *first;    struct sigqueue info; /* in order to always have memory for the                             first signal, we put it here */};struct sigaltstack target_sigaltstack_used = {    0, 0, SA_DISABLE};static struct emulated_sigaction sigact_table[NSIG];static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */static struct sigqueue *first_free; /* first free siginfo queue entry */static int signal_pending; /* non zero if a signal may be pending */static void host_signal_handler(int host_signum, siginfo_t *info,                                void *puc);static inline int host_to_target_signal(int sig){    return sig;}static inline int target_to_host_signal(int sig){    return sig;}/* siginfo conversion */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 signal_init(void){    struct sigaction act;    int i;    /* set all host signal handlers. ALL signals are blocked during       the handlers to serialize them. */    sigfillset(&act.sa_mask);    act.sa_flags = SA_SIGINFO;    act.sa_sigaction = host_signal_handler;    for(i = 1; i < NSIG; i++) {        sigaction(i, &act, NULL);    }    memset(sigact_table, 0, sizeof(sigact_table));    first_free = &sigqueue_table[0];    for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)        sigqueue_table[i].next = &sigqueue_table[i + 1];    sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;}/* signal queue handling */static inline struct sigqueue *alloc_sigqueue(void){    struct sigqueue *q = first_free;    if (!q)        return NULL;    first_free = q->next;    return q;}static inline void free_sigqueue(struct sigqueue *q){    q->next = first_free;    first_free = q;}/* abort execution with signal */void __attribute((noreturn)) force_sig(int sig){    int host_sig;    host_sig = target_to_host_signal(sig);    fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",            sig, strsignal(host_sig));    _exit(-host_sig);}/* queue a signal so that it will be send to the virtual CPU as soon   as possible */int queue_signal(int sig, target_siginfo_t *info){    struct emulated_sigaction *k;    struct sigqueue *q, **pq;    target_ulong handler;#if defined(DEBUG_SIGNAL)    fprintf(stderr, "queue_signal: sig=%d\n",            sig);#endif    k = &sigact_table[sig - 1];    handler = (target_ulong)k->sa.sa_handler;    if (handler == SIG_DFL) {        /* default handler : ignore some signal. The other are fatal */        if (sig != SIGCHLD &&            sig != SIGURG &&            sig != SIGWINCH) {            force_sig(sig);        } else {            return 0; /* indicate ignored */        }    } else if (handler == host_to_target_signal(SIG_IGN)) {        /* ignore signal */        return 0;    } else if (handler == host_to_target_signal(SIG_ERR)) {        force_sig(sig);    } else {        pq = &k->first;        if (!k->pending) {            /* first signal */            q = &k->info;        } else {            q = alloc_sigqueue();            if (!q)                return -EAGAIN;            while (*pq != NULL)                pq = &(*pq)->next;        }        *pq = q;        q->info = *info;        q->next = NULL;        k->pending = 1;        /* signal that a new signal is pending */        signal_pending = 1;        return 1; /* indicates that the signal was queued */    }}static void host_signal_handler(int host_signum, siginfo_t *info,                                void *puc){    int sig;    target_siginfo_t tinfo;    /* the CPU emulator uses some host signals to detect exceptions,       we we forward to it some signals */    if (host_signum == SIGSEGV || host_signum == SIGBUS) {        if (cpu_signal_handler(host_signum, (void*)info, puc))            return;    }    /* get target signal number */    sig = host_to_target_signal(host_signum);    if (sig < 1 || sig > NSIG)        return;#if defined(DEBUG_SIGNAL)	fprintf(stderr, "qemu: got signal %d\n", sig);#endif    if (queue_signal(sig, &tinfo) == 1) {        /* interrupt the virtual CPU as soon as possible */        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);    }}int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss){    /* XXX: test errors */    if(oss)    {        oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);        oss->ss_size = tswap32(target_sigaltstack_used.ss_size);        oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);    }    if(ss)    {        target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);        target_sigaltstack_used.ss_size = tswap32(ss->ss_size);        target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);    }    return 0;}int do_sigaction(int sig, const struct sigaction *act,                 struct sigaction *oact){    struct emulated_sigaction *k;    struct sigaction act1;    int host_sig;    if (sig < 1 || sig > NSIG)        return -EINVAL;    k = &sigact_table[sig - 1];#if defined(DEBUG_SIGNAL)    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",            sig, (int)act, (int)oact);#endif    if (oact) {#if defined(DEBUG_SIGNAL)    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",            sig, (int)act, (int)oact);#endif        oact->sa_handler = tswapl(k->sa.sa_handler);        oact->sa_flags = tswapl(k->sa.sa_flags);        oact->sa_mask = tswapl(k->sa.sa_mask);    }    if (act) {#if defined(DEBUG_SIGNAL)    fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",            act->sa_handler, act->sa_flags, act->sa_mask);#endif        k->sa.sa_handler = tswapl(act->sa_handler);        k->sa.sa_flags = tswapl(act->sa_flags);        k->sa.sa_mask = tswapl(act->sa_mask);        /* we update the host signal state */        host_sig = target_to_host_signal(sig);        if (host_sig != SIGSEGV && host_sig != SIGBUS) {#if defined(DEBUG_SIGNAL)    fprintf(stderr, "sigaction handler going to call sigaction\n",            act->sa_handler, act->sa_flags, act->sa_mask);#endif            sigfillset(&act1.sa_mask);            act1.sa_flags = SA_SIGINFO;            if (k->sa.sa_flags & SA_RESTART)                act1.sa_flags |= SA_RESTART;            /* NOTE: it is important to update the host kernel signal               ignore state to avoid getting unexpected interrupted               syscalls */            if (k->sa.sa_handler == SIG_IGN) {                act1.sa_sigaction = (void *)SIG_IGN;            } else if (k->sa.sa_handler == SIG_DFL) {                act1.sa_sigaction = (void *)SIG_DFL;            } else {                act1.sa_sigaction = host_signal_handler;            }            sigaction(host_sig, &act1, NULL);        }    }    return 0;}#ifdef TARGET_I386static inline void *get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size){    /* XXX Fix that */    if(target_sigaltstack_used.ss_flags & SA_DISABLE)    {        int esp;        /* Default to using normal stack */        esp = env->regs[R_ESP];        return (void *)((esp - frame_size) & -8ul);    }    else    {        return target_sigaltstack_used.ss_sp;    }}static void setup_frame(int sig, struct emulated_sigaction *ka,			void *set, CPUState *env){	void *frame;	int i, err = 0;    fprintf(stderr, "setup_frame %d\n", sig);	frame = get_sigframe(ka, env, sizeof(*frame));	/* Set up registers for signal handler */	env->regs[R_ESP] = (unsigned long) frame;	env->eip = (unsigned long) ka->sa.sa_handler;	env->eflags &= ~TF_MASK;	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV /* , current */);}long do_sigreturn(CPUState *env, int num){    int i = 0;    struct target_sigcontext *scp = get_int_arg(&i, env);    /* XXX Get current signal number */    /* XXX Adjust accordin to sc_onstack, sc_mask */    if(tswapl(scp->sc_onstack) & 0x1)        target_sigaltstack_used.ss_flags |= ~SA_DISABLE;    else        target_sigaltstack_used.ss_flags &=  SA_DISABLE;    int set = tswapl(scp->sc_eax);    sigprocmask(SIG_SETMASK, &set, NULL);    fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));    fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));    fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));    env->regs[R_EAX] = tswapl(scp->sc_eax);    env->regs[R_EBX] = tswapl(scp->sc_ebx);    env->regs[R_ECX] = tswapl(scp->sc_ecx);    env->regs[R_EDX] = tswapl(scp->sc_edx);    env->regs[R_EDI] = tswapl(scp->sc_edi);    env->regs[R_ESI] = tswapl(scp->sc_esi);    env->regs[R_EBP] = tswapl(scp->sc_ebp);    env->regs[R_ESP] = tswapl(scp->sc_esp);    env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);    env->eflags = tswapl(scp->sc_eflags);    env->eip = tswapl(scp->sc_eip);    env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);    env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);    env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);    env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);    env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);    /* Again, because our caller's caller will reset EAX */    return env->regs[R_EAX];}#elsestatic void setup_frame(int sig, struct emulated_sigaction *ka,			void *set, CPUState *env){    fprintf(stderr, "setup_frame: not implemented\n");}long do_sigreturn(CPUState *env, int num){    int i = 0;    struct target_sigcontext *scp = get_int_arg(&i, env);    fprintf(stderr, "do_sigreturn: not implemented\n");    return -ENOSYS;}#endifvoid process_pending_signals(void *cpu_env){    struct emulated_sigaction *k;    struct sigqueue *q;    target_ulong handler;    int sig;    if (!signal_pending)        return;    k = sigact_table;    for(sig = 1; sig <= NSIG; sig++) {        if (k->pending)            goto handle_signal;        k++;    }    /* if no signal is pending, just return */    signal_pending = 0;    return;handle_signal:    #ifdef DEBUG_SIGNAL    fprintf(stderr, "qemu: process signal %d\n", sig);    #endif    /* dequeue signal */    q = k->first;    k->first = q->next;    if (!k->first)        k->pending = 0;    sig = gdb_handlesig (cpu_env, sig);    if (!sig) {        fprintf (stderr, "Lost signal\n");        abort();    }    handler = k->sa.sa_handler;    if (handler == SIG_DFL) {        /* default handler : ignore some signal. The other are fatal */        if (sig != SIGCHLD &&            sig != SIGURG &&            sig != SIGWINCH) {            force_sig(sig);        }    } else if (handler == SIG_IGN) {        /* ignore sig */    } else if (handler == SIG_ERR) {        force_sig(sig);    } else {        setup_frame(sig, k, 0, cpu_env);	if (k->sa.sa_flags & SA_RESETHAND)            k->sa.sa_handler = SIG_DFL;    }    if (q != &k->info)        free_sigqueue(q);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -