Statistics
| Branch: | Revision:

root / darwin-user / signal.c @ 530e7615

History | View | Annotate | Download (12.3 kB)

1
/*
2
 *  Emulation of Linux signals
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
 *  MA 02110-1301, USA.
20
 */
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <stdarg.h>
25
#include <unistd.h>
26
#include <signal.h>
27
#include <errno.h>
28
#include <sys/ucontext.h>
29

    
30
#ifdef __ia64__
31
#undef uc_mcontext
32
#undef uc_sigmask
33
#undef uc_stack
34
#undef uc_link
35
#endif
36

    
37
#include <signal.h>
38

    
39
#include "qemu.h"
40

    
41
#define DEBUG_SIGNAL
42

    
43
#define MAX_SIGQUEUE_SIZE 1024
44

    
45
struct sigqueue {
46
    struct sigqueue *next;
47
    target_siginfo_t info;
48
};
49

    
50
struct emulated_sigaction {
51
    struct target_sigaction sa;
52
    int pending; /* true if signal is pending */
53
    struct sigqueue *first;
54
    struct sigqueue info; /* in order to always have memory for the
55
                             first signal, we put it here */
56
};
57

    
58
static struct sigaltstack target_sigaltstack_used = {
59
    0, 0, SA_DISABLE
60
};
61

    
62
static struct emulated_sigaction sigact_table[NSIG];
63
static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
64
static struct sigqueue *first_free; /* first free siginfo queue entry */
65
static int signal_pending; /* non zero if a signal may be pending */
66

    
67
static void host_signal_handler(int host_signum, siginfo_t *info,
68
                                void *puc);
69

    
70

    
71
static inline int host_to_target_signal(int sig)
72
{
73
    return sig;
74
}
75

    
76
static inline int target_to_host_signal(int sig)
77
{
78
    return sig;
79
}
80

    
81
/* siginfo conversion */
82

    
83

    
84

    
85
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
86
{
87

    
88
}
89

    
90
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
91
{
92

    
93
}
94

    
95
void signal_init(void)
96
{
97
    struct sigaction act;
98
    int i;
99

    
100
    /* set all host signal handlers. ALL signals are blocked during
101
       the handlers to serialize them. */
102
    sigfillset(&act.sa_mask);
103
    act.sa_flags = SA_SIGINFO;
104
    act.sa_sigaction = host_signal_handler;
105
    for(i = 1; i < NSIG; i++) {
106
        sigaction(i, &act, NULL);
107
    }
108

    
109
    memset(sigact_table, 0, sizeof(sigact_table));
110

    
111
    first_free = &sigqueue_table[0];
112
    for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
113
        sigqueue_table[i].next = &sigqueue_table[i + 1];
114
    sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
115
}
116

    
117
/* signal queue handling */
118

    
119
static inline struct sigqueue *alloc_sigqueue(void)
120
{
121
    struct sigqueue *q = first_free;
122
    if (!q)
123
        return NULL;
124
    first_free = q->next;
125
    return q;
126
}
127

    
128
static inline void free_sigqueue(struct sigqueue *q)
129
{
130
    q->next = first_free;
131
    first_free = q;
132
}
133

    
134
/* abort execution with signal */
135
void __attribute((noreturn)) force_sig(int sig)
136
{
137
    int host_sig;
138
    host_sig = target_to_host_signal(sig);
139
    fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
140
            sig, strsignal(host_sig));
141
    _exit(-host_sig);
142
}
143

    
144
/* queue a signal so that it will be send to the virtual CPU as soon
145
   as possible */
146
int queue_signal(int sig, target_siginfo_t *info)
147
{
148
    struct emulated_sigaction *k;
149
    struct sigqueue *q, **pq;
150
    target_ulong handler;
151

    
152
#if defined(DEBUG_SIGNAL)
153
    fprintf(stderr, "queue_signal: sig=%d\n",
154
            sig);
155
#endif
156
    k = &sigact_table[sig - 1];
157
    handler = (target_ulong)k->sa.sa_handler;
158
    if (handler == SIG_DFL) {
159
        /* default handler : ignore some signal. The other are fatal */
160
        if (sig != SIGCHLD &&
161
            sig != SIGURG &&
162
            sig != SIGWINCH) {
163
            force_sig(sig);
164
        } else {
165
            return 0; /* indicate ignored */
166
        }
167
    } else if (handler == host_to_target_signal(SIG_IGN)) {
168
        /* ignore signal */
169
        return 0;
170
    } else if (handler == host_to_target_signal(SIG_ERR)) {
171
        force_sig(sig);
172
    } else {
173
        pq = &k->first;
174
        if (!k->pending) {
175
            /* first signal */
176
            q = &k->info;
177
        } else {
178
            q = alloc_sigqueue();
179
            if (!q)
180
                return -EAGAIN;
181
            while (*pq != NULL)
182
                pq = &(*pq)->next;
183
        }
184
        *pq = q;
185
        q->info = *info;
186
        q->next = NULL;
187
        k->pending = 1;
188
        /* signal that a new signal is pending */
189
        signal_pending = 1;
190
        return 1; /* indicates that the signal was queued */
191
    }
192
}
193

    
194
static void host_signal_handler(int host_signum, siginfo_t *info,
195
                                void *puc)
196
{
197
    int sig;
198
    target_siginfo_t tinfo;
199

    
200
    /* the CPU emulator uses some host signals to detect exceptions,
201
       we we forward to it some signals */
202
    if (host_signum == SIGSEGV || host_signum == SIGBUS) {
203
        if (cpu_signal_handler(host_signum, (void*)info, puc))
204
            return;
205
    }
206

    
207
    /* get target signal number */
208
    sig = host_to_target_signal(host_signum);
209
    if (sig < 1 || sig > NSIG)
210
        return;
211

    
212
#if defined(DEBUG_SIGNAL)
213
        fprintf(stderr, "qemu: got signal %d\n", sig);
214
#endif
215
    if (queue_signal(sig, &tinfo) == 1) {
216
        /* interrupt the virtual CPU as soon as possible */
217
        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
218
    }
219
}
220

    
221
int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
222
{
223
    /* XXX: test errors */
224
    if(oss)
225
    {
226
        oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
227
        oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
228
        oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
229
    }
230
    if(ss)
231
    {
232
        target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
233
        target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
234
        target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
235
    }
236
    return 0;
237
}
238

    
239
int do_sigaction(int sig, const struct sigaction *act,
240
                 struct sigaction *oact)
241
{
242
    struct emulated_sigaction *k;
243
    struct sigaction act1;
244
    int host_sig;
245

    
246
    if (sig < 1 || sig > NSIG)
247
        return -EINVAL;
248

    
249
    k = &sigact_table[sig - 1];
250
#if defined(DEBUG_SIGNAL)
251
    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
252
            sig, (int)act, (int)oact);
253
#endif
254
    if (oact) {
255
#if defined(DEBUG_SIGNAL)
256
    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
257
            sig, (int)act, (int)oact);
258
#endif
259

    
260
        oact->sa_handler = tswapl(k->sa.sa_handler);
261
        oact->sa_flags = tswapl(k->sa.sa_flags);
262
        oact->sa_mask = tswapl(k->sa.sa_mask);
263
    }
264
    if (act) {
265
#if defined(DEBUG_SIGNAL)
266
    fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
267
            act->sa_handler, act->sa_flags, act->sa_mask);
268
#endif
269

    
270
        k->sa.sa_handler = tswapl(act->sa_handler);
271
        k->sa.sa_flags = tswapl(act->sa_flags);
272
        k->sa.sa_mask = tswapl(act->sa_mask);
273
        /* we update the host signal state */
274
        host_sig = target_to_host_signal(sig);
275
        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
276
#if defined(DEBUG_SIGNAL)
277
    fprintf(stderr, "sigaction handler going to call sigaction\n",
278
            act->sa_handler, act->sa_flags, act->sa_mask);
279
#endif
280

    
281
            sigfillset(&act1.sa_mask);
282
            act1.sa_flags = SA_SIGINFO;
283
            if (k->sa.sa_flags & SA_RESTART)
284
                act1.sa_flags |= SA_RESTART;
285
            /* NOTE: it is important to update the host kernel signal
286
               ignore state to avoid getting unexpected interrupted
287
               syscalls */
288
            if (k->sa.sa_handler == SIG_IGN) {
289
                act1.sa_sigaction = (void *)SIG_IGN;
290
            } else if (k->sa.sa_handler == SIG_DFL) {
291
                act1.sa_sigaction = (void *)SIG_DFL;
292
            } else {
293
                act1.sa_sigaction = host_signal_handler;
294
            }
295
            sigaction(host_sig, &act1, NULL);
296
        }
297
    }
298
    return 0;
299
}
300

    
301

    
302
#ifdef TARGET_I386
303

    
304
static inline void *
305
get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
306
{
307
    /* XXX Fix that */
308
    if(target_sigaltstack_used.ss_flags & SA_DISABLE)
309
    {
310
        int esp;
311
        /* Default to using normal stack */
312
        esp = env->regs[R_ESP];
313

    
314
        return (void *)((esp - frame_size) & -8ul);
315
    }
316
    else
317
    {
318
        return target_sigaltstack_used.ss_sp;
319
    }
320
}
321

    
322
static void setup_frame(int sig, struct emulated_sigaction *ka,
323
                        void *set, CPUState *env)
324
{
325
        void *frame;
326
        int i, err = 0;
327

    
328
    fprintf(stderr, "setup_frame %d\n", sig);
329
        frame = get_sigframe(ka, env, sizeof(*frame));
330

    
331
        /* Set up registers for signal handler */
332
        env->regs[R_ESP] = (unsigned long) frame;
333
        env->eip = (unsigned long) ka->sa.sa_handler;
334

    
335
        env->eflags &= ~TF_MASK;
336

    
337
        return;
338

    
339
give_sigsegv:
340
        if (sig == SIGSEGV)
341
                ka->sa.sa_handler = SIG_DFL;
342
        force_sig(SIGSEGV /* , current */);
343
}
344

    
345
long do_sigreturn(CPUState *env, int num)
346
{
347
    int i = 0;
348
    struct target_sigcontext *scp = get_int_arg(&i, env);
349
    /* XXX Get current signal number */
350
    /* XXX Adjust accordin to sc_onstack, sc_mask */
351
    if(tswapl(scp->sc_onstack) & 0x1)
352
        target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
353
    else
354
        target_sigaltstack_used.ss_flags &=  SA_DISABLE;
355
    int set = tswapl(scp->sc_eax);
356
    sigprocmask(SIG_SETMASK, &set, NULL);
357

    
358
    fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
359
    fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
360
    fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
361

    
362
    env->regs[R_EAX] = tswapl(scp->sc_eax);
363
    env->regs[R_EBX] = tswapl(scp->sc_ebx);
364
    env->regs[R_ECX] = tswapl(scp->sc_ecx);
365
    env->regs[R_EDX] = tswapl(scp->sc_edx);
366
    env->regs[R_EDI] = tswapl(scp->sc_edi);
367
    env->regs[R_ESI] = tswapl(scp->sc_esi);
368
    env->regs[R_EBP] = tswapl(scp->sc_ebp);
369
    env->regs[R_ESP] = tswapl(scp->sc_esp);
370
    env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
371
    env->eflags = tswapl(scp->sc_eflags);
372
    env->eip = tswapl(scp->sc_eip);
373
    env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
374
    env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
375
    env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
376
    env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
377
    env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
378

    
379
    /* Again, because our caller's caller will reset EAX */
380
    return env->regs[R_EAX];
381
}
382

    
383
#else
384

    
385
static void setup_frame(int sig, struct emulated_sigaction *ka,
386
                        void *set, CPUState *env)
387
{
388
    fprintf(stderr, "setup_frame: not implemented\n");
389
}
390

    
391
long do_sigreturn(CPUState *env, int num)
392
{
393
    int i = 0;
394
    struct target_sigcontext *scp = get_int_arg(&i, env);
395
    fprintf(stderr, "do_sigreturn: not implemented\n");
396
    return -ENOSYS;
397
}
398

    
399
#endif
400

    
401
void process_pending_signals(void *cpu_env)
402
{
403
    struct emulated_sigaction *k;
404
    struct sigqueue *q;
405
    target_ulong handler;
406
    int sig;
407

    
408
    if (!signal_pending)
409
        return;
410

    
411
    k = sigact_table;
412

    
413
    for(sig = 1; sig <= NSIG; sig++) {
414
        if (k->pending)
415
            goto handle_signal;
416
        k++;
417
    }
418

    
419
    /* if no signal is pending, just return */
420
    signal_pending = 0;
421
    return;
422
handle_signal:
423
    #ifdef DEBUG_SIGNAL
424
    fprintf(stderr, "qemu: process signal %d\n", sig);
425
    #endif
426
    /* dequeue signal */
427
    q = k->first;
428
    k->first = q->next;
429
    if (!k->first)
430
        k->pending = 0;
431

    
432
    sig = gdb_handlesig (cpu_env, sig);
433
    if (!sig) {
434
        fprintf (stderr, "Lost signal\n");
435
        abort();
436
    }
437

    
438
    handler = k->sa.sa_handler;
439
    if (handler == SIG_DFL) {
440
        /* default handler : ignore some signal. The other are fatal */
441
        if (sig != SIGCHLD &&
442
            sig != SIGURG &&
443
            sig != SIGWINCH) {
444
            force_sig(sig);
445
        }
446
    } else if (handler == SIG_IGN) {
447
        /* ignore sig */
448
    } else if (handler == SIG_ERR) {
449
        force_sig(sig);
450
    } else {
451

    
452
        setup_frame(sig, k, 0, cpu_env);
453
        if (k->sa.sa_flags & SA_RESETHAND)
454
            k->sa.sa_handler = SIG_DFL;
455
    }
456
    if (q != &k->info)
457
        free_sigqueue(q);
458
}