Don't open device if already open.
[wine] / dlls / ntdll / signal_powerpc.c
1 /*
2  * PowerPC signal handling routines
3  *
4  * Copyright 2002 Marcus Meissner, SuSE Linux AG
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #ifdef __powerpc__
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #ifdef HAVE_SYS_PARAM_H
35 # include <sys/param.h>
36 #endif
37 #ifdef HAVE_SYSCALL_H
38 # include <syscall.h>
39 #else
40 # ifdef HAVE_SYS_SYSCALL_H
41 #  include <sys/syscall.h>
42 # endif
43 #endif
44
45 #ifdef HAVE_SYS_VM86_H
46 # include <sys/vm86.h>
47 #endif
48
49 #ifdef HAVE_SYS_SIGNAL_H
50 # include <sys/signal.h>
51 #endif
52
53 #include "windef.h"
54 #include "winbase.h"
55 #include "winreg.h"
56 #include "winternl.h"
57 #include "wine/library.h"
58 #include "wine/exception.h"
59 #include "ntdll_misc.h"
60 #include "wine/debug.h"
61
62 WINE_DEFAULT_DEBUG_CHANNEL(seh);
63
64
65 /***********************************************************************
66  * signal context platform-specific definitions
67  */
68 #ifdef linux
69
70 typedef struct ucontext SIGCONTEXT;
71
72 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
73 # define HANDLER_CONTEXT (__context)
74
75 /* All Registers access - only for local access */
76 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
77
78
79 /* Gpr Registers access  */
80 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
81
82 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
83 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
84 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
85
86 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
87 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
88 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
89
90 /* Float Registers access  */
91 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
92
93 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
94
95 /* Exception Registers access */
96 # define DAR_sig(context)                       REG_sig(dar, context)
97 # define DSISR_sig(context)                     REG_sig(dsisr, context)
98 # define TRAP_sig(context)                      REG_sig(trap, context)
99
100 #endif /* linux */
101
102 #ifdef __APPLE__
103
104 # include <sys/ucontext.h>
105
106 # include <sys/types.h>
107 # include <signal.h>
108 typedef siginfo_t siginfo;
109
110 typedef struct ucontext SIGCONTEXT;
111
112
113 # define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context )
114 # define HANDLER_CONTEXT (__context)
115
116 /* All Registers access - only for local access */
117 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
118 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
119 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
120 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
121
122 /* Gpr Registers access */
123 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
124
125 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
126 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
127 # define CTR_sig(context)                       REG_sig(ctr, context)
128
129 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
130 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
131 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
132
133 /* Float Registers access */
134 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
135
136 # define FPSCR_sig(context)                     FLOATREG_sig(fpscr, context)
137
138 /* Exception Registers access */
139 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
140 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
141 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
142
143 /* Signal defs : Those are undefined on darwin
144 SIGBUS
145 #undef BUS_ADRERR
146 #undef BUS_OBJERR
147 SIGILL
148 #undef ILL_ILLOPN
149 #undef ILL_ILLTRP
150 #undef ILL_ILLADR
151 #undef ILL_COPROC
152 #undef ILL_PRVREG
153 #undef ILL_BADSTK
154 SIGTRAP
155 #undef TRAP_BRKPT
156 #undef TRAP_TRACE
157 SIGFPE
158 */
159
160 #endif /* __APPLE__ */
161
162
163
164 typedef int (*wine_signal_handler)(unsigned int sig);
165
166 static wine_signal_handler handlers[256];
167
168 /***********************************************************************
169  *           dispatch_signal
170  */
171 inline static int dispatch_signal(unsigned int sig)
172 {
173     if (handlers[sig] == NULL) return 0;
174     return handlers[sig](sig);
175 }
176
177 /***********************************************************************
178  *           save_context
179  *
180  * Set the register values from a sigcontext.
181  */
182 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
183 {
184
185 #define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
186         /* Save Gpr registers */
187         C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
188         C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
189         C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
190         C(31);
191 #undef C
192
193         context->Iar = IAR_sig(sigcontext);  /* Program Counter */
194         context->Msr = MSR_sig(sigcontext);  /* Machine State Register (Supervisor) */
195         context->Ctr = CTR_sig(sigcontext);
196         
197         context->Xer = XER_sig(sigcontext);
198         context->Lr  = LR_sig(sigcontext);
199         context->Cr  = CR_sig(sigcontext);
200         
201         /* Saving Exception regs */
202         context->Dar   = DAR_sig(sigcontext);
203         context->Dsisr = DSISR_sig(sigcontext);
204         context->Trap  = TRAP_sig(sigcontext);
205 }
206
207
208 /***********************************************************************
209  *           restore_context
210  *
211  * Build a sigcontext from the register values.
212  */
213 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
214 {
215
216 #define C(x)  GPR_sig(x,sigcontext) = context->Gpr##x
217         C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
218         C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
219         C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
220         C(31);
221 #undef C
222
223         IAR_sig(sigcontext) = context->Iar;  /* Program Counter */
224         MSR_sig(sigcontext) = context->Msr;  /* Machine State Register (Supervisor) */
225         CTR_sig(sigcontext) = context->Ctr;
226         
227         XER_sig(sigcontext) = context->Xer;
228         LR_sig(sigcontext) = context->Lr;
229         CR_sig(sigcontext) = context->Cr;
230         
231         /* Setting Exception regs */
232         DAR_sig(sigcontext) = context->Dar;
233         DSISR_sig(sigcontext) = context->Dsisr;
234         TRAP_sig(sigcontext) = context->Trap;
235 }
236
237
238 /***********************************************************************
239  *           save_fpu
240  *
241  * Set the FPU context from a sigcontext.
242  */
243 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
244 {
245 #define C(x)   context->Fpr##x = FLOAT_sig(x,sigcontext)
246         C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
247         C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
248         C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
249         C(31);
250 #undef C
251         context->Fpscr = FPSCR_sig(sigcontext);
252 }
253
254
255 /***********************************************************************
256  *           restore_fpu
257  *
258  * Restore the FPU context to a sigcontext.
259  */
260 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
261 {
262 #define C(x)  FLOAT_sig(x,sigcontext) = context->Fpr##x
263         C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
264         C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
265         C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
266         C(31);
267 #undef C
268         FPSCR_sig(sigcontext) = context->Fpscr;
269 }
270
271
272 /**********************************************************************
273  *              get_fpu_code
274  *
275  * Get the FPU exception code from the FPU status.
276  */
277 static inline DWORD get_fpu_code( const CONTEXT *context )
278 {
279     DWORD status  = context->Fpscr;
280
281     if (status & 0x01)  /* IE */
282     {
283         if (status & 0x40)  /* SF */
284             return EXCEPTION_FLT_STACK_CHECK;
285         else
286             return EXCEPTION_FLT_INVALID_OPERATION;
287     }
288     if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND;  /* DE flag */
289     if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO;    /* ZE flag */
290     if (status & 0x08) return EXCEPTION_FLT_OVERFLOW;          /* OE flag */
291     if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW;         /* UE flag */
292     if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT;    /* PE flag */
293     return EXCEPTION_FLT_INVALID_OPERATION;  /* generic error */
294 }
295
296 /**********************************************************************
297  *              do_segv
298  *
299  * Implementation of SIGSEGV handler.
300  */
301 static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr )
302 {
303     EXCEPTION_RECORD rec;
304     DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
305
306     rec.ExceptionRecord  = NULL;
307     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
308     rec.ExceptionAddress = addr;
309     rec.NumberParameters = 0;
310     
311     switch (trap) {
312     case SIGSEGV:
313         switch ( code & 0xffff ) {
314         case SEGV_MAPERR:
315         case SEGV_ACCERR:
316                 rec.NumberParameters = 2;
317                 rec.ExceptionInformation[0] = 0; /* FIXME ? */
318                 rec.ExceptionInformation[1] = (ULONG_PTR)addr;
319                 if (!(page_fault_code=VIRTUAL_HandleFault(addr)))
320                         return;
321                 rec.ExceptionCode = page_fault_code;
322                 break;
323         default:FIXME("Unhandled SIGSEGV/%x\n",code);
324                 break;
325         }
326         break;
327     case SIGBUS:
328         switch ( code & 0xffff ) {
329         case BUS_ADRALN:
330                 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
331                 break;
332 #ifdef BUS_ADRERR
333         case BUS_ADRERR:
334 #endif
335 #ifdef BUS_OBJERR
336         case BUS_OBJERR:
337                 /* FIXME: correct for all cases ? */
338                 rec.NumberParameters = 2;
339                 rec.ExceptionInformation[0] = 0; /* FIXME ? */
340                 rec.ExceptionInformation[1] = (ULONG_PTR)addr;
341                 if (!(page_fault_code=VIRTUAL_HandleFault(addr)))
342                         return;
343                 rec.ExceptionCode = page_fault_code;
344                 break;
345 #endif
346         default:FIXME("Unhandled SIGBUS/%x\n",code);
347                 break;
348         }
349         break;
350     case SIGILL:
351         switch ( code & 0xffff ) {
352         case ILL_ILLOPC: /* illegal opcode */
353 #ifdef ILL_ILLOPN
354         case ILL_ILLOPN: /* illegal operand */
355 #endif
356 #ifdef ILL_ILLADR
357         case ILL_ILLADR: /* illegal addressing mode */
358 #endif
359 #ifdef ILL_ILLTRP
360         case ILL_ILLTRP: /* illegal trap */
361 #endif
362 #ifdef ILL_COPROC
363         case ILL_COPROC: /* coprocessor error */
364 #endif
365                 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
366                 break;
367         case ILL_PRVOPC: /* privileged opcode */
368 #ifdef ILL_PRVREG
369         case ILL_PRVREG: /* privileged register */
370 #endif
371                 rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
372                 break;
373 #ifdef ILL_BADSTK
374         case ILL_BADSTK: /* internal stack error */
375                 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
376                 break;
377 #endif
378         default:FIXME("Unhandled SIGILL/%x\n", code);
379                 break;
380         }
381         break;
382     }
383     __regs_RtlRaiseException( &rec, context );
384 }
385
386 /**********************************************************************
387  *              do_trap
388  *
389  * Implementation of SIGTRAP handler.
390  */
391 static void do_trap( CONTEXT *context, int code, void * addr )
392 {
393     EXCEPTION_RECORD rec;
394
395     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
396     rec.ExceptionRecord  = NULL;
397     rec.ExceptionAddress = addr;
398     rec.NumberParameters = 0;
399
400     /* FIXME: check if we might need to modify PC */
401     switch (code & 0xffff) {
402 #ifdef TRAP_BRKPT
403     case TRAP_BRKPT:
404         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
405         break;
406 #endif
407 #ifdef TRAP_TRACE
408     case TRAP_TRACE:
409         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
410         break;
411 #endif
412     default:FIXME("Unhandled SIGTRAP/%x\n", code);
413                 break;
414     }
415     __regs_RtlRaiseException( &rec, context );
416 }
417
418 /**********************************************************************
419  *              do_trap
420  *
421  * Implementation of SIGFPE handler.
422  */
423 static void do_fpe( CONTEXT *context, int code, void * addr )
424 {
425     EXCEPTION_RECORD rec;
426
427     switch ( code  & 0xffff ) {
428 #ifdef FPE_FLTSUB
429     case FPE_FLTSUB:
430         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
431         break;
432 #endif
433 #ifdef FPE_INTDIV
434     case FPE_INTDIV:
435         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
436         break;
437 #endif
438 #ifdef FPE_INTOVF
439     case FPE_INTOVF:
440         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
441         break;
442 #endif
443 #ifdef FPE_FLTDIV
444     case FPE_FLTDIV:
445         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
446         break;
447 #endif
448 #ifdef FPE_FLTOVF
449     case FPE_FLTOVF:
450         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
451         break;
452 #endif
453 #ifdef FPE_FLTUND
454     case FPE_FLTUND:
455         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
456         break;
457 #endif
458 #ifdef FPE_FLTRES
459     case FPE_FLTRES:
460         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
461         break;
462 #endif
463 #ifdef FPE_FLTINV
464     case FPE_FLTINV:
465 #endif
466     default:
467         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
468         break;
469     }
470     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
471     rec.ExceptionRecord  = NULL;
472     rec.ExceptionAddress = addr;
473     rec.NumberParameters = 0;
474     __regs_RtlRaiseException( &rec, context );
475 }
476
477 /**********************************************************************
478  *              segv_handler
479  *
480  * Handler for SIGSEGV and related errors.
481  */
482 static HANDLER_DEF(segv_handler)
483 {
484     CONTEXT context;
485     save_context( &context, HANDLER_CONTEXT );
486     do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr );
487     restore_context( &context, HANDLER_CONTEXT );
488 }
489
490 /**********************************************************************
491  *              trap_handler
492  *
493  * Handler for SIGTRAP.
494  */
495 static HANDLER_DEF(trap_handler)
496 {
497     CONTEXT context;
498     save_context( &context, HANDLER_CONTEXT );
499     do_trap( &context, __siginfo->si_code, __siginfo->si_addr );
500     restore_context( &context, HANDLER_CONTEXT );
501 }
502
503 /**********************************************************************
504  *              fpe_handler
505  *
506  * Handler for SIGFPE.
507  */
508 static HANDLER_DEF(fpe_handler)
509 {
510     CONTEXT context;
511     save_fpu( &context, HANDLER_CONTEXT );
512     save_context( &context, HANDLER_CONTEXT );
513     do_fpe( &context,  __siginfo->si_code, __siginfo->si_addr );
514     restore_context( &context, HANDLER_CONTEXT );
515     restore_fpu( &context, HANDLER_CONTEXT );
516 }
517
518 /**********************************************************************
519  *              int_handler
520  *
521  * Handler for SIGINT.
522  */
523 static HANDLER_DEF(int_handler)
524 {
525     if (!dispatch_signal(SIGINT))
526     {
527         EXCEPTION_RECORD rec;
528         CONTEXT context;
529
530         save_context( &context, HANDLER_CONTEXT );
531         rec.ExceptionCode    = CONTROL_C_EXIT;
532         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
533         rec.ExceptionRecord  = NULL;
534         rec.ExceptionAddress = (LPVOID)context.Iar;
535         rec.NumberParameters = 0;
536         __regs_RtlRaiseException( &rec, &context );
537         restore_context( &context, HANDLER_CONTEXT );
538     }
539 }
540
541
542 /**********************************************************************
543  *              abrt_handler
544  *
545  * Handler for SIGABRT.
546  */
547 static HANDLER_DEF(abrt_handler)
548 {
549     EXCEPTION_RECORD rec;
550     CONTEXT context;
551
552     save_context( &context, HANDLER_CONTEXT );
553     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
554     rec.ExceptionFlags   = EH_NONCONTINUABLE;
555     rec.ExceptionRecord  = NULL;
556     rec.ExceptionAddress = (LPVOID)context.Iar;
557     rec.NumberParameters = 0;
558     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
559     restore_context( &context, HANDLER_CONTEXT );
560 }
561
562
563 /**********************************************************************
564  *              term_handler
565  *
566  * Handler for SIGTERM.
567  */
568 static HANDLER_DEF(term_handler)
569 {
570     server_abort_thread(0);
571 }
572
573
574 /**********************************************************************
575  *              usr1_handler
576  *
577  * Handler for SIGUSR1, used to signal a thread that it got suspended.
578  */
579 static HANDLER_DEF(usr1_handler)
580 {
581     LARGE_INTEGER timeout;
582
583     /* wait with 0 timeout, will only return once the thread is no longer suspended */
584     timeout.QuadPart = 0;
585     NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout, 0 );
586 }
587
588
589 /***********************************************************************
590  *           set_handler
591  *
592  * Set a signal handler
593  */
594 static int set_handler( int sig, void (*func)() )
595 {
596     struct sigaction sig_act;
597
598     sig_act.sa_sigaction = func;
599     sigemptyset( &sig_act.sa_mask );
600     sigaddset( &sig_act.sa_mask, SIGINT );
601     sigaddset( &sig_act.sa_mask, SIGALRM );
602
603     sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
604     return sigaction( sig, &sig_act, NULL );
605 }
606
607
608 /***********************************************************************
609  *           __wine_set_signal_handler   (NTDLL.@)
610  */
611 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
612 {
613     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
614     if (handlers[sig] != NULL) return -2;
615     handlers[sig] = wsh;
616     return 0;
617 }
618
619
620 /**********************************************************************
621  *              SIGNAL_Init
622  */
623 BOOL SIGNAL_Init(void)
624 {
625     if (set_handler( SIGINT,  (void (*)())int_handler ) == -1) goto error;
626     if (set_handler( SIGFPE,  (void (*)())fpe_handler ) == -1) goto error;
627     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
628     if (set_handler( SIGILL,  (void (*)())segv_handler ) == -1) goto error;
629     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
630     if (set_handler( SIGTERM, (void (*)())term_handler ) == -1) goto error;
631     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
632 #ifdef SIGBUS
633     if (set_handler( SIGBUS,  (void (*)())segv_handler ) == -1) goto error;
634 #endif
635 #ifdef SIGTRAP
636     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
637 #endif
638
639     return TRUE;
640
641  error:
642     perror("sigaction");
643     return FALSE;
644 }
645
646
647 /**********************************************************************
648  *              __wine_enter_vm86   (NTDLL.@)
649  */
650 void __wine_enter_vm86( CONTEXT *context )
651 {
652     MESSAGE("vm86 mode not supported on this platform\n");
653 }
654
655 /**********************************************************************
656  *              DbgBreakPoint   (NTDLL.@)
657  */
658 void WINAPI DbgBreakPoint(void)
659 {
660      kill(getpid(), SIGTRAP);
661 }
662
663 /**********************************************************************
664  *              DbgUserBreakPoint   (NTDLL.@)
665  */
666 void WINAPI DbgUserBreakPoint(void)
667 {
668      kill(getpid(), SIGTRAP);
669 }
670
671 #endif  /* __powerpc__ */