2 * Copyright 2015 Steven Watanabe
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
33 #undef debug_on_enter_function
34 #undef debug_on_exit_function
44 #define BREAKPOINT_ENABLED 1
45 #define BREAKPOINT_DISABLED 2
46 #define BREAKPOINT_DELETED 3
48 static struct breakpoint
* breakpoints
;
49 static int num_breakpoints
;
50 static int breakpoints_capacity
;
52 #define DEBUG_NO_CHILD 0
56 #define DEBUG_FINISH 4
57 #define DEBUG_STOPPED 5
59 #define DEBUG_MSG_BREAKPOINT 1
60 #define DEBUG_MSG_END_STEPPING 2
61 #define DEBUG_MSG_SETUP 3
62 #define DEBUG_MSG_DONE 32
64 static int debug_state
;
65 static int debug_depth
;
66 static OBJECT
* debug_file
;
67 static int debug_line
;
68 static FRAME
* debug_frame
;
69 LIST
* debug_print_result
;
70 static int current_token
;
71 static int debug_selected_frame_number
;
73 /* Commands are read from this stream. */
74 static FILE * command_input
;
75 /* Where to send output from commands. */
76 static FILE * command_output
;
77 /* Only valid in the parent. Reads command output from the child. */
78 static FILE * command_child
;
83 void (*command
)( int, const char * * );
86 static struct command_elem
* command_array
;
88 static void debug_listen( void );
89 static int read_command( void );
90 static int is_same_file( OBJECT
* file1
, OBJECT
* file2
);
91 static void debug_mi_format_token( void );
92 static OBJECT
* make_absolute_path( OBJECT
* filename
);
94 static void debug_string_write( FILE * out
, const char * data
)
96 fprintf( out
, "%s", data
);
100 static char * debug_string_read( FILE * in
)
106 while( ( ch
= fgetc( in
) ) > 0 )
108 string_push_back( buf
, (char)ch
);
110 result
= strdup( buf
->value
);
115 static void debug_object_write( FILE * out
, OBJECT
* data
)
117 debug_string_write( out
, object_str( data
) );
120 static OBJECT
* debug_object_read( FILE * in
)
126 while( ( ch
= fgetc( in
) ) > 0 )
128 string_push_back( buf
, (char)ch
);
130 result
= object_new( buf
->value
);
135 static void debug_int_write( FILE * out
, int i
)
137 fprintf( out
, "%d", i
);
141 static int debug_int_read( FILE * in
)
143 OBJECT
* str
= debug_object_read( in
);
144 int result
= atoi( object_str( str
) );
149 static void debug_list_write( FILE * out
, LIST
* l
)
151 LISTITER iter
= list_begin( l
), end
= list_end( l
);
152 fprintf( out
, "%d\n", list_length( l
) );
153 for ( ; iter
!= end
; iter
= list_next( iter
) )
155 debug_object_write( out
, list_item( iter
) );
159 static LIST
* debug_list_read( FILE * in
)
165 fscanf( in
, "%d", &len
);
167 assert( ch
== '\n' );
168 for ( i
= 0; i
< len
; ++i
)
170 result
= list_push_back( result
, debug_object_read( in
) );
175 static void debug_lol_write( FILE * out
, LOL
* lol
)
178 debug_int_write( out
, lol
->count
);
179 for ( i
= 0; i
< lol
->count
; ++i
)
181 debug_list_write( out
, lol_get( lol
, i
) );
185 static void debug_lol_read( FILE * in
, LOL
* lol
)
189 count
= debug_int_read( in
);
190 for ( i
= 0; i
< count
; ++i
)
192 lol_add( lol
, debug_list_read( in
) );
196 static void debug_format_rulename ( string
* out
, FRAME
* frame
)
198 const char * pos
= strchr( frame
->rulename
, '.' );
199 if ( frame
->module
->class_module
&& pos
)
201 string_copy( out
, object_str( frame
->module
->name
) );
202 string_push_back( out
, '.' );
203 string_append( out
, pos
+ 1 );
207 string_copy( out
, frame
->rulename
);
211 static void debug_frame_write( FILE * out
, FRAME
* frame
)
213 string rulename_buffer
[ 1 ];
214 OBJECT
* fullname
= constant_builtin
;
215 OBJECT
* file
= frame
->file
;
216 if ( file
== NULL
) file
= constant_builtin
;
217 else fullname
= make_absolute_path( frame
->file
);
218 debug_format_rulename( rulename_buffer
, frame
);
219 debug_object_write( out
, file
);
220 debug_int_write( out
, frame
->line
);
221 debug_object_write( out
, fullname
);
222 debug_lol_write( out
, frame
->args
);
223 debug_string_write( out
, rulename_buffer
->value
);
224 object_free( fullname
);
225 string_free( rulename_buffer
);
229 * The information passed to the debugger for
230 * a frame is slightly different from the FRAME
233 typedef struct _frame_info
242 static void debug_frame_info_free( FRAME_INFO
* frame
)
244 object_free( frame
->file
);
245 object_free( frame
->fullname
);
246 lol_free( frame
->args
);
247 free( frame
->rulename
);
250 static void debug_frame_read( FILE * in
, FRAME_INFO
* frame
)
252 frame
->file
= debug_object_read( in
);
253 frame
->line
= debug_int_read( in
);
254 frame
->fullname
= debug_object_read( in
);
255 debug_lol_read( in
, frame
->args
);
256 frame
->rulename
= debug_string_read( in
);
259 static int add_breakpoint( struct breakpoint elem
)
261 if ( num_breakpoints
== breakpoints_capacity
)
263 int new_capacity
= breakpoints_capacity
* 2;
264 if ( new_capacity
== 0 ) new_capacity
= 1;
265 breakpoints
= ( struct breakpoint
* )realloc( breakpoints
, new_capacity
* sizeof( struct breakpoint
) );
266 breakpoints_capacity
= new_capacity
;
268 breakpoints
[ num_breakpoints
++ ] = elem
;
269 return num_breakpoints
;
272 static int add_line_breakpoint( OBJECT
* file
, int line
)
274 struct breakpoint elem
;
276 elem
.bound_file
= NULL
;
278 elem
.status
= BREAKPOINT_ENABLED
;
279 return add_breakpoint( elem
);
282 static int add_function_breakpoint( OBJECT
* name
)
284 struct breakpoint elem
;
286 elem
.bound_file
= object_copy( name
);
288 elem
.status
= BREAKPOINT_ENABLED
;
289 return add_breakpoint( elem
);
293 * Checks whether there is an active breakpoint at the
294 * specified location. Returns the breakpoint id
295 * or -1 if none is found.
297 static int handle_line_breakpoint( OBJECT
* file
, int line
)
300 if ( file
== NULL
) return 0;
301 for ( i
= 0; i
< num_breakpoints
; ++i
)
303 if ( breakpoints
[ i
].bound_file
== NULL
&& is_same_file( breakpoints
[ i
].file
, file
) )
305 breakpoints
[ i
].bound_file
= object_copy( file
);
307 if ( breakpoints
[ i
].status
== BREAKPOINT_ENABLED
&&
308 breakpoints
[ i
].bound_file
!= NULL
&&
309 object_equal( breakpoints
[ i
].bound_file
, file
) &&
310 breakpoints
[ i
].line
== line
)
318 static int handle_function_breakpoint( OBJECT
* name
)
320 return handle_line_breakpoint( name
, -1 );
323 static OBJECT
* make_absolute_path( OBJECT
* filename
)
328 const char * root
= object_str( cwd() );
329 path_parse( object_str( filename
), path1
);
330 path1
->f_root
.ptr
= root
;
331 path1
->f_root
.len
= strlen( root
);
333 path_build( path1
, buf
);
334 result
= object_new( buf
->value
);
339 static OBJECT
* get_filename( OBJECT
* path
)
344 const char * root
= object_str( cwd() );
345 path_parse( object_str( path
), path1
);
346 path1
->f_dir
.ptr
= NULL
;
347 path1
->f_dir
.len
= 0;
349 path_build( path1
, buf
);
350 result
= object_new( buf
->value
);
355 static int is_same_file( OBJECT
* file1
, OBJECT
* file2
)
357 OBJECT
* absolute1
= make_absolute_path( file1
);
358 OBJECT
* absolute2
= make_absolute_path( file2
);
359 OBJECT
* norm1
= path_as_key( absolute1
);
360 OBJECT
* norm2
= path_as_key( absolute2
);
361 OBJECT
* base1
= get_filename( file1
);
362 OBJECT
* base2
= get_filename( file2
);
363 OBJECT
* normbase1
= path_as_key( base1
);
364 OBJECT
* normbase2
= path_as_key( base2
);
365 int result
= object_equal( norm1
, norm2
) ||
366 ( object_equal( base1
, file1
) && object_equal( normbase1
, normbase2
) );
367 object_free( absolute1
);
368 object_free( absolute2
);
369 object_free( norm1
);
370 object_free( norm2
);
371 object_free( base1
);
372 object_free( base2
);
373 object_free( normbase1
);
374 object_free( normbase2
);
378 static void debug_print_source( OBJECT
* filename
, int line
)
382 if ( filename
== NULL
|| object_equal( filename
, constant_builtin
) )
385 file
= fopen( object_str( filename
), "r" );
390 int current_line
= 1;
394 printf( "%d\t", current_line
);
396 while ( ( ch
= fgetc( file
) ) != EOF
)
407 if ( current_line
== line
)
410 printf( "%d\t", current_line
);
418 static void debug_print_frame( FRAME
* frame
)
420 OBJECT
* file
= frame
->file
;
421 if ( file
== NULL
) file
= constant_builtin
;
422 printf( "%s ", frame
->rulename
);
423 if ( strcmp( frame
->rulename
, "module scope" ) != 0 )
426 if ( frame
->args
->count
)
428 lol_print( frame
->args
);
433 printf( "at %s:%d", object_str( file
), frame
->line
);
436 static void debug_mi_print_frame( FRAME
* frame
)
438 OBJECT
* fullname
= make_absolute_path( frame
->file
);
439 printf( "frame={func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}",
441 object_str( frame
->file
),
442 object_str( fullname
),
444 object_free( fullname
);
447 static void debug_print_frame_info( FRAME_INFO
* frame
)
449 OBJECT
* file
= frame
->file
;
450 if ( file
== NULL
) file
= constant_builtin
;
451 printf( "%s ", frame
->rulename
);
452 if ( strcmp( frame
->rulename
, "module scope" ) != 0 )
455 if ( frame
->args
->count
)
457 lol_print( frame
->args
);
462 printf( "at %s:%d", object_str( file
), frame
->line
);
465 static void debug_mi_print_frame_info( FRAME_INFO
* frame
)
467 printf( "frame={func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}",
469 object_str( frame
->file
),
470 object_str( frame
->fullname
),
474 static void debug_on_breakpoint( int id
)
476 fputc( DEBUG_MSG_BREAKPOINT
, command_output
);
477 debug_int_write( command_output
, id
);
478 fflush( command_output
);
482 static void debug_end_stepping( void )
484 fputc( DEBUG_MSG_END_STEPPING
, command_output
);
485 fflush( command_output
);
489 void debug_on_instruction( FRAME
* frame
, OBJECT
* file
, int line
)
492 assert( debug_is_debugging() );
493 if ( debug_state
== DEBUG_NEXT
&&
494 ( debug_depth
< 0 || ( debug_depth
== 0 && debug_line
!= line
) ) )
499 debug_end_stepping();
501 else if ( debug_state
== DEBUG_STEP
&& debug_line
!= line
)
506 debug_end_stepping();
508 else if ( debug_state
== DEBUG_FINISH
&& debug_depth
< 0 )
513 debug_end_stepping();
515 else if ( ( debug_file
== NULL
|| ! object_equal( file
, debug_file
) ||
516 line
!= debug_line
|| debug_depth
!= 0 ) &&
517 ( breakpoint_id
= handle_line_breakpoint( file
, line
) ) )
522 debug_on_breakpoint( breakpoint_id
);
524 else if ( ( debug_state
== DEBUG_RUN
|| debug_state
== DEBUG_FINISH
) &&
525 ( debug_depth
< 0 || ( debug_depth
== 0 && debug_line
!= line
) ) )
532 void debug_on_enter_function( FRAME
* frame
, OBJECT
* name
, OBJECT
* file
, int line
)
535 assert( debug_is_debugging() );
537 if ( debug_state
== DEBUG_STEP
&& file
)
542 debug_end_stepping();
544 else if ( ( breakpoint_id
= handle_function_breakpoint( name
) ) ||
545 ( breakpoint_id
= handle_line_breakpoint( file
, line
) ) )
550 debug_on_breakpoint( breakpoint_id
);
554 void debug_on_exit_function( OBJECT
* name
)
556 assert( debug_is_debugging() );
558 if ( debug_depth
< 0 )
560 /* The current location is no longer valid
561 after we return from the containing function. */
568 static HANDLE child_handle
;
569 static DWORD child_pid
;
571 static int child_pid
;
574 static void debug_child_continue( int argc
, const char * * argv
)
576 debug_state
= DEBUG_RUN
;
580 static void debug_child_step( int argc
, const char * * argv
)
582 debug_state
= DEBUG_STEP
;
586 static void debug_child_next( int argc
, const char * * argv
)
588 debug_state
= DEBUG_NEXT
;
592 static void debug_child_finish( int argc
, const char * * argv
)
594 debug_state
= DEBUG_FINISH
;
598 static void debug_child_kill( int argc
, const char * * argv
)
603 static int debug_add_breakpoint( const char * name
)
605 const char * file_ptr
= name
;
606 const char * ptr
= strrchr( file_ptr
, ':' );
610 long line
= strtoul( ptr
+ 1, &end
, 10 );
611 if ( line
> 0 && line
<= INT_MAX
&& end
!= ptr
+ 1 && *end
== 0 )
613 OBJECT
* file
= object_new_range( file_ptr
, ptr
- file_ptr
);
614 return add_line_breakpoint( file
, line
);
618 OBJECT
* name
= object_new( file_ptr
);
619 return add_function_breakpoint( name
);
624 OBJECT
* name
= object_new( file_ptr
);
625 return add_function_breakpoint( name
);
629 static void debug_child_break( int argc
, const char * * argv
)
633 debug_add_breakpoint( argv
[ 1 ] );
637 static int get_breakpoint_by_name( const char * name
)
640 const char * file_ptr
= name
;
641 const char * ptr
= strrchr( file_ptr
, ':' );
645 long line
= strtoul( ptr
+ 1, &end
, 10 );
646 if ( line
> 0 && line
<= INT_MAX
&& end
!= ptr
+ 1 && *end
== 0 )
648 OBJECT
* file
= object_new_range( file_ptr
, ptr
- file_ptr
);
649 result
= handle_line_breakpoint( file
, line
);
654 OBJECT
* name
= object_new( file_ptr
);
655 result
= handle_function_breakpoint( name
);
661 OBJECT
* name
= object_new( file_ptr
);
662 result
= handle_function_breakpoint( name
);
668 static void debug_child_disable( int argc
, const char * * argv
)
672 int id
= atoi( argv
[ 1 ] );
673 if ( id
< 1 || id
> num_breakpoints
)
676 if ( breakpoints
[ id
].status
== BREAKPOINT_DELETED
)
678 breakpoints
[ id
].status
= BREAKPOINT_DISABLED
;
682 static void debug_child_enable( int argc
, const char * * argv
)
686 int id
= atoi( argv
[ 1 ] );
687 if ( id
< 1 || id
> num_breakpoints
)
690 if ( breakpoints
[ id
].status
== BREAKPOINT_DELETED
)
692 breakpoints
[ id
].status
= BREAKPOINT_ENABLED
;
696 static void debug_child_delete( int argc
, const char * * argv
)
700 int id
= atoi( argv
[ 1 ] );
701 if ( id
< 1 || id
> num_breakpoints
)
704 breakpoints
[ id
].status
= BREAKPOINT_DELETED
;
708 static void debug_child_print( int argc
, const char * * argv
)
714 const char * lines
[ 2 ];
716 FRAME new_frame
= *debug_frame
;
717 /* Save the current file/line, since running parse_string
718 * will likely change it.
720 saved_frame
= debug_frame
;
721 saved_file
= debug_file
;
722 saved_line
= debug_line
;
724 string_append( buf
, "__DEBUG_PRINT_HELPER__" );
725 for ( i
= 1; i
< argc
; ++i
)
727 string_push_back( buf
, ' ' );
728 string_append( buf
, argv
[ i
] );
730 string_append( buf
, " ;\n" );
731 lines
[ 0 ] = buf
->value
;
733 parse_string( constant_builtin
, lines
, &new_frame
);
735 debug_list_write( command_output
, debug_print_result
);
736 fflush( command_output
);
737 debug_frame
= saved_frame
;
738 debug_file
= saved_file
;
739 debug_line
= saved_line
;
742 static void debug_child_frame( int argc
, const char * * argv
)
746 debug_selected_frame_number
= atoi( argv
[ 1 ] );
750 assert( !"Wrong number of arguments to frame." );
754 static void debug_child_info( int argc
, const char * * argv
)
756 if ( strcmp( argv
[ 1 ], "locals" ) == 0 )
759 if ( debug_frame
->function
)
761 locals
= function_get_variables( (FUNCTION
*)debug_frame
->function
);
763 debug_list_write( command_output
, locals
);
764 fflush( command_output
);
767 else if ( strcmp( argv
[ 1 ], "frame" ) == 0 )
769 int frame_number
= debug_selected_frame_number
;
772 FRAME base
= *debug_frame
;
773 FRAME
* frame
= &base
;
774 base
.file
= debug_file
;
775 base
.line
= debug_line
;
776 if ( argc
== 3 ) frame_number
= atoi( argv
[ 2 ] );
778 for ( i
= 0; i
< frame_number
; ++i
) frame
= frame
->prev
;
780 debug_frame_write( command_output
, frame
);
782 else if ( strcmp( argv
[ 1 ], "depth" ) == 0 )
785 FRAME
* frame
= debug_frame
;
791 fprintf( command_output
, "%d", result
);
792 fputc( '\0', command_output
);
793 fflush( command_output
);
797 /* Commands for the parent. */
801 static int get_module_filename( string
* out
)
804 string_reserve( out
, 256 + 1 );
805 string_truncate( out
, 256 );
806 while( ( result
= GetModuleFileName( NULL
, out
->value
, out
->size
) ) == out
->size
)
808 string_reserve( out
, out
->size
* 2 + 1);
809 string_truncate( out
, out
->size
* 2 );
813 string_truncate( out
, result
);
824 static struct command_elem child_commands
[] =
826 { "continue", &debug_child_continue
},
827 { "kill", &debug_child_kill
},
828 { "step", &debug_child_step
},
829 { "next", &debug_child_next
},
830 { "finish", &debug_child_finish
},
831 { "break", &debug_child_break
},
832 { "disable", &debug_child_disable
},
833 { "enable", &debug_child_enable
},
834 { "delete", &debug_child_delete
},
835 { "print", &debug_child_print
},
836 { "frame", &debug_child_frame
},
837 { "info", &debug_child_info
},
841 static void debug_mi_error( const char * message
)
843 debug_mi_format_token();
844 printf( "^error,msg=\"%s\"\n(gdb) \n", message
);
847 static void debug_error_( const char * message
)
849 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
851 printf( "%s\n", message
);
853 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
855 debug_mi_error( message
);
859 static const char * debug_format_message( const char * format
, va_list vargs
)
867 buf
= (char *)malloc( sz
);
873 va_copy( args
, vargs
);
875 #if defined(_MSC_VER) && (_MSC_VER <= 1310)
876 result
= _vsnprintf( buf
, sz
, format
, args
);
878 result
= vsnprintf( buf
, sz
, format
, args
);
881 if ( 0 <= result
&& result
< sz
)
890 static void debug_error( const char * format
, ... )
894 va_start( args
, format
);
895 msg
= debug_format_message( format
, args
);
899 debug_error_( "Failed formatting error message." );
903 free( ( void * )msg
);
906 static void debug_parent_child_exited( int pid
, int exit_code
)
908 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
910 printf( "Child %d exited with status %d\n", (int)child_pid
, (int)exit_code
);
912 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
914 if ( exit_code
== 0 )
915 printf( "*stopped,reason=\"exited-normally\"\n(gdb) \n" );
917 printf( "*stopped,reason=\"exited\",exit-code=\"%d\"\n(gdb) \n", exit_code
);
921 assert( !"Wrong value of debug_interface." );
925 static void debug_parent_child_signalled( int pid
, int sigid
)
928 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
930 printf( "Child %d exited on signal %d\n", child_pid
, sigid
);
932 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
934 const char * name
= "unknown";
935 const char * meaning
= "unknown";
938 case SIGINT
: name
= "SIGINT"; meaning
= "Interrupt"; break;
940 printf("*stopped,reason=\"exited-signalled\",signal-name=\"%s\",signal-meaning=\"%s\"\n(gdb) \n", name
, meaning
);
944 assert( !"Wrong value of debug_interface." );
948 static void debug_parent_on_breakpoint( void )
952 id
= debug_int_read( command_child
);
953 fprintf( command_output
, "info frame\n" );
954 fflush( command_output
);
955 debug_frame_read( command_child
, &base
);
956 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
958 printf( "Breakpoint %d, ", id
);
959 debug_print_frame_info( &base
);
961 debug_print_source( base
.file
, base
.line
);
963 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
965 printf( "*stopped,reason=\"breakpoint-hit\",bkptno=\"%d\",disp=\"keep\",", id
);
966 debug_mi_print_frame_info( &base
);
967 printf( ",thread-id=\"1\",stopped-threads=\"all\"" );
968 printf( "\n(gdb) \n" );
972 assert( !"Wrong value if debug_interface" );
977 static void debug_parent_on_end_stepping( void )
980 fprintf( command_output
, "info frame\n" );
981 fflush( command_output
);
982 debug_frame_read( command_child
, &base
);
983 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
985 debug_print_source( base
.file
, base
.line
);
989 printf( "*stopped,reason=\"end-stepping-range\"," );
990 debug_mi_print_frame_info( &base
);
991 printf( ",thread-id=\"1\"" );
992 printf( "\n(gdb) \n" );
997 /* Waits for events from the child. */
998 static void debug_parent_wait( int print_message
)
1000 int ch
= fgetc( command_child
);
1001 if ( ch
== DEBUG_MSG_BREAKPOINT
)
1003 debug_parent_on_breakpoint();
1005 else if ( ch
== DEBUG_MSG_END_STEPPING
)
1007 debug_parent_on_end_stepping();
1009 else if ( ch
== DEBUG_MSG_SETUP
)
1011 /* FIXME: This is handled in the caller, but it would make
1012 more sense to handle it here. */
1015 else if ( ch
== EOF
)
1018 WaitForSingleObject( child_handle
, INFINITE
);
1019 if ( print_message
)
1022 GetExitCodeProcess( child_handle
, &exit_code
);
1023 debug_parent_child_exited( (int)child_pid
, (int)exit_code
);
1025 CloseHandle( child_handle
);
1029 while ( ( pid
= waitpid( child_pid
, &status
, 0 ) ) == -1 )
1030 if ( errno
!= EINTR
)
1032 if ( print_message
)
1034 if ( WIFEXITED( status
) )
1035 debug_parent_child_exited( child_pid
, WEXITSTATUS( status
) );
1036 else if ( WIFSIGNALED( status
) )
1037 debug_parent_child_signalled( child_pid
, WTERMSIG( status
) );
1040 fclose( command_child
);
1041 fclose( command_output
);
1042 debug_state
= DEBUG_NO_CHILD
;
1046 /* Prints the message for starting the child. */
1047 static void debug_parent_run_print( int argc
, const char * * argv
)
1050 extern char const * saved_argv0
;
1051 char * name
= executable_path( saved_argv0
);
1052 printf( "Starting program: %s", name
);
1054 for ( i
= 1; i
< argc
; ++i
)
1056 printf( " %s", argv
[ i
] );
1064 void debug_init_handles( const char * in
, const char * out
)
1068 HANDLE write_handle
;
1071 sscanf( in
, "%p", &read_handle
);
1072 read_fd
= _open_osfhandle( (intptr_t)read_handle
, _O_RDONLY
);
1073 command_input
= _fdopen( read_fd
, "r" );
1075 sscanf( out
, "%p", &write_handle
);
1076 write_fd
= _open_osfhandle( (intptr_t)write_handle
, _O_WRONLY
);
1077 command_output
= _fdopen( write_fd
, "w" );
1079 command_array
= child_commands
;
1081 /* Handle the initial setup */
1082 /* wake up the parent */
1083 fputc( DEBUG_MSG_SETUP
, command_output
);
1087 static void init_parent_handles( HANDLE out
, HANDLE in
)
1089 int read_fd
, write_fd
;
1091 command_child
= _fdopen( _open_osfhandle( (intptr_t)in
, _O_RDONLY
), "r" );
1092 command_output
= _fdopen( _open_osfhandle( (intptr_t)out
, _O_WRONLY
), "w" );
1095 static void debug_parent_copy_breakpoints( void )
1098 for ( i
= 0; i
< num_breakpoints
; ++i
)
1100 fprintf( command_output
, "break %s", object_str( breakpoints
[ i
].file
) );
1101 if ( breakpoints
[ i
].line
!= -1 )
1103 fprintf( command_output
, ":%d", breakpoints
[ i
].line
);
1105 fprintf( command_output
, "\n" );
1107 switch ( breakpoints
[ i
].status
)
1109 case BREAKPOINT_ENABLED
:
1111 case BREAKPOINT_DISABLED
:
1112 fprintf( command_output
, "disable %d\n", i
+ 1 );
1114 case BREAKPOINT_DELETED
:
1115 fprintf( command_output
, "delete %d\n", i
+ 1 );
1118 assert( !"Wrong breakpoint status." );
1121 fflush( command_output
);
1126 static void debug_start_child( int argc
, const char * * argv
)
1133 string command_line
[ 1 ];
1134 SECURITY_ATTRIBUTES sa
= { sizeof( SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1135 PROCESS_INFORMATION pi
= { NULL
, NULL
, 0, 0 };
1136 STARTUPINFO si
= { sizeof( STARTUPINFO
), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1138 assert( debug_state
== DEBUG_NO_CHILD
);
1139 if ( ! CreatePipe( &pipe1
[ 0 ], &pipe1
[ 1 ], &sa
, 0 ) )
1141 printf("internal error: CreatePipe:1: 0x$08x\n", GetLastError());
1144 if ( ! CreatePipe( &pipe2
[ 0 ], &pipe2
[ 1 ], &sa
, 0 ) )
1146 printf("internal error: CreatePipe:2: 0x$08x\n", GetLastError());
1147 CloseHandle( pipe1
[ 0 ] );
1148 CloseHandle( pipe1
[ 1 ] );
1152 if ( ! get_module_filename( self
) )
1154 printf("internal error\n");
1155 CloseHandle( pipe1
[ 0 ] );
1156 CloseHandle( pipe1
[ 1 ] );
1157 CloseHandle( pipe2
[ 0 ] );
1158 CloseHandle( pipe2
[ 1 ] );
1161 string_copy( command_line
, "b2 " );
1162 /* Pass the handles as the first and second arguments. */
1163 string_append( command_line
, debugger_opt
);
1164 sprintf( buf
, "%p", pipe1
[ 0 ] );
1165 string_append( command_line
, buf
);
1166 string_push_back( command_line
, ' ' );
1167 string_append( command_line
, debugger_opt
);
1168 sprintf( buf
, "%p", pipe2
[ 1 ] );
1169 string_append( command_line
, buf
);
1170 /* Pass the rest of the command line. */
1173 for ( i
= 1; i
< argc
; ++i
)
1175 string_push_back( command_line
, ' ' );
1176 string_append( command_line
, argv
[ i
] );
1179 SetHandleInformation( pipe1
[ 1 ], HANDLE_FLAG_INHERIT
, 0 );
1180 SetHandleInformation( pipe2
[ 0 ], HANDLE_FLAG_INHERIT
, 0 );
1181 if ( ! CreateProcess(
1183 command_line
->value
,
1194 printf("internal error\n");
1195 CloseHandle( pipe1
[ 0 ] );
1196 CloseHandle( pipe1
[ 1 ] );
1197 CloseHandle( pipe2
[ 0 ] );
1198 CloseHandle( pipe2
[ 1 ] );
1199 string_free( self
);
1200 string_free( command_line
);
1203 child_pid
= pi
.dwProcessId
;
1204 child_handle
= pi
.hProcess
;
1205 CloseHandle( pi
.hThread
);
1206 CloseHandle( pipe1
[ 0 ] );
1207 CloseHandle( pipe2
[ 1 ] );
1208 string_free( self
);
1209 string_free( command_line
);
1211 debug_state
= DEBUG_RUN
;
1213 init_parent_handles( pipe1
[ 1 ], pipe2
[ 0 ] );
1214 debug_parent_wait( 1 );
1215 debug_parent_copy_breakpoints();
1216 fprintf( command_output
, "continue\n" );
1217 fflush( command_output
);
1225 assert( debug_state
== DEBUG_NO_CHILD
);
1226 if (pipe(pipe1
) == -1)
1228 printf("internal error: pipe:1: %s\n", strerror(errno
));
1231 if (pipe(pipe2
) == -1)
1233 close( pipe1
[ 0 ] );
1234 close( pipe1
[ 1 ] );
1235 printf("internal error: pipe:2: %s\n", strerror(errno
));
1243 close( pipe1
[ 0 ] );
1244 close( pipe1
[ 1 ] );
1245 close( pipe2
[ 0 ] );
1246 close( pipe2
[ 1 ] );
1247 printf("internal error: fork: %s\n", strerror(errno
));
1250 else if ( pid
== 0 )
1253 extern const char * saved_argv0
;
1254 read_fd
= pipe1
[ 0 ];
1255 write_fd
= pipe2
[ 1 ];
1256 close( pipe2
[ 0 ] );
1257 close( pipe1
[ 1 ] );
1258 command_array
= child_commands
;
1259 argv
[ 0 ] = executable_path( saved_argv0
);
1260 debug_child_data
.argc
= argc
;
1261 debug_child_data
.argv
= argv
;
1262 command_input
= fdopen( read_fd
, "r" );
1263 command_output
= fdopen( write_fd
, "w" );
1264 longjmp( debug_child_data
.jmp
, 1 );
1269 read_fd
= pipe2
[ 0 ];
1270 write_fd
= pipe1
[ 1 ];
1271 close( pipe1
[ 0 ] );
1272 close( pipe2
[ 1 ] );
1273 command_output
= fdopen( write_fd
, "w" );
1274 command_child
= fdopen( read_fd
, "r" );
1277 debug_state
= DEBUG_RUN
;
1281 static void debug_parent_run( int argc
, const char * * argv
)
1283 if ( debug_state
== DEBUG_RUN
)
1285 fprintf( command_output
, "kill\n" );
1286 fflush( command_output
);
1287 debug_parent_wait( 1 );
1289 debug_parent_run_print( argc
, argv
);
1290 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1292 printf( "=thread-created,id=\"1\",group-id=\"i1\"\n" );
1293 debug_mi_format_token();
1294 printf( "^running\n(gdb) \n" );
1296 debug_start_child( argc
, argv
);
1297 debug_parent_wait( 1 );
1300 static int debug_parent_forward_nowait( int argc
, const char * * argv
, int print_message
, int require_child
)
1303 if ( debug_state
== DEBUG_NO_CHILD
)
1305 if ( require_child
)
1306 printf( "The program is not being run.\n" );
1309 fputs( argv
[ 0 ], command_output
);
1310 for( i
= 1; i
< argc
; ++i
)
1312 fputc( ' ', command_output
);
1313 fputs( argv
[ i
], command_output
);
1315 fputc( '\n', command_output
);
1316 fflush( command_output
);
1320 /* FIXME: This function should be eliminated when I finish all stdout to the parent. */
1321 static void debug_parent_forward( int argc
, const char * * argv
, int print_message
, int require_child
)
1323 if ( debug_parent_forward_nowait( argc
, argv
, print_message
, require_child
) != 0 )
1327 debug_parent_wait( print_message
);
1330 static void debug_parent_continue( int argc
, const char * * argv
)
1334 debug_error( "Too many arguments to continue." );
1337 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1339 debug_mi_format_token();
1340 printf( "^running\n(gdb) \n" );
1343 debug_parent_forward( 1, argv
, 1, 1 );
1346 static void debug_parent_kill( int argc
, const char * * argv
)
1350 debug_error( "Too many arguments to kill." );
1353 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1355 debug_mi_format_token();
1356 printf( "^done\n(gdb) \n" );
1359 debug_parent_forward( 1, argv
, 0, 1 );
1362 static void debug_parent_step( int argc
, const char * * argv
)
1366 debug_error( "Too many arguments to step." );
1369 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1371 debug_mi_format_token();
1372 printf( "^running\n(gdb) \n" );
1375 debug_parent_forward( 1, argv
, 1, 1 );
1378 static void debug_parent_next( int argc
, const char * * argv
)
1382 debug_error( "Too many arguments to next." );
1385 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1387 debug_mi_format_token();
1388 printf( "^running\n(gdb) \n" );
1391 debug_parent_forward( 1, argv
, 1, 1 );
1394 static void debug_parent_finish( int argc
, const char * * argv
)
1398 debug_error( "Too many arguments to finish." );
1401 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1403 debug_mi_format_token();
1404 printf( "^running\n(gdb) \n" );
1407 debug_parent_forward( 1, argv
, 1, 1 );
1410 static void debug_parent_break( int argc
, const char * * argv
)
1415 debug_error( "Missing argument to break." );
1418 else if ( argc
> 2 )
1420 debug_error( "Too many arguments to break." );
1423 id
= debug_add_breakpoint( argv
[ 1 ] );
1424 debug_parent_forward_nowait( argc
, argv
, 1, 0 );
1425 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
1427 printf( "Breakpoint %d set at %s\n", id
, argv
[ 1 ] );
1429 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
1431 debug_mi_format_token();
1432 printf( "^done\n(gdb) \n" );
1436 assert( !"wrong value of debug_interface." );
1440 int check_breakpoint_fn_args( int argc
, const char * * argv
)
1444 debug_error( "Missing argument to %s.", argv
[ 0 ] );
1447 else if ( argc
> 2 )
1449 debug_error( "Too many arguments to %s.", argv
[ 0 ] );
1455 long x
= strtol( argv
[ 1 ], &end
, 10 );
1458 debug_error( "Invalid breakpoint number %s.", argv
[ 1 ] );
1461 if ( x
< 1 || x
> num_breakpoints
|| breakpoints
[ x
- 1 ].status
== BREAKPOINT_DELETED
)
1463 debug_error( "Unknown breakpoint %s.", argv
[ 1 ] );
1470 static void debug_parent_disable( int argc
, const char * * argv
)
1472 if ( ! check_breakpoint_fn_args( argc
, argv
) )
1476 debug_child_disable( argc
, argv
);
1477 debug_parent_forward_nowait( 2, argv
, 1, 0 );
1478 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1480 debug_mi_format_token();
1481 printf( "^done\n(gdb) \n" );
1485 static void debug_parent_enable( int argc
, const char * * argv
)
1487 if ( ! check_breakpoint_fn_args( argc
, argv
) )
1491 debug_child_enable( argc
, argv
);
1492 debug_parent_forward_nowait( 2, argv
, 1, 0 );
1493 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1495 debug_mi_format_token();
1496 printf( "^done\n(gdb) \n" );
1500 static void debug_parent_delete( int argc
, const char * * argv
)
1502 if ( ! check_breakpoint_fn_args( argc
, argv
) )
1506 debug_child_delete( argc
, argv
);
1507 debug_parent_forward_nowait( 2, argv
, 1, 0 );
1508 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1510 debug_mi_format_token();
1511 printf( "^done\n(gdb) \n" );
1515 static void debug_parent_clear( int argc
, const char * * argv
)
1518 const char * new_args
[ 2 ];
1522 debug_error( "Missing argument to clear." );
1525 else if ( argc
> 2 )
1527 debug_error( "Too many arguments to clear." );
1530 id
= get_breakpoint_by_name( argv
[ 1 ] );
1533 debug_error( "No breakpoint at %s.", argv
[ 1 ] );
1537 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
1539 printf( "Deleted breakpoint %d\n", id
);
1542 sprintf( buf
, "%d", id
);
1543 new_args
[ 0 ] = "delete";
1544 new_args
[ 1 ] = buf
;
1545 debug_parent_delete( 2, new_args
);
1548 static void debug_parent_print( int argc
, const char * * argv
)
1551 if ( debug_parent_forward_nowait( argc
, argv
, 1, 1 ) != 0 )
1555 result
= debug_list_read( command_child
);
1557 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
1559 list_print( result
);
1562 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
1564 printf( "~\"$1 = " );
1565 list_print( result
);
1566 printf( "\"\n~\"\\n\"\n" );
1567 debug_mi_format_token();
1568 printf( "^done\n(gdb) \n" );
1571 list_free( result
);
1574 static void debug_parent_backtrace( int argc
, const char * * argv
)
1576 const char * new_args
[ 3 ];
1582 if ( debug_state
== DEBUG_NO_CHILD
)
1584 debug_error( "The program is not being run." );
1588 new_args
[ 0 ] = "info";
1589 new_args
[ 1 ] = "frame";
1591 fprintf( command_output
, "info depth\n" );
1592 fflush( command_output
);
1593 depth_str
= debug_object_read( command_child
);
1594 depth
= atoi( object_str( depth_str
) );
1595 object_free( depth_str
);
1597 for ( i
= 0; i
< depth
; ++i
)
1600 sprintf( buf
, "%d", i
);
1601 new_args
[ 2 ] = buf
;
1602 debug_parent_forward_nowait( 3, new_args
, 0, 0 );
1603 debug_frame_read( command_child
, &frame
);
1604 printf( "#%d in ", i
);
1605 debug_print_frame_info( &frame
);
1611 static void debug_parent_quit( int argc
, const char * * argv
)
1613 if ( debug_state
== DEBUG_RUN
)
1615 fprintf( command_output
, "kill\n" );
1616 fflush( command_output
);
1617 debug_parent_wait( 0 );
1622 static const char * const help_text
[][2] =
1627 "Creates a new b2 child process passing <args> on the command line."
1628 " Terminates\nthe current child (if any).\n"
1632 "continue\nContinue debugging\n"
1636 "step\nContinue to the next statement\n"
1640 "next\nContinue to the next line in the current frame\n"
1644 "finish\nContinue to the end of the current frame\n"
1648 "break <location>\n"
1649 "Sets a breakpoint at <location>. <location> can be either a the name of a\nfunction or <filename>:<lineno>\n"
1653 "disable <breakpoint>\nDisable a breakpoint\n"
1657 "enable <breakpoint>\nEnable a breakpoint\n"
1661 "delete <breakpoint>\nDelete a breakpoint\n"
1665 "clear <location>\nDelete the breakpoint at <location>\n"
1669 "print <expression>\nDisplay the value of <expression>\n"
1673 "backtrace\nDisplay the call stack\n"
1677 "kill\nTerminate the child\n"
1681 "quit\nExit the debugger\n"
1685 "help\nhelp <command>\nShow help for debugger commands.\n"
1690 static void debug_parent_help( int argc
, const char * * argv
)
1695 "run - Start debugging\n"
1696 "continue - Continue debugging\n"
1697 "step - Continue to the next statement\n"
1698 "next - Continue to the next line in the current frame\n"
1699 "finish - Continue to the end of the current frame\n"
1700 "break - Set a breakpoint\n"
1701 "disable - Disable a breakpoint\n"
1702 "enable - Enable a breakpoint\n"
1703 "delete - Delete a breakpoint\n"
1704 "clear - Delete a breakpoint by location\n"
1707 "print - Display an expression\n"
1708 "backtrace - Display the call stack\n"
1709 "kill - Terminate the child\n"
1710 "quit - Exit the debugger\n"
1711 "help - Debugger help\n"
1714 else if ( argc
== 2 )
1717 for ( i
= 0; help_text
[ i
][ 0 ]; ++i
)
1719 if ( strcmp( argv
[ 1 ], help_text
[ i
][ 0 ] ) == 0 )
1721 printf( "%s", help_text
[ i
][ 1 ] );
1725 printf( "No command named %s\n", argv
[ 1 ] );
1729 static void debug_mi_break_insert( int argc
, const char * * argv
);
1730 static void debug_mi_break_delete( int argc
, const char * * argv
);
1731 static void debug_mi_break_disable( int argc
, const char * * argv
);
1732 static void debug_mi_break_enable( int argc
, const char * * argv
);
1733 static void debug_mi_break_info( int argc
, const char * * argv
);
1734 static void debug_mi_break_list( int argc
, const char * * argv
);
1735 static void debug_mi_inferior_tty_set( int argc
, const char * * argv
);
1736 static void debug_mi_gdb_exit( int argc
, const char * * argv
);
1737 static void debug_mi_gdb_set( int argc
, const char * * argv
);
1738 static void debug_mi_gdb_show( int argc
, const char * * argv
);
1739 static void debug_mi_not_implemented( int argc
, const char * * argv
);
1740 static void debug_mi_file_list_exec_source_files( int argc
, const char * * argv
);
1741 static void debug_mi_file_list_exec_source_file( int argc
, const char * * argv
);
1742 static void debug_mi_thread_info( int argc
, const char * * argv
);
1743 static void debug_mi_thread_select( int argc
, const char * * argv
);
1744 static void debug_mi_stack_info_frame( int argc
, const char * * argv
);
1745 static void debug_mi_stack_select_frame( int argc
, const char * * argv
);
1746 static void debug_mi_stack_list_variables( int argc
, const char * * argv
);
1747 static void debug_mi_stack_list_locals( int argc
, const char * * argv
);
1748 static void debug_mi_stack_list_frames( int argc
, const char * * argv
);
1749 static void debug_mi_list_target_features( int argc
, const char * * argv
);
1750 static void debug_mi_exec_run( int argc
, const char * * argv
);
1751 static void debug_mi_exec_continue( int argc
, const char * * argv
);
1752 static void debug_mi_exec_step( int argc
, const char * * argv
);
1753 static void debug_mi_exec_next( int argc
, const char * * argv
);
1754 static void debug_mi_exec_finish( int argc
, const char * * argv
);
1755 static void debug_mi_data_list_register_names( int argc
, const char * * argv
);
1756 static void debug_mi_data_evaluate_expression( int argc
, const char * * argv
);
1757 static void debug_mi_interpreter_exec( int argc
, const char * * argv
);
1759 static struct command_elem parent_commands
[] =
1761 { "run", &debug_parent_run
},
1762 { "continue", &debug_parent_continue
},
1763 { "kill", &debug_parent_kill
},
1764 { "step", &debug_parent_step
},
1765 { "next", &debug_parent_next
},
1766 { "finish", &debug_parent_finish
},
1767 { "break", &debug_parent_break
},
1768 { "disable", &debug_parent_disable
},
1769 { "enable", &debug_parent_enable
},
1770 { "delete", &debug_parent_delete
},
1771 { "clear", &debug_parent_clear
},
1772 { "print", &debug_parent_print
},
1773 { "backtrace", &debug_parent_backtrace
},
1774 { "quit", &debug_parent_quit
},
1775 { "help", &debug_parent_help
},
1776 { "-break-insert", &debug_mi_break_insert
},
1777 { "-break-delete", &debug_mi_break_delete
},
1778 { "-break-disable", &debug_mi_break_disable
},
1779 { "-break-enable", &debug_mi_break_enable
},
1780 { "-break-info", &debug_mi_break_info
},
1781 { "-break-list", &debug_mi_break_list
},
1782 { "-inferior-tty-set", &debug_mi_inferior_tty_set
},
1783 { "-gdb-exit", &debug_mi_gdb_exit
},
1784 { "-gdb-set", &debug_mi_gdb_set
},
1785 { "-gdb-show", &debug_mi_gdb_show
},
1786 { "-enable-pretty-printing", &debug_mi_not_implemented
},
1787 { "-file-list-exec-source-files", &debug_mi_file_list_exec_source_files
},
1788 { "-file-list-exec-source-file", &debug_mi_file_list_exec_source_file
},
1789 { "-thread-info", &debug_mi_thread_info
},
1790 { "-thread-select", &debug_mi_thread_select
},
1791 { "-stack-info-frame", &debug_mi_stack_info_frame
},
1792 { "-stack-select-frame", &debug_mi_stack_select_frame
},
1793 { "-stack-list-variables", &debug_mi_stack_list_variables
},
1794 { "-stack-list-locals", &debug_mi_stack_list_locals
},
1795 { "-stack-list-frames", &debug_mi_stack_list_frames
},
1796 { "-list-target-features", &debug_mi_list_target_features
},
1797 { "-exec-run", &debug_mi_exec_run
},
1798 { "-exec-continue", &debug_mi_exec_continue
},
1799 { "-exec-step", &debug_mi_exec_step
},
1800 { "-exec-next", &debug_mi_exec_next
},
1801 { "-exec-finish", &debug_mi_exec_finish
},
1802 { "-data-list-register-names", &debug_mi_data_list_register_names
},
1803 { "-data-evaluate-expression", &debug_mi_data_evaluate_expression
},
1804 { "-interpreter-exec", &debug_mi_interpreter_exec
},
1808 static void debug_mi_format_token( void )
1810 if ( current_token
!= 0 )
1812 printf( "%d", current_token
);
1816 static void debug_mi_format_breakpoint( int id
)
1818 struct breakpoint
* ptr
= &breakpoints
[ id
- 1 ];
1820 printf( "number=\"%d\"", id
);
1821 printf( ",type=\"breakpoint\"" );
1822 printf( ",disp=\"keep\"" ); /* FIXME: support temporary breakpoints. */
1823 printf( ",enabled=\"%s\"", ptr
->status
== BREAKPOINT_ENABLED
? "y" : "n" );
1825 if ( ptr
->line
== -1 )
1827 printf( ",func=\"%s\"", object_str( ptr
->file
) );
1831 printf( ",file=\"%s\"", object_str( ptr
->file
) );
1832 printf( ",line=\"%d\"", ptr
->line
);
1833 printf( ",fullname=\"%s\"", object_str( ptr
->file
) );
1841 static int breakpoint_id_parse( const char * name
)
1843 int id
= atoi( name
);
1844 if ( id
> num_breakpoints
|| id
< 1 || breakpoints
[ id
].status
== BREAKPOINT_DELETED
)
1849 static void debug_mi_break_after( int argc
, const char * * argv
)
1855 if ( argc
> 0 && strcmp( argv
[ 0 ], "--" ) == 0 )
1862 debug_mi_error( "not enough arguments for -break-after." );
1865 else if ( argc
> 2 )
1867 debug_mi_error( "too many arguments for -break-after." );
1870 id
= atoi( argv
[ 0 ] );
1871 count
= atoi( argv
[ 1 ] );
1872 /* FIXME: set ignore count */
1875 static void debug_mi_break_insert( int argc
, const char * * argv
)
1877 const char * inner_argv
[ 2 ];
1878 int temporary
= 0; /* FIXME: not supported yet */
1879 int hardware
= 0; /* unsupported */
1880 int force
= 1; /* We don't have global debug information... */
1882 int tracepoint
= 0; /* unsupported */
1884 int ignore_count
= 0;
1885 const char * condition
; /* FIXME: not supported yet */
1886 const char * location
;
1888 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
1890 if ( strcmp( *argv
, "-t" ) == 0 )
1894 else if ( strcmp( *argv
, "-h" ) == 0 )
1898 else if ( strcmp( *argv
, "-f" ) == 0 )
1902 else if ( strcmp( *argv
, "-d" ) == 0 )
1906 else if ( strcmp( *argv
, "-a" ) == 0 )
1910 else if ( strcmp( *argv
, "-c" ) == 0 )
1914 debug_mi_error( "Missing argument for -c." );
1918 condition
= argv
[ 1 ];
1922 else if ( strcmp( *argv
, "-i" ) == 0 )
1926 debug_mi_error( "Missing argument for -i." );
1930 ignore_count
= atoi( argv
[ 1 ] );
1934 else if ( strcmp( *argv
, "-p" ) == 0 )
1938 debug_mi_error( "Missing argument for -p." );
1942 thread_id
= atoi( argv
[ 1 ] );
1946 else if ( strcmp( *argv
, "--" ) == 0 )
1952 else if ( **argv
!= '-' )
1958 debug_mi_error( "Unknown argument." );
1964 debug_mi_error( "Too many arguments for -break-insert." );
1974 debug_mi_error( "Not implemented: -break-insert with no location." );
1977 inner_argv
[ 0 ] = "break";
1978 inner_argv
[ 1 ] = location
;
1980 id
= debug_add_breakpoint( location
);
1981 debug_parent_forward_nowait( 2, inner_argv
, 1, 0 );
1986 sprintf( buf
, "%d", num_breakpoints
);
1987 inner_argv
[ 0 ] = "disable";
1988 inner_argv
[ 1 ] = buf
;
1989 debug_child_disable( 2, inner_argv
);
1990 debug_parent_forward_nowait( 2, inner_argv
, 1, 0 );
1993 debug_mi_format_token();
1995 debug_mi_format_breakpoint( id
);
1996 printf( "\n(gdb) \n" );
1999 static void debug_mi_break_delete( int argc
, const char * * argv
)
2003 debug_mi_error( "Not enough arguments for -break-delete" );
2006 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
2008 const char * inner_argv
[ 2 ];
2009 int id
= breakpoint_id_parse( *argv
);
2012 debug_mi_error( "Not a valid breakpoint" );
2015 inner_argv
[ 0 ] = "delete";
2016 inner_argv
[ 1 ] = *argv
;
2017 debug_parent_delete( 2, inner_argv
);
2021 static void debug_mi_break_enable( int argc
, const char * * argv
)
2025 debug_mi_error( "Not enough arguments for -break-enable" );
2028 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
2030 const char * inner_argv
[ 2 ];
2031 int id
= breakpoint_id_parse( *argv
);
2034 debug_mi_error( "Not a valid breakpoint" );
2037 inner_argv
[ 0 ] = "enable";
2038 inner_argv
[ 1 ] = *argv
;
2039 debug_parent_enable( 2, inner_argv
);
2043 static void debug_mi_break_disable( int argc
, const char * * argv
)
2047 debug_mi_error( "Not enough arguments for -break-disable" );
2050 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
2052 const char * inner_argv
[ 2 ];
2053 int id
= breakpoint_id_parse( *argv
);
2056 debug_mi_error( "Not a valid breakpoint" );
2059 inner_argv
[ 0 ] = "disable";
2060 inner_argv
[ 1 ] = *argv
;
2061 debug_parent_disable( 2, inner_argv
);
2065 static void debug_mi_format_breakpoint_header_col( int width
, int alignment
, const char * col_name
, const char * colhdr
)
2067 printf( "{width=\"%d\",alignment=\"%d\",col_name=\"%s\",colhdr=\"%s\"}", width
, alignment
, col_name
, colhdr
);
2070 static void debug_mi_format_breakpoint_hdr( void )
2073 debug_mi_format_breakpoint_header_col( 7, -1, "number", "Num" );
2075 debug_mi_format_breakpoint_header_col( 14, -1, "type", "Type" );
2077 debug_mi_format_breakpoint_header_col( 4, -1, "disp", "Disp" );
2079 debug_mi_format_breakpoint_header_col( 3, -1, "enabled", "Enb" );
2081 debug_mi_format_breakpoint_header_col( 10, -1, "addr", "Address" );
2083 debug_mi_format_breakpoint_header_col( 40, 2, "what", "What" );
2087 static void debug_mi_break_info( int argc
, const char * * argv
)
2092 if ( strcmp( *argv
, "--" ) == 0 )
2099 debug_mi_error( "Not enough arguments for -break-info" );
2104 debug_mi_error( "Too many arguments for -break-info" );
2107 id
= breakpoint_id_parse( *argv
);
2110 debug_mi_error( "No such breakpoint." );
2114 printf( "^done,BreakpointTable={"
2115 "nr_rows=\"%d\",nr_cols=\"6\",", 1 );
2116 debug_mi_format_breakpoint_hdr();
2117 printf( ",body=[" );
2118 debug_mi_format_breakpoint( id
);
2120 printf("\n(gdb) \n");
2123 static void debug_mi_break_list( int argc
, const char * * argv
)
2128 if ( argc
> 2 || ( argc
== 2 && strcmp( argv
[ 1 ], "--" ) ) )
2130 debug_mi_error( "Too many arguments for -break-list" );
2135 for ( i
= 0; i
< num_breakpoints
; ++i
)
2136 if ( breakpoints
[ i
].status
!= BREAKPOINT_DELETED
)
2138 debug_mi_format_token();
2139 printf( "^done,BreakpointTable={"
2140 "nr_rows=\"%d\",nr_cols=\"6\",", number
);
2141 debug_mi_format_breakpoint_hdr();
2142 printf( ",body=[" );
2144 for ( i
= 0; i
< num_breakpoints
; ++i
)
2145 if ( breakpoints
[ i
].status
!= BREAKPOINT_DELETED
)
2147 if ( first
) first
= 0;
2149 debug_mi_format_breakpoint( i
+ 1 );
2152 printf("\n(gdb) \n");
2155 static void debug_mi_inferior_tty_set( int argc
, const char * * argv
)
2157 /* FIXME: implement this for real */
2158 debug_mi_format_token();
2159 printf( "^done\n(gdb) \n" );
2162 static void debug_mi_gdb_exit( int argc
, const char * * argv
)
2164 if ( debug_state
== DEBUG_RUN
)
2166 fprintf( command_output
, "kill\n" );
2167 fflush( command_output
);
2168 debug_parent_wait( 0 );
2170 debug_mi_format_token();
2171 printf( "^exit\n" );
2172 exit( EXIT_SUCCESS
);
2175 static void debug_mi_gdb_set( int argc
, const char * * argv
)
2177 /* FIXME: implement this for real */
2178 debug_mi_format_token();
2179 printf( "^done\n(gdb) \n" );
2182 static void debug_mi_gdb_show( int argc
, const char * * argv
)
2184 const char * value
= "";
2185 /* FIXME: implement this for real */
2186 debug_mi_format_token();
2188 printf( "^done,value=\"%s\"\n(gdb) \n", value
);
2191 static void debug_mi_not_implemented( int argc
, const char * * argv
)
2193 /* FIXME: implement this for real */
2194 debug_mi_format_token();
2195 printf( "^done\n(gdb) \n" );
2198 void debug_mi_file_list_exec_source_files( int argc
, const char * * argv
)
2200 /* FIXME: implement this for real */
2201 debug_mi_format_token();
2202 printf( "^done,files=[]\n(gdb) \n" );
2205 static void debug_mi_file_list_exec_source_file( int argc
, const char * * argv
)
2207 /* FIXME: implement this for real */
2208 debug_mi_format_token();
2209 printf( "^error,msg=\"Don't know how to handle this yet\"\n(gdb) \n" );
2212 static void debug_mi_thread_info( int argc
, const char * * argv
)
2214 if ( debug_state
== DEBUG_NO_CHILD
)
2216 debug_mi_format_token();
2217 printf( "^done,threads=[]\n(gdb) \n" );
2221 const char * new_args
[] = { "info", "frame" };
2223 debug_parent_forward_nowait( 2, new_args
, 0, 0 );
2224 debug_frame_read( command_child
, &info
);
2226 debug_mi_format_token();
2227 printf( "^done,threads=[{id=\"1\"," );
2228 debug_mi_print_frame_info( &info
);
2229 debug_frame_info_free( &info
);
2230 printf( "}],current-thread-id=\"1\"\n(gdb) \n" );
2234 static void debug_mi_thread_select( int argc
, const char * * argv
)
2236 if ( debug_state
== DEBUG_NO_CHILD
)
2238 /* FIXME: better error handling*/
2239 debug_mi_format_token();
2240 printf( "^error,msg=\"Thread ID 1 not known\"\n(gdb) \n" );
2244 const char * new_args
[] = { "info", "frame" };
2246 debug_parent_forward_nowait( 2, new_args
, 0, 0 );
2247 debug_frame_read( command_child
, &info
);
2249 debug_mi_format_token();
2250 printf( "^done,new-thread-id=\"1\"," );
2251 debug_mi_print_frame_info( &info
);
2252 debug_frame_info_free( &info
);
2253 printf( "\n(gdb) \n" );
2257 static void debug_mi_stack_select_frame( int argc
, const char * * argv
)
2259 if ( debug_state
== DEBUG_NO_CHILD
)
2261 debug_mi_format_token();
2262 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2266 const char * new_args
[ 2 ];
2267 new_args
[ 0 ] = "frame";
2268 new_args
[ 1 ] = argv
[ 1 ];
2269 debug_parent_forward_nowait( 2, new_args
, 0, 0 );
2270 debug_mi_format_token();
2271 printf( "^done\n(gdb) \n" );
2275 static void debug_mi_stack_info_frame( int argc
, const char * * argv
)
2277 if ( debug_state
== DEBUG_NO_CHILD
)
2279 debug_mi_format_token();
2280 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2285 fprintf( command_output
, "info frame\n" );
2286 fflush( command_output
);
2287 debug_frame_read( command_child
, &info
);
2288 debug_mi_format_token();
2290 debug_mi_print_frame_info( &info
);
2291 debug_frame_info_free( &info
);
2292 printf( "\n(gdb) \n" );
2296 static void debug_mi_stack_list_variables( int argc
, const char * * argv
)
2298 int print_values
= 0;
2299 #define DEBUG_PRINT_VARIABLES_NO_VALUES 1
2300 #define DEBUG_PRINT_VARIABLES_ALL_VALUES 2
2301 #define DEBUG_PRINT_VARIABLES_SIMPLE_VALUES 3
2302 if ( debug_state
== DEBUG_NO_CHILD
)
2304 debug_mi_format_token();
2305 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2310 for ( ; argc
; --argc
, ++argv
)
2312 if ( strcmp( *argv
, "--thread" ) == 0 )
2314 /* Only one thread. */
2318 else if ( strcmp( *argv
, "--no-values" ) == 0 )
2320 print_values
= DEBUG_PRINT_VARIABLES_NO_VALUES
;
2322 else if ( strcmp( *argv
, "--all-values" ) == 0 )
2324 print_values
= DEBUG_PRINT_VARIABLES_ALL_VALUES
;
2326 else if ( strcmp( *argv
, "--simple-values" ) == 0 )
2328 print_values
= DEBUG_PRINT_VARIABLES_SIMPLE_VALUES
;
2330 else if ( strcmp( *argv
, "--" ) == 0 )
2336 else if ( argv
[ 0 ][ 0 ] == '-' )
2338 debug_mi_format_token();
2339 printf( "^error,msg=\"Unknown argument %s\"\n(gdb) \n", *argv
);
2349 debug_mi_format_token();
2350 printf( "^error,msg=\"Too many arguments for -stack-list-variables\"\n(gdb) \n" );
2358 fprintf( command_output
, "info locals\n" );
2359 fflush( command_output
);
2360 vars
= debug_list_read( command_child
);
2361 debug_parent_wait( 0 );
2362 debug_mi_format_token();
2363 printf( "^done,variables=[" );
2364 for ( iter
= list_begin( vars
), end
= list_end( vars
); iter
!= end
; iter
= list_next( iter
) )
2366 OBJECT
* varname
= list_item( iter
);
2368 const char * new_args
[2];
2377 printf( "{name=\"%s\",value=\"", object_str( varname
) );
2379 string_new( varbuf
);
2380 string_append( varbuf
, "$(" );
2381 string_append( varbuf
, object_str( varname
) );
2382 string_append( varbuf
, ")" );
2383 new_args
[ 0 ] = "print";
2384 new_args
[ 1 ] = varbuf
->value
;
2385 debug_parent_forward( 2, new_args
, 0, 0 );
2386 string_free( varbuf
);
2389 printf( "]\n(gdb) \n" );
2395 static void debug_mi_stack_list_locals( int argc
, const char * * argv
)
2397 int print_values
= 0;
2398 #define DEBUG_PRINT_VARIABLES_NO_VALUES 1
2399 #define DEBUG_PRINT_VARIABLES_ALL_VALUES 2
2400 #define DEBUG_PRINT_VARIABLES_SIMPLE_VALUES 3
2401 if ( debug_state
== DEBUG_NO_CHILD
)
2403 debug_mi_format_token();
2404 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2409 for ( ; argc
; --argc
, ++argv
)
2411 if ( strcmp( *argv
, "--thread" ) == 0 )
2413 /* Only one thread. */
2418 debug_mi_format_token();
2419 printf( "^error,msg=\"Argument required for --thread.\"" );
2423 else if ( strcmp( *argv
, "--no-values" ) == 0 )
2425 print_values
= DEBUG_PRINT_VARIABLES_NO_VALUES
;
2427 else if ( strcmp( *argv
, "--all-values" ) == 0 )
2429 print_values
= DEBUG_PRINT_VARIABLES_ALL_VALUES
;
2431 else if ( strcmp( *argv
, "--simple-values" ) == 0 )
2433 print_values
= DEBUG_PRINT_VARIABLES_SIMPLE_VALUES
;
2435 else if ( strcmp( *argv
, "--" ) == 0 )
2441 else if ( argv
[ 0 ][ 0 ] == '-' )
2443 debug_mi_format_token();
2444 printf( "^error,msg=\"Unknown argument %s\"\n(gdb) \n", *argv
);
2454 debug_mi_format_token();
2455 printf( "^error,msg=\"Too many arguments for -stack-list-variables\"\n(gdb) \n" );
2463 fprintf( command_output
, "info locals\n" );
2464 fflush( command_output
);
2465 vars
= debug_list_read( command_child
);
2466 debug_parent_wait( 0 );
2467 debug_mi_format_token();
2468 printf( "^done,locals=[" );
2469 for ( iter
= list_begin( vars
), end
= list_end( vars
); iter
!= end
; iter
= list_next( iter
) )
2471 OBJECT
* varname
= list_item( iter
);
2473 const char * new_args
[2];
2482 printf( "{name=\"%s\",type=\"list\",value=\"", object_str( varname
) );
2484 string_new( varbuf
);
2485 string_append( varbuf
, "$(" );
2486 string_append( varbuf
, object_str( varname
) );
2487 string_append( varbuf
, ")" );
2488 new_args
[ 0 ] = "print";
2489 new_args
[ 1 ] = varbuf
->value
;
2490 debug_parent_forward( 2, new_args
, 0, 0 );
2491 string_free( varbuf
);
2494 printf( "]\n(gdb) \n" );
2500 static void debug_mi_stack_list_frames( int argc
, const char * * argv
)
2502 const char * new_args
[ 3 ];
2506 if ( debug_state
== DEBUG_NO_CHILD
)
2508 debug_mi_format_token();
2509 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2513 new_args
[ 0 ] = "info";
2514 new_args
[ 1 ] = "frame";
2516 fprintf( command_output
, "info depth\n" );
2517 fflush( command_output
);
2518 depth
= debug_int_read( command_child
);
2520 debug_mi_format_token();
2521 printf( "^done,stack=[" );
2522 for ( i
= 0; i
< depth
; ++i
)
2525 fprintf( command_output
, "info frame %d\n", i
);
2526 fflush( command_output
);
2531 debug_frame_read( command_child
, &frame
);
2532 debug_mi_print_frame_info( &frame
);
2534 printf( "]\n(gdb) \n" );
2538 static void debug_mi_list_target_features( int argc
, const char * * argv
)
2540 /* FIXME: implement this for real */
2541 debug_mi_format_token();
2542 printf( "^done,features=[\"async\"]\n(gdb) \n" );
2545 static void debug_mi_exec_run( int argc
, const char * * argv
)
2547 printf( "=thread-created,id=\"1\",group-id=\"i1\"\n" );
2548 debug_mi_format_token();
2549 printf( "^running\n(gdb) \n" );
2551 debug_start_child( argc
, argv
);
2552 debug_parent_wait( 1 );
2555 static void debug_mi_exec_continue( int argc
, const char * * argv
)
2557 if ( debug_state
== DEBUG_NO_CHILD
)
2559 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2563 const char * new_args
[] = { "continue" };
2564 debug_mi_format_token();
2565 printf( "^running\n(gdb) \n" );
2567 debug_parent_forward( 1, new_args
, 1, 0 );
2571 static void debug_mi_exec_step( int argc
, const char * * argv
)
2573 if ( debug_state
== DEBUG_NO_CHILD
)
2575 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2579 const char * new_args
[] = { "step" };
2580 debug_mi_format_token();
2581 printf( "^running\n(gdb) \n" );
2583 debug_parent_forward( 1, new_args
, 1, 0 );
2587 static void debug_mi_exec_next( int argc
, const char * * argv
)
2589 if ( debug_state
== DEBUG_NO_CHILD
)
2591 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2595 const char * new_args
[] = { "next" };
2596 debug_mi_format_token();
2597 printf( "^running\n(gdb) \n" );
2599 debug_parent_forward( 1, new_args
, 1, 0 );
2603 static void debug_mi_exec_finish( int argc
, const char * * argv
)
2605 if ( debug_state
== DEBUG_NO_CHILD
)
2607 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2611 const char * new_args
[] = { "finish" };
2612 debug_mi_format_token();
2613 printf( "^running\n(gdb) \n" );
2615 debug_parent_forward( 1, new_args
, 1, 0 );
2619 static void debug_mi_data_list_register_names( int argc
, const char * * argv
)
2621 debug_mi_format_token();
2622 printf( "^done,register-names=[]\n(gdb) \n" );
2625 static void debug_mi_data_evaluate_expression( int argc
, const char * * argv
)
2629 printf( "^error,msg=\"Not enough arguments for -data-evaluate-expression\"\n(gdb) \n" );
2631 if ( debug_state
== DEBUG_NO_CHILD
)
2633 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2637 const char * new_args
[ 2 ];
2638 debug_mi_format_token();
2639 printf( "^done,value=\"" );
2641 new_args
[ 0 ] = "print";
2642 new_args
[ 1 ] = argv
[ 1 ];
2643 debug_parent_forward( 2, new_args
, 1, 0 );
2644 printf( "\"\n(gdb) \n" );
2648 static int process_command( char * command
);
2650 static void debug_mi_interpreter_exec( int argc
, const char * * argv
)
2654 debug_mi_error( "Not enough arguments for -interpreter-exec" );
2656 process_command( (char *)argv
[ 2 ] );
2659 /* The debugger's main loop. */
2660 int debugger( void )
2662 command_array
= parent_commands
;
2663 command_input
= stdin
;
2664 if ( debug_interface
== DEBUG_INTERFACE_MI
)
2665 printf( "=thread-group-added,id=\"i1\"\n(gdb) \n" );
2668 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
2677 /* Runs the matching command in the current command_array. */
2678 static int run_command( int argc
, const char * * argv
)
2680 struct command_elem
* command
;
2681 const char * command_name
;
2686 command_name
= argv
[ 0 ];
2687 /* Skip the GDB/MI token when choosing the command to run. */
2688 while( isdigit( *command_name
) ) ++command_name
;
2689 current_token
= atoi( argv
[ 0 ] );
2690 for( command
= command_array
; command
->key
; ++command
)
2692 if ( strcmp( command
->key
, command_name
) == 0 )
2694 ( *command
->command
)( argc
, argv
);
2698 debug_error( "Unknown command: %s", command_name
);
2702 /* Parses a single command into whitespace separated tokens, and runs it. */
2703 static int process_command( char * line
)
2706 size_t capacity
= 8;
2707 char * * buffer
= (char **)malloc( capacity
* sizeof( char * ) );
2708 char * * current
= buffer
;
2710 char * saved
= iter
;
2715 while ( *iter
&& isspace( *iter
) )
2723 /* Find the next token */
2725 if ( *iter
== '\"' )
2728 /* FIXME: handle escaping */
2729 while ( *iter
&& *iter
!= '\"' )
2736 while ( *iter
&& ! isspace( *iter
) )
2741 /* resize the buffer if necessary */
2742 if ( current
== buffer
+ capacity
)
2744 buffer
= (char**)realloc( (void *)buffer
, capacity
* 2 * sizeof( char * ) );
2745 current
= buffer
+ capacity
;
2747 /* append the token to the buffer */
2749 /* null terminate the token */
2755 result
= run_command( current
- buffer
, (const char **)buffer
);
2756 free( (void *)buffer
);
2760 static int read_command( void )
2766 /* HACK: force line to be on the heap. */
2767 string_reserve( line
, 64 );
2768 while( ( ch
= fgetc( command_input
) ) != EOF
)
2776 string_push_back( line
, (char)ch
);
2779 result
= process_command( line
->value
);
2780 string_free( line
);
2784 static void debug_listen( void )
2786 debug_state
= DEBUG_STOPPED
;
2787 while ( debug_state
== DEBUG_STOPPED
)
2789 if ( feof( command_input
) )
2792 fflush( command_output
);
2795 debug_selected_frame_number
= 0;
2798 struct debug_child_data_t debug_child_data
;
2799 const char debugger_opt
[] = "--b2db-internal-debug-handle=";
2800 int debug_interface
;