1/*
2 * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _DEBUGGER_H
6#define _DEBUGGER_H
7
8
9#include <signal.h>
10
11#include <image.h>
12#include <OS.h>
13
14// include architecture specific definitions
15#include <arch/x86/arch_debugger.h>
16#include <arch/x86_64/arch_debugger.h>
17#include <arch/ppc/arch_debugger.h>
18#include <arch/m68k/arch_debugger.h>
19#include <arch/mipsel/arch_debugger.h>
20#include <arch/arm/arch_debugger.h>
21
22
23#ifdef __x86_64__
24	typedef struct x86_64_debug_cpu_state debug_cpu_state;
25#elif __INTEL__
26	typedef struct x86_debug_cpu_state debug_cpu_state;
27#elif __POWERPC__
28	typedef struct ppc_debug_cpu_state debug_cpu_state;
29#elif __M68K__
30	typedef struct m68k_debug_cpu_state debug_cpu_state;
31#elif __MIPSEL__
32	typedef struct mipsel_debug_cpu_state debug_cpu_state;
33#elif __ARM__
34	typedef struct arm_debug_cpu_state debug_cpu_state;
35#else
36	#error unsupported architecture
37#endif
38
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44extern status_t	install_default_debugger(port_id debuggerPort);
45extern port_id	install_team_debugger(team_id team, port_id debuggerPort);
46extern status_t	remove_team_debugger(team_id team);
47extern status_t	debug_thread(thread_id thread);
48extern void		wait_for_debugger(void);
49
50// EXPERIMENTAL: Self-debugging functions. Will fail when a team debugger is
51// installed. A breakpoint/watchpoint hit will cause the default debugger to
52// be installed for the team.
53extern status_t	set_debugger_breakpoint(void *address);
54extern status_t	clear_debugger_breakpoint(void *address);
55extern status_t	set_debugger_watchpoint(void *address, uint32 type,
56					int32 length);
57extern status_t	clear_debugger_watchpoint(void *address);
58
59
60// team debugging flags
61enum {
62	// event mask: If a flag is set, any of the team's threads will stop when
63	// the respective event occurs. None of the flags are enabled by default.
64	// Always enabled are debugger() calls and hardware exceptions, as well as
65	// the deletion of the debugged team.
66	B_TEAM_DEBUG_SIGNALS						= 0x00010000,
67	B_TEAM_DEBUG_PRE_SYSCALL					= 0x00020000,
68	B_TEAM_DEBUG_POST_SYSCALL					= 0x00040000,
69	B_TEAM_DEBUG_TEAM_CREATION					= 0x00080000,
70	B_TEAM_DEBUG_THREADS						= 0x00100000,
71	B_TEAM_DEBUG_IMAGES							= 0x00200000,
72	B_TEAM_DEBUG_PREVENT_EXIT					= 0x00400000,
73
74	// new thread handling
75	B_TEAM_DEBUG_STOP_NEW_THREADS				= 0x01000000,
76
77	B_TEAM_DEBUG_USER_FLAG_MASK					= 0xffff0000,
78};
79
80// per-thread debugging flags
81enum {
82	// event mask: If a flag is set, the thread will stop when the respective
83	// event occurs. If there is a corresponding team flag, it is sufficient,
84	// if either is set. Per default none of the flags is set.
85	B_THREAD_DEBUG_PRE_SYSCALL					= 0x00010000,
86	B_THREAD_DEBUG_POST_SYSCALL					= 0x00020000,
87
88	// child thread handling
89	B_THREAD_DEBUG_STOP_CHILD_THREADS			= 0x00100000,
90	B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS	= 0x00200000,
91
92	B_THREAD_DEBUG_USER_FLAG_MASK				= 0xffff0000,
93};
94
95// in case of a B_EXCEPTION_OCCURRED event: the type of the exception
96typedef enum {
97	B_NON_MASKABLE_INTERRUPT	= 0,
98	B_MACHINE_CHECK_EXCEPTION,
99	B_SEGMENT_VIOLATION,
100	B_ALIGNMENT_EXCEPTION,
101	B_DIVIDE_ERROR,
102	B_OVERFLOW_EXCEPTION,
103	B_BOUNDS_CHECK_EXCEPTION,
104	B_INVALID_OPCODE_EXCEPTION,
105	B_SEGMENT_NOT_PRESENT,
106	B_STACK_FAULT,
107	B_GENERAL_PROTECTION_FAULT,
108	B_FLOATING_POINT_EXCEPTION,
109} debug_exception_type;
110
111// Value indicating how a stopped thread shall continue.
112enum {
113	B_THREAD_DEBUG_HANDLE_EVENT = 0,	// handle the event normally
114										// (e.g. a signal is delivered, a
115										// CPU fault kills the team,...)
116	B_THREAD_DEBUG_IGNORE_EVENT,		// ignore the event and continue as if
117										// it didn't occur (e.g. a signal or
118										// a CPU fault will be ignored)
119};
120
121// watchpoint types (ToDo: Check PPC support.)
122enum {
123	B_DATA_READ_WATCHPOINT = 0,			// !x86
124	B_DATA_WRITE_WATCHPOINT,
125	B_DATA_READ_WRITE_WATCHPOINT,
126};
127
128// how to apply signal ignore masks
129typedef enum {
130	B_DEBUG_SIGNAL_MASK_AND	= 0,
131	B_DEBUG_SIGNAL_MASK_OR,
132	B_DEBUG_SIGNAL_MASK_SET,
133} debug_signal_mask_op;
134
135#define B_DEBUG_SIGNAL_TO_MASK(signal) (1ULL << ((signal) - 1))
136
137// maximal number of bytes to read/write via B_DEBUG_MESSAGE_{READ,WRITE]_MEMORY
138enum {
139	B_MAX_READ_WRITE_MEMORY_SIZE	= 1024,
140};
141
142// messages to the debug nub thread
143typedef enum {
144	B_DEBUG_MESSAGE_READ_MEMORY	= 0,	// read from the team's memory
145	B_DEBUG_MESSAGE_WRITE_MEMORY,		// write to the team's memory
146	B_DEBUG_MESSAGE_SET_TEAM_FLAGS,		// set the team's debugging flags
147	B_DEBUG_MESSAGE_SET_THREAD_FLAGS,	// set a thread's debugging flags
148	B_DEBUG_MESSAGE_CONTINUE_THREAD,	// continue a stopped thread
149	B_DEBUG_MESSAGE_SET_CPU_STATE,		// change a stopped thread's CPU state
150	B_DEBUG_MESSAGE_GET_CPU_STATE,		// get the thread's current CPU state
151	B_DEBUG_MESSAGE_SET_BREAKPOINT,		// set a breakpoint
152	B_DEBUG_MESSAGE_CLEAR_BREAKPOINT,	// clear a breakpoint
153	B_DEBUG_MESSAGE_SET_WATCHPOINT,		// set a watchpoint
154	B_DEBUG_MESSAGE_CLEAR_WATCHPOINT,	// clear a watchpoint
155	B_DEBUG_MESSAGE_SET_SIGNAL_MASKS,	// set/get a thread's masks of signals
156	B_DEBUG_MESSAGE_GET_SIGNAL_MASKS,	//  the debugger is interested in
157	B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER,	// set/get the team's signal handler for
158	B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER,	//  a signal
159
160	B_DEBUG_MESSAGE_PREPARE_HANDOVER,	// prepares the debugged team for being
161										// handed over to another debugger;
162										// the new debugger can just invoke
163										// install_team_debugger()
164
165	B_DEBUG_START_PROFILER,				// start/stop sampling
166	B_DEBUG_STOP_PROFILER				//
167} debug_nub_message;
168
169// messages sent to the debugger
170typedef enum {
171	B_DEBUGGER_MESSAGE_THREAD_DEBUGGED = 0,	// debugger message in reaction to
172											// an invocation of debug_thread()
173	B_DEBUGGER_MESSAGE_DEBUGGER_CALL,		// thread called debugger()
174	B_DEBUGGER_MESSAGE_BREAKPOINT_HIT,		// thread hit a breakpoint
175	B_DEBUGGER_MESSAGE_WATCHPOINT_HIT,		// thread hit a watchpoint
176	B_DEBUGGER_MESSAGE_SINGLE_STEP,			// thread was single-stepped
177	B_DEBUGGER_MESSAGE_PRE_SYSCALL,			// begin of a syscall
178	B_DEBUGGER_MESSAGE_POST_SYSCALL,		// end of a syscall
179	B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED,		// thread received a signal
180	B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED,	// an exception occurred
181	B_DEBUGGER_MESSAGE_TEAM_CREATED,		// the debugged team created a new
182											// one
183	B_DEBUGGER_MESSAGE_TEAM_DELETED,		// the debugged team is gone
184	B_DEBUGGER_MESSAGE_TEAM_EXEC,			// the debugged team executes exec()
185	B_DEBUGGER_MESSAGE_THREAD_CREATED,		// a thread has been created
186	B_DEBUGGER_MESSAGE_THREAD_DELETED,		// a thread has been deleted
187	B_DEBUGGER_MESSAGE_IMAGE_CREATED,		// an image has been created
188	B_DEBUGGER_MESSAGE_IMAGE_DELETED,		// an image has been deleted
189
190	B_DEBUGGER_MESSAGE_PROFILER_UPDATE,		// flush the profiling buffer for a
191											// thread
192
193	B_DEBUGGER_MESSAGE_HANDED_OVER,			// the debugged team has been
194											// handed over to another debugger,
195											// sent to both debuggers
196} debug_debugger_message;
197
198
199// profile events -- when the buffer is in variable stack depth format, a sample
200// count entry >= B_DEBUG_PROFILE_EVENT_BASE indicates a profile event
201enum {
202	B_DEBUG_PROFILE_EVENT_BASE				= 0x80000000,
203	B_DEBUG_PROFILE_EVENT_PARAMETER_MASK	= 0x0000ffff,
204		// & with to get the event's parameter count
205
206	B_DEBUG_PROFILE_IMAGE_EVENT				= 0x80010001
207		// single parameter: the respective image event counter
208};
209
210
211// #pragma mark -
212// #pragma mark ----- messages to the debug nub thread -----
213
214// B_DEBUG_MESSAGE_READ_MEMORY
215
216typedef struct {
217	port_id		reply_port;		// port to send the reply to
218	void		*address;		// address from which to read
219	int32		size;			// number of bytes to read
220} debug_nub_read_memory;
221
222typedef struct {
223	status_t	error;			// B_OK, if reading went fine
224	int32		size;			// the number of bytes actually read
225								// > 0, iff error == B_OK
226	char		data[B_MAX_READ_WRITE_MEMORY_SIZE];
227								// the read data
228} debug_nub_read_memory_reply;
229
230// B_DEBUG_MESSAGE_WRITE_MEMORY
231
232typedef struct {
233	port_id		reply_port;		// port to send the reply to
234	void		*address;		// address to which to write
235	int32		size;			// number of bytes to write
236	char		data[B_MAX_READ_WRITE_MEMORY_SIZE];
237								// data to write
238} debug_nub_write_memory;
239
240typedef struct {
241	status_t	error;			// B_OK, if writing went fine
242	int32		size;			// the number of bytes actually written
243} debug_nub_write_memory_reply;
244
245// B_DEBUG_MESSAGE_SET_TEAM_FLAGS
246
247typedef struct {
248	int32		flags;			// the new team debugging flags
249} debug_nub_set_team_flags;
250
251// B_DEBUG_MESSAGE_SET_THREAD_FLAGS
252
253typedef struct {
254	thread_id	thread;			// the thread
255	int32		flags;			// the new thread debugging flags
256} debug_nub_set_thread_flags;
257
258// B_DEBUG_MESSAGE_CONTINUE_THREAD
259
260typedef struct {
261	thread_id	thread;			// the thread
262	uint32		handle_event;	// how to handle the occurred event
263	bool		single_step;	// true == single step, false == run full speed
264} debug_nub_continue_thread;
265
266// B_DEBUG_MESSAGE_SET_CPU_STATE
267
268typedef struct {
269	thread_id			thread;				// the thread
270	debug_cpu_state		cpu_state;			// the new CPU state
271} debug_nub_set_cpu_state;
272
273// B_DEBUG_MESSAGE_GET_CPU_STATE
274
275typedef struct {
276	port_id					reply_port;		// port to send the reply to
277	thread_id				thread;			// the thread
278} debug_nub_get_cpu_state;
279
280typedef struct {
281	status_t				error;		// != B_OK, if something went wrong
282										// (bad thread ID, thread not stopped)
283	debug_debugger_message	message;	// the reason why the thread stopped
284	debug_cpu_state			cpu_state;	// the thread's CPU state
285} debug_nub_get_cpu_state_reply;
286
287// B_DEBUG_MESSAGE_SET_BREAKPOINT
288
289typedef struct {
290	port_id		reply_port;		// port to send the reply to
291	void		*address;		// breakpoint address
292} debug_nub_set_breakpoint;
293
294typedef struct {
295	status_t	error;			// B_OK, if the breakpoint has been set
296								// successfully
297} debug_nub_set_breakpoint_reply;
298
299// B_DEBUG_MESSAGE_CLEAR_BREAKPOINT
300
301typedef struct {
302	void		*address;		// breakpoint address
303} debug_nub_clear_breakpoint;
304
305// B_DEBUG_MESSAGE_SET_WATCHPOINT
306
307typedef struct {
308	port_id		reply_port;		// port to send the reply to
309	void		*address;		// watchpoint address
310	uint32		type;			// watchpoint type (see type constants above)
311	int32		length;			// number of bytes to watch (typically 1, 2,
312								// 4); architecture specific alignment
313								// restrictions apply.
314} debug_nub_set_watchpoint;
315
316typedef struct {
317	status_t	error;			// B_OK, if the watchpoint has been set
318								// successfully
319} debug_nub_set_watchpoint_reply;
320
321// B_DEBUG_MESSAGE_CLEAR_WATCHPOINT
322
323typedef struct {
324	void		*address;		// watchpoint address
325} debug_nub_clear_watchpoint;
326
327// B_DEBUG_MESSAGE_SET_SIGNAL_MASKS
328
329typedef struct {
330	thread_id				thread;				// the thread
331	uint64					ignore_mask;		// the mask for signals the
332												// debugger wishes not to be
333												// notified of
334	uint64					ignore_once_mask;	// the mask for signals the
335												// debugger wishes not to be
336												// notified of when they next
337												// occur
338	debug_signal_mask_op	ignore_op;			// what to do with ignore_mask
339	debug_signal_mask_op	ignore_once_op;		// what to do with
340												// ignore_once_mask
341} debug_nub_set_signal_masks;
342
343// B_DEBUG_MESSAGE_GET_SIGNAL_MASKS
344
345typedef struct {
346	port_id		reply_port;			// port to send the reply to
347	thread_id	thread;				// the thread
348} debug_nub_get_signal_masks;
349
350typedef struct {
351	status_t	error;				// B_OK, if the thread exists
352	uint64		ignore_mask;		// the mask for signals the debugger wishes
353									// not to be notified of
354	uint64		ignore_once_mask;	// the mask for signals the debugger wishes
355									// not to be notified of when they next
356									// occur
357} debug_nub_get_signal_masks_reply;
358
359// B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER
360
361typedef struct {
362	int					signal;		// the signal
363	struct sigaction	handler;	// the new signal handler
364} debug_nub_set_signal_handler;
365
366// B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER
367
368typedef struct {
369	port_id				reply_port;	// port to send the reply to
370	int					signal;		// the signal
371} debug_nub_get_signal_handler;
372
373typedef struct {
374	status_t			error;		// B_OK, if the thread exists
375	struct sigaction	handler;	// the signal handler
376} debug_nub_get_signal_handler_reply;
377
378// B_DEBUG_MESSAGE_PREPARE_HANDOVER
379
380// no parameters, no reply
381
382// B_DEBUG_START_PROFILER
383
384struct debug_profile_function {
385	addr_t			base;	// function base address
386	size_t			size;	// function size
387};
388
389typedef struct {
390	port_id				reply_port;		// port to send the reply to
391	thread_id			thread;			// thread to profile
392	bigtime_t			interval;		// sample interval
393	area_id				sample_area;	// area into which the sample will be
394										// written
395	int32				stack_depth;	// number of return address per hit
396	bool				variable_stack_depth;
397										// variable number of samples per hit;
398										// cf. debug_profiler_update
399} debug_nub_start_profiler;
400
401typedef struct {
402	status_t			error;
403	int32				image_event;	// number of the last image event
404	bigtime_t			interval;		// actual sample interval (might
405										// differ from the requested one)
406} debug_nub_start_profiler_reply;
407
408// B_DEBUG_STOP_PROFILER
409
410typedef struct {
411	port_id				reply_port;		// port to send the reply to
412	thread_id			thread;			// thread to profile
413} debug_nub_stop_profiler;
414
415// reply is debug_profiler_update
416
417// union of all messages structures sent to the debug nub thread
418typedef union {
419	debug_nub_read_memory			read_memory;
420	debug_nub_write_memory			write_memory;
421	debug_nub_set_team_flags		set_team_flags;
422	debug_nub_set_thread_flags		set_thread_flags;
423	debug_nub_continue_thread		continue_thread;
424	debug_nub_set_cpu_state			set_cpu_state;
425	debug_nub_get_cpu_state			get_cpu_state;
426	debug_nub_set_breakpoint		set_breakpoint;
427	debug_nub_clear_breakpoint		clear_breakpoint;
428	debug_nub_set_watchpoint		set_watchpoint;
429	debug_nub_clear_watchpoint		clear_watchpoint;
430	debug_nub_set_signal_masks		set_signal_masks;
431	debug_nub_get_signal_masks		get_signal_masks;
432	debug_nub_set_signal_handler	set_signal_handler;
433	debug_nub_get_signal_handler	get_signal_handler;
434	debug_nub_start_profiler		start_profiler;
435	debug_nub_stop_profiler			stop_profiler;
436} debug_nub_message_data;
437
438
439// #pragma mark -
440// #pragma mark ----- messages to the debugger -----
441
442// first member of all debugger messages -- not a message by itself
443typedef struct {
444	thread_id	thread;			// the thread being the event origin
445	team_id		team;			// the thread's team
446	port_id		nub_port;		// port to debug nub for this team (only set
447								// for synchronous messages)
448} debug_origin;
449
450// B_DEBUGGER_MESSAGE_THREAD_DEBUGGED
451
452typedef struct {
453	debug_origin		origin;
454} debug_thread_debugged;
455
456// B_DEBUGGER_MESSAGE_DEBUGGER_CALL
457
458typedef struct {
459	debug_origin		origin;
460	void				*message;	// address of the message passed to
461									// debugger()
462} debug_debugger_call;
463
464// B_DEBUGGER_MESSAGE_BREAKPOINT_HIT
465
466typedef struct {
467	debug_origin		origin;
468	debug_cpu_state		cpu_state;	// cpu state
469} debug_breakpoint_hit;
470
471// B_DEBUGGER_MESSAGE_WATCHPOINT_HIT
472
473typedef struct {
474	debug_origin		origin;
475	debug_cpu_state		cpu_state;	// cpu state
476} debug_watchpoint_hit;
477
478// B_DEBUGGER_MESSAGE_SINGLE_STEP
479
480typedef struct {
481	debug_origin		origin;
482	debug_cpu_state		cpu_state;	// cpu state
483} debug_single_step;
484
485// B_DEBUGGER_MESSAGE_PRE_SYSCALL
486
487typedef struct {
488	debug_origin	origin;
489	uint32			syscall;		// the syscall number
490	uint32			args[16];		// syscall arguments
491} debug_pre_syscall;
492
493// B_DEBUGGER_MESSAGE_POST_SYSCALL
494
495typedef struct {
496	debug_origin	origin;
497	bigtime_t		start_time;		// time of syscall start
498	bigtime_t		end_time;		// time of syscall completion
499	uint64			return_value;	// the syscall's return value
500	uint32			syscall;		// the syscall number
501	uint32			args[16];		// syscall arguments
502} debug_post_syscall;
503
504// B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED
505
506typedef struct {
507	debug_origin		origin;
508	int					signal;		// the signal
509	struct sigaction	handler;	// the signal handler
510	bool				deadly;		// true, if handling the signal will kill
511									// the team
512} debug_signal_received;
513
514// B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED
515
516typedef struct {
517	debug_origin			origin;
518	debug_exception_type	exception;		// the exception
519	int						signal;			// the signal that will be sent,
520											// when the thread continues
521											// normally
522} debug_exception_occurred;
523
524// B_DEBUGGER_MESSAGE_TEAM_CREATED
525
526typedef struct {
527	debug_origin	origin;
528	team_id			new_team;		// the newly created team
529} debug_team_created;
530
531// B_DEBUGGER_MESSAGE_TEAM_DELETED
532
533typedef struct {
534	debug_origin	origin;			// thread is < 0, team is the deleted team
535									// (asynchronous message)
536} debug_team_deleted;
537
538// B_DEBUGGER_MESSAGE_TEAM_EXEC
539
540typedef struct {
541	debug_origin	origin;
542	int32			image_event;	// number of the image event
543} debug_team_exec;
544
545// B_DEBUGGER_MESSAGE_THREAD_CREATED
546
547typedef struct {
548	debug_origin	origin;			// the thread that created the new thread
549	team_id			new_thread;		// the newly created thread
550} debug_thread_created;
551
552// B_DEBUGGER_MESSAGE_THREAD_DELETED
553
554typedef struct {
555	debug_origin	origin;			// the deleted thread (asynchronous message)
556} debug_thread_deleted;
557
558// B_DEBUGGER_MESSAGE_IMAGE_CREATED
559
560typedef struct {
561	debug_origin	origin;
562	image_info		info;			// info for the image
563	int32			image_event;	// number of the image event
564} debug_image_created;
565
566// B_DEBUGGER_MESSAGE_IMAGE_DELETED
567
568typedef struct {
569	debug_origin	origin;
570	image_info		info;			// info for the image
571	int32			image_event;	// number of the image event
572} debug_image_deleted;
573
574// B_DEBUGGER_MESSAGE_PROFILER_UPDATE
575
576typedef struct {
577	debug_origin		origin;
578	int32				image_event;	// number of the last image event; all
579										// samples were recorded after this
580										// event and before the next one
581	int32				stack_depth;	// number of return addresses per tick
582	int32				sample_count;	// number of samples in the buffer
583	int32				dropped_ticks;	// number of ticks that had been
584										// dropped, since the buffer was full
585	bool				variable_stack_depth;
586										// the number of samples per hit is
587										// variable, i.e. the format for the
588										// samples of a hit in the buffer is
589										//   <n> <sample 1> ... <sample n>
590										// instead of
591										//   <sample 1> ... <sample stack_depth>
592	bool				stopped;		// if true, the thread is no longer
593										// being profiled
594} debug_profiler_update;
595
596// B_DEBUGGER_MESSAGE_HANDED_OVER
597
598typedef struct {
599	debug_origin	origin;			// thread is < 0, team is the deleted team
600									// (asynchronous message)
601	team_id			debugger;		// the new debugger
602	port_id			debugger_port;	// the port the new debugger uses
603	thread_id		causing_thread;	// the thread that caused entering the
604									// debugger in the first place, -1 if the
605									// debugger wasn't attached automatically
606} debug_handed_over;
607
608// union of all messages structures sent to the debugger
609typedef union {
610	debug_thread_debugged			thread_debugged;
611	debug_debugger_call				debugger_call;
612	debug_breakpoint_hit			breakpoint_hit;
613	debug_watchpoint_hit			watchpoint_hit;
614	debug_single_step				single_step;
615	debug_pre_syscall				pre_syscall;
616	debug_post_syscall				post_syscall;
617	debug_signal_received			signal_received;
618	debug_exception_occurred		exception_occurred;
619	debug_team_created				team_created;
620	debug_team_deleted				team_deleted;
621	debug_team_exec					team_exec;
622	debug_thread_created			thread_created;
623	debug_thread_deleted			thread_deleted;
624	debug_image_created				image_created;
625	debug_image_deleted				image_deleted;
626	debug_profiler_update			profiler_update;
627	debug_handed_over				handed_over;
628
629	debug_origin					origin;	// for convenience (no real message)
630} debug_debugger_message_data;
631
632
633extern void get_debug_message_string(debug_debugger_message message,
634		char *buffer, int32 bufferSize);
635extern void get_debug_exception_string(debug_exception_type exception,
636		char *buffer, int32 bufferSize);
637
638
639#ifdef __cplusplus
640}	// extern "C"
641#endif
642
643#endif	// _DEBUGGER_H
644