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_frame_write( FILE * out
, FRAME
* frame
)
198 OBJECT
* fullname
= make_absolute_path( frame
->file
);
199 debug_object_write( out
, frame
->file
);
200 debug_int_write( out
, frame
->line
);
201 debug_object_write( out
, fullname
);
202 debug_lol_write( out
, frame
->args
);
203 debug_string_write( out
, frame
->rulename
);
204 object_free( fullname
);
208 * The information passed to the debugger for
209 * a frame is slightly different from the FRAME
212 typedef struct _frame_info
221 static void debug_frame_info_free( FRAME_INFO
* frame
)
223 object_free( frame
->file
);
224 object_free( frame
->fullname
);
225 lol_free( frame
->args
);
226 free( frame
->rulename
);
229 static void debug_frame_read( FILE * in
, FRAME_INFO
* frame
)
231 frame
->file
= debug_object_read( in
);
232 frame
->line
= debug_int_read( in
);
233 frame
->fullname
= debug_object_read( in
);
234 debug_lol_read( in
, frame
->args
);
235 frame
->rulename
= debug_string_read( in
);
238 static int add_breakpoint( struct breakpoint elem
)
240 if ( num_breakpoints
== breakpoints_capacity
)
242 int new_capacity
= breakpoints_capacity
* 2;
243 if ( new_capacity
== 0 ) new_capacity
= 1;
244 breakpoints
= ( struct breakpoint
* )realloc( breakpoints
, new_capacity
* sizeof( struct breakpoint
) );
245 breakpoints_capacity
= new_capacity
;
247 breakpoints
[ num_breakpoints
++ ] = elem
;
248 return num_breakpoints
;
251 static int add_line_breakpoint( OBJECT
* file
, int line
)
253 struct breakpoint elem
;
255 elem
.bound_file
= NULL
;
257 elem
.status
= BREAKPOINT_ENABLED
;
258 return add_breakpoint( elem
);
261 static int add_function_breakpoint( OBJECT
* name
)
263 struct breakpoint elem
;
265 elem
.bound_file
= object_copy( name
);
267 elem
.status
= BREAKPOINT_ENABLED
;
268 return add_breakpoint( elem
);
272 * Checks whether there is an active breakpoint at the
273 * specified location. Returns the breakpoint id
274 * or -1 if none is found.
276 static int handle_line_breakpoint( OBJECT
* file
, int line
)
279 if ( file
== NULL
) return 0;
280 for ( i
= 0; i
< num_breakpoints
; ++i
)
282 if ( breakpoints
[ i
].bound_file
== NULL
&& is_same_file( breakpoints
[ i
].file
, file
) )
284 breakpoints
[ i
].bound_file
= object_copy( file
);
286 if ( breakpoints
[ i
].status
== BREAKPOINT_ENABLED
&&
287 breakpoints
[ i
].bound_file
!= NULL
&&
288 object_equal( breakpoints
[ i
].bound_file
, file
) &&
289 breakpoints
[ i
].line
== line
)
297 static int handle_function_breakpoint( OBJECT
* name
)
299 return handle_line_breakpoint( name
, -1 );
302 static OBJECT
* make_absolute_path( OBJECT
* filename
)
307 const char * root
= object_str( cwd() );
308 path_parse( object_str( filename
), path1
);
309 path1
->f_root
.ptr
= root
;
310 path1
->f_root
.len
= strlen( root
);
312 path_build( path1
, buf
);
313 result
= object_new( buf
->value
);
318 static OBJECT
* get_filename( OBJECT
* path
)
323 const char * root
= object_str( cwd() );
324 path_parse( object_str( path
), path1
);
325 path1
->f_dir
.ptr
= NULL
;
326 path1
->f_dir
.len
= 0;
328 path_build( path1
, buf
);
329 result
= object_new( buf
->value
);
334 static int is_same_file( OBJECT
* file1
, OBJECT
* file2
)
336 OBJECT
* absolute1
= make_absolute_path( file1
);
337 OBJECT
* absolute2
= make_absolute_path( file2
);
338 OBJECT
* norm1
= path_as_key( absolute1
);
339 OBJECT
* norm2
= path_as_key( absolute2
);
340 OBJECT
* base1
= get_filename( file1
);
341 OBJECT
* base2
= get_filename( file2
);
342 OBJECT
* normbase1
= path_as_key( base1
);
343 OBJECT
* normbase2
= path_as_key( base2
);
344 int result
= object_equal( norm1
, norm2
) ||
345 ( object_equal( base1
, file1
) && object_equal( normbase1
, normbase2
) );
346 object_free( absolute1
);
347 object_free( absolute2
);
348 object_free( norm1
);
349 object_free( norm2
);
350 object_free( base1
);
351 object_free( base2
);
352 object_free( normbase1
);
353 object_free( normbase2
);
357 static void debug_print_source( OBJECT
* filename
, int line
)
361 if ( filename
== NULL
|| object_equal( filename
, constant_builtin
) )
364 file
= fopen( object_str( filename
), "r" );
369 int current_line
= 1;
373 printf( "%d\t", current_line
);
375 while ( ( ch
= fgetc( file
) ) != EOF
)
386 if ( current_line
== line
)
389 printf( "%d\t", current_line
);
397 static void debug_print_frame( FRAME
* frame
)
399 OBJECT
* file
= frame
->file
;
400 if ( file
== NULL
) file
= constant_builtin
;
401 printf( "%s ", frame
->rulename
);
402 if ( strcmp( frame
->rulename
, "module scope" ) != 0 )
405 if ( frame
->args
->count
)
407 lol_print( frame
->args
);
412 printf( "at %s:%d", object_str( file
), frame
->line
);
415 static void debug_mi_print_frame( FRAME
* frame
)
417 OBJECT
* fullname
= make_absolute_path( frame
->file
);
418 printf( "frame={func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}",
420 object_str( frame
->file
),
421 object_str( fullname
),
423 object_free( fullname
);
426 static void debug_print_frame_info( FRAME_INFO
* frame
)
428 OBJECT
* file
= frame
->file
;
429 if ( file
== NULL
) file
= constant_builtin
;
430 printf( "%s ", frame
->rulename
);
431 if ( strcmp( frame
->rulename
, "module scope" ) != 0 )
434 if ( frame
->args
->count
)
436 lol_print( frame
->args
);
441 printf( "at %s:%d", object_str( file
), frame
->line
);
444 static void debug_mi_print_frame_info( FRAME_INFO
* frame
)
446 printf( "frame={func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}",
448 object_str( frame
->file
),
449 object_str( frame
->fullname
),
453 static void debug_on_breakpoint( int id
)
455 fputc( DEBUG_MSG_BREAKPOINT
, command_output
);
456 debug_int_write( command_output
, id
);
457 fflush( command_output
);
461 static void debug_end_stepping( void )
463 fputc( DEBUG_MSG_END_STEPPING
, command_output
);
464 fflush( command_output
);
468 void debug_on_instruction( FRAME
* frame
, OBJECT
* file
, int line
)
471 assert( debug_is_debugging() );
472 if ( debug_state
== DEBUG_NEXT
&& debug_depth
<= 0 && debug_line
!= line
)
477 debug_end_stepping();
479 else if ( debug_state
== DEBUG_STEP
&& debug_line
!= line
)
484 debug_end_stepping();
486 else if ( debug_state
== DEBUG_FINISH
&& debug_depth
<= 0 )
491 debug_end_stepping();
493 else if ( ( debug_file
== NULL
|| ! object_equal( file
, debug_file
) || line
!= debug_line
) &&
494 ( breakpoint_id
= handle_line_breakpoint( file
, line
) ) )
499 debug_on_breakpoint( breakpoint_id
);
503 void debug_on_enter_function( FRAME
* frame
, OBJECT
* name
, OBJECT
* file
, int line
)
506 assert( debug_is_debugging() );
507 if ( debug_state
== DEBUG_STEP
&& file
)
512 debug_end_stepping();
514 else if ( ( breakpoint_id
= handle_function_breakpoint( name
) ) ||
515 ( breakpoint_id
= handle_line_breakpoint( file
, line
) ) )
520 debug_on_breakpoint( breakpoint_id
);
522 else if ( debug_state
== DEBUG_NEXT
|| debug_state
== DEBUG_FINISH
)
528 void debug_on_exit_function( OBJECT
* name
)
530 assert( debug_is_debugging() );
531 if ( debug_state
== DEBUG_NEXT
|| debug_state
== DEBUG_FINISH
)
538 static HANDLE child_handle
;
539 static DWORD child_pid
;
541 static int child_pid
;
544 static void debug_child_continue( int argc
, const char * * argv
)
546 debug_state
= DEBUG_RUN
;
549 static void debug_child_step( int argc
, const char * * argv
)
551 debug_state
= DEBUG_STEP
;
554 static void debug_child_next( int argc
, const char * * argv
)
556 debug_state
= DEBUG_NEXT
;
560 static void debug_child_finish( int argc
, const char * * argv
)
562 debug_state
= DEBUG_FINISH
;
566 static void debug_child_kill( int argc
, const char * * argv
)
571 static int debug_add_breakpoint( const char * name
)
573 const char * file_ptr
= name
;
574 const char * ptr
= strrchr( file_ptr
, ':' );
578 long line
= strtoul( ptr
+ 1, &end
, 10 );
579 if ( line
> 0 && line
<= INT_MAX
&& end
!= ptr
+ 1 && *end
== 0 )
581 OBJECT
* file
= object_new_range( file_ptr
, ptr
- file_ptr
);
582 return add_line_breakpoint( file
, line
);
586 OBJECT
* name
= object_new( file_ptr
);
587 return add_function_breakpoint( name
);
592 OBJECT
* name
= object_new( file_ptr
);
593 return add_function_breakpoint( name
);
597 static void debug_child_break( int argc
, const char * * argv
)
601 debug_add_breakpoint( argv
[ 1 ] );
605 static int get_breakpoint_by_name( const char * name
)
608 const char * file_ptr
= name
;
609 const char * ptr
= strrchr( file_ptr
, ':' );
613 long line
= strtoul( ptr
+ 1, &end
, 10 );
614 if ( line
> 0 && line
<= INT_MAX
&& end
!= ptr
+ 1 && *end
== 0 )
616 OBJECT
* file
= object_new_range( file_ptr
, ptr
- file_ptr
);
617 result
= handle_line_breakpoint( file
, line
);
622 OBJECT
* name
= object_new( file_ptr
);
623 result
= handle_function_breakpoint( name
);
629 OBJECT
* name
= object_new( file_ptr
);
630 result
= handle_function_breakpoint( name
);
636 static void debug_child_disable( int argc
, const char * * argv
)
640 int id
= atoi( argv
[ 1 ] );
641 if ( id
< 1 || id
> num_breakpoints
)
644 if ( breakpoints
[ id
].status
== BREAKPOINT_DELETED
)
646 breakpoints
[ id
].status
= BREAKPOINT_DISABLED
;
650 static void debug_child_enable( int argc
, const char * * argv
)
654 int id
= atoi( argv
[ 1 ] );
655 if ( id
< 1 || id
> num_breakpoints
)
658 if ( breakpoints
[ id
].status
== BREAKPOINT_DELETED
)
660 breakpoints
[ id
].status
= BREAKPOINT_ENABLED
;
664 static void debug_child_delete( int argc
, const char * * argv
)
668 int id
= atoi( argv
[ 1 ] );
669 if ( id
< 1 || id
> num_breakpoints
)
672 breakpoints
[ id
].status
= BREAKPOINT_DELETED
;
676 static void debug_child_print( int argc
, const char * * argv
)
682 const char * lines
[ 2 ];
684 FRAME new_frame
= *debug_frame
;
685 /* Save the current file/line, since running parse_string
686 * will likely change it.
688 saved_frame
= debug_frame
;
689 saved_file
= debug_file
;
690 saved_line
= debug_line
;
692 string_append( buf
, "__DEBUG_PRINT_HELPER__" );
693 for ( i
= 1; i
< argc
; ++i
)
695 string_push_back( buf
, ' ' );
696 string_append( buf
, argv
[ i
] );
698 string_append( buf
, " ;\n" );
699 lines
[ 0 ] = buf
->value
;
701 parse_string( constant_builtin
, lines
, &new_frame
);
703 debug_list_write( command_output
, debug_print_result
);
704 fflush( command_output
);
705 debug_frame
= saved_frame
;
706 debug_file
= saved_file
;
707 debug_line
= saved_line
;
710 static void debug_child_frame( int argc
, const char * * argv
)
714 debug_selected_frame_number
= atoi( argv
[ 1 ] );
718 assert( !"Wrong number of arguments to frame." );
722 static void debug_child_info( int argc
, const char * * argv
)
724 if ( strcmp( argv
[ 1 ], "locals" ) == 0 )
727 if ( debug_frame
->function
)
729 locals
= function_get_variables( debug_frame
->function
);
731 debug_list_write( command_output
, locals
);
732 fflush( command_output
);
735 else if ( strcmp( argv
[ 1 ], "frame" ) == 0 )
737 int frame_number
= debug_selected_frame_number
;
740 FRAME base
= *debug_frame
;
741 FRAME
* frame
= &base
;
742 base
.file
= debug_file
;
743 base
.line
= debug_line
;
744 if ( argc
== 3 ) frame_number
= atoi( argv
[ 2 ] );
746 for ( i
= 0; i
< frame_number
; ++i
) frame
= frame
->prev
;
748 debug_frame_write( command_output
, frame
);
750 else if ( strcmp( argv
[ 1 ], "depth" ) == 0 )
753 FRAME
* frame
= debug_frame
;
759 fprintf( command_output
, "%d", result
);
760 fputc( '\0', command_output
);
761 fflush( command_output
);
765 /* Commands for the parent. */
769 static int get_module_filename( string
* out
)
772 string_reserve( out
, 256 + 1 );
773 string_truncate( out
, 256 );
774 while( ( result
= GetModuleFileName( NULL
, out
->value
, out
->size
) ) == out
->size
)
776 string_reserve( out
, out
->size
* 2 + 1);
777 string_truncate( out
, out
->size
* 2 );
781 string_truncate( out
, result
);
792 static struct command_elem child_commands
[] =
794 { "continue", &debug_child_continue
},
795 { "kill", &debug_child_kill
},
796 { "step", &debug_child_step
},
797 { "next", &debug_child_next
},
798 { "finish", &debug_child_finish
},
799 { "break", &debug_child_break
},
800 { "disable", &debug_child_disable
},
801 { "enable", &debug_child_enable
},
802 { "delete", &debug_child_delete
},
803 { "print", &debug_child_print
},
804 { "frame", &debug_child_frame
},
805 { "info", &debug_child_info
},
809 static void debug_mi_error( const char * message
)
811 debug_mi_format_token();
812 printf( "^error,msg=\"%s\"\n(gdb) \n", message
);
815 static void debug_error_( const char * message
)
817 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
819 printf( "%s\n", message
);
821 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
823 debug_mi_error( message
);
827 static const char * debug_format_message( const char * format
, va_list vargs
)
841 va_copy( args
, vargs
);
843 #if defined(_MSC_VER) && (_MSC_VER <= 1310)
844 result
= _vsnprintf( buf
, sz
, format
, args
);
846 result
= vsnprintf( buf
, sz
, format
, args
);
851 if ( result
< sz
) return buf
;
857 static void debug_error( const char * format
, ... )
861 va_start( args
, format
);
862 msg
= debug_format_message( format
, args
);
866 debug_error_( "Failed formatting error message." );
870 free( ( void * )msg
);
873 static void debug_parent_child_exited( int pid
, int exit_code
)
875 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
877 printf( "Child %d exited with status %d\n", (int)child_pid
, (int)exit_code
);
879 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
881 if ( exit_code
== 0 )
882 printf( "*stopped,reason=\"exited-normally\"\n(gdb) \n" );
884 printf( "*stopped,reason=\"exited\",exit-code=\"%d\"\n(gdb) \n", exit_code
);
888 assert( !"Wrong value of debug_interface." );
892 static void debug_parent_child_signalled( int pid
, int sigid
)
895 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
897 printf( "Child %d exited on signal %d\n", child_pid
, sigid
);
899 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
901 const char * name
= "unknown";
902 const char * meaning
= "unknown";
905 case SIGINT
: name
= "SIGINT"; meaning
= "Interrupt"; break;
907 printf("*stopped,reason=\"exited-signalled\",signal-name=\"%s\",signal-meaning=\"%s\"\n(gdb) \n", name
, meaning
);
911 assert( !"Wrong value of debug_interface." );
915 static void debug_parent_on_breakpoint( void )
919 id
= debug_int_read( command_child
);
920 fprintf( command_output
, "info frame\n" );
921 fflush( command_output
);
922 debug_frame_read( command_child
, &base
);
923 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
925 printf( "Breakpoint %d, ", id
);
926 debug_print_frame_info( &base
);
928 debug_print_source( base
.file
, base
.line
);
930 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
932 printf( "*stopped,reason=\"breakpoint-hit\",bkptno=\"%d\",disp=\"keep\",", id
);
933 debug_mi_print_frame_info( &base
);
934 printf( ",thread-id=\"1\",stopped-threads=\"all\"" );
935 printf( "\n(gdb) \n" );
939 assert( !"Wrong value if debug_interface" );
944 static void debug_parent_on_end_stepping( void )
947 fprintf( command_output
, "info frame\n" );
948 fflush( command_output
);
949 debug_frame_read( command_child
, &base
);
950 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
952 debug_print_source( base
.file
, base
.line
);
956 printf( "*stopped,reason=\"end-stepping-range\"," );
957 debug_mi_print_frame_info( &base
);
958 printf( ",thread-id=\"1\"" );
959 printf( "\n(gdb) \n" );
964 /* Waits for events from the child. */
965 static void debug_parent_wait( int print_message
)
967 char ch
= fgetc( command_child
);
968 if ( ch
== DEBUG_MSG_BREAKPOINT
)
970 debug_parent_on_breakpoint();
972 else if ( ch
== DEBUG_MSG_END_STEPPING
)
974 debug_parent_on_end_stepping();
976 else if ( ch
== DEBUG_MSG_SETUP
)
978 /* FIXME: This is handled in the caller, but it would make
979 more sense to handle it here. */
982 else if ( ch
== EOF
)
985 WaitForSingleObject( child_handle
, INFINITE
);
989 GetExitCodeProcess( child_handle
, &exit_code
);
990 debug_parent_child_exited( (int)child_pid
, (int)exit_code
);
992 CloseHandle( child_handle
);
996 while ( ( pid
= waitpid( child_pid
, &status
, 0 ) ) == -1 )
997 if ( errno
!= EINTR
)
1001 if ( WIFEXITED( status
) )
1002 debug_parent_child_exited( child_pid
, WEXITSTATUS( status
) );
1003 else if ( WIFSIGNALED( status
) )
1004 debug_parent_child_signalled( child_pid
, WTERMSIG( status
) );
1007 fclose( command_child
);
1008 fclose( command_output
);
1009 debug_state
= DEBUG_NO_CHILD
;
1013 /* Prints the message for starting the child. */
1014 static void debug_parent_run_print( int argc
, const char * * argv
)
1017 extern char const * saved_argv0
;
1018 char * name
= executable_path( saved_argv0
);
1019 printf( "Starting program: %s", name
);
1021 for ( i
= 1; i
< argc
; ++i
)
1023 printf( " %s", argv
[ i
] );
1031 void debug_init_handles( const char * in
, const char * out
)
1035 HANDLE write_handle
;
1038 sscanf( in
, "%p", &read_handle
);
1039 read_fd
= _open_osfhandle( (intptr_t)read_handle
, _O_RDONLY
);
1040 command_input
= _fdopen( read_fd
, "r" );
1042 sscanf( out
, "%p", &write_handle
);
1043 write_fd
= _open_osfhandle( (intptr_t)write_handle
, _O_WRONLY
);
1044 command_output
= _fdopen( write_fd
, "w" );
1046 command_array
= child_commands
;
1048 /* Handle the initial setup */
1049 /* wake up the parent */
1050 fputc( DEBUG_MSG_SETUP
, command_output
);
1054 static void init_parent_handles( HANDLE out
, HANDLE in
)
1056 int read_fd
, write_fd
;
1058 command_child
= _fdopen( _open_osfhandle( (intptr_t)in
, _O_RDONLY
), "r" );
1059 command_output
= _fdopen( _open_osfhandle( (intptr_t)out
, _O_WRONLY
), "w" );
1062 static void debug_parent_copy_breakpoints( void )
1065 for ( i
= 0; i
< num_breakpoints
; ++i
)
1067 fprintf( command_output
, "break %s", object_str( breakpoints
[ i
].file
) );
1068 if ( breakpoints
[ i
].line
!= -1 )
1070 fprintf( command_output
, ":%d", breakpoints
[ i
].line
);
1072 fprintf( command_output
, "\n" );
1074 switch ( breakpoints
[ i
].status
)
1076 case BREAKPOINT_ENABLED
:
1078 case BREAKPOINT_DISABLED
:
1079 fprintf( command_output
, "disable %d\n", i
+ 1 );
1081 case BREAKPOINT_DELETED
:
1082 fprintf( command_output
, "delete %d\n", i
+ 1 );
1085 assert( !"Wrong breakpoint status." );
1088 fflush( command_output
);
1093 static void debug_start_child( int argc
, const char * * argv
)
1100 string command_line
[ 1 ];
1101 SECURITY_ATTRIBUTES sa
= { sizeof( SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1102 PROCESS_INFORMATION pi
= { NULL
, NULL
, 0, 0 };
1103 STARTUPINFO si
= { sizeof( STARTUPINFO
), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1105 assert( DEBUG_STATE
== DEBUG_NO_CHILD
);
1106 if ( ! CreatePipe( &pipe1
[ 0 ], &pipe1
[ 1 ], &sa
, 0 ) )
1108 printf("internal error\n");
1111 if ( ! CreatePipe( &pipe2
[ 0 ], &pipe2
[ 1 ], &sa
, 0 ) )
1113 printf("internal error\n");
1114 CloseHandle( pipe1
[ 0 ] );
1115 CloseHandle( pipe1
[ 1 ] );
1119 if ( ! get_module_filename( self
) )
1121 printf("internal error\n");
1122 CloseHandle( pipe1
[ 0 ] );
1123 CloseHandle( pipe1
[ 1 ] );
1124 CloseHandle( pipe2
[ 0 ] );
1125 CloseHandle( pipe2
[ 1 ] );
1128 string_copy( command_line
, "b2 " );
1129 /* Pass the handles as the first and second arguments. */
1130 string_append( command_line
, debugger_opt
);
1131 sprintf( buf
, "%p", pipe1
[ 0 ] );
1132 string_append( command_line
, buf
);
1133 string_push_back( command_line
, ' ' );
1134 string_append( command_line
, debugger_opt
);
1135 sprintf( buf
, "%p", pipe2
[ 1 ] );
1136 string_append( command_line
, buf
);
1137 /* Pass the rest of the command line. */
1140 for ( i
= 1; i
< argc
; ++i
)
1142 string_push_back( command_line
, ' ' );
1143 string_append( command_line
, argv
[ i
] );
1146 SetHandleInformation( pipe1
[ 1 ], HANDLE_FLAG_INHERIT
, 0 );
1147 SetHandleInformation( pipe2
[ 0 ], HANDLE_FLAG_INHERIT
, 0 );
1148 if ( ! CreateProcess(
1150 command_line
->value
,
1161 printf("internal error\n");
1162 CloseHandle( pipe1
[ 0 ] );
1163 CloseHandle( pipe1
[ 1 ] );
1164 CloseHandle( pipe2
[ 0 ] );
1165 CloseHandle( pipe2
[ 1 ] );
1166 string_free( self
);
1167 string_free( command_line
);
1170 child_pid
= pi
.dwProcessId
;
1171 child_handle
= pi
.hProcess
;
1172 CloseHandle( pi
.hThread
);
1173 CloseHandle( pipe1
[ 0 ] );
1174 CloseHandle( pipe2
[ 1 ] );
1175 string_free( self
);
1176 string_free( command_line
);
1178 debug_state
= DEBUG_RUN
;
1180 init_parent_handles( pipe1
[ 1 ], pipe2
[ 0 ] );
1181 debug_parent_wait( 1 );
1182 debug_parent_copy_breakpoints();
1183 fprintf( command_output
, "continue\n" );
1184 fflush( command_output
);
1192 assert( DEBUG_STATE
== DEBUG_NO_CHILD
);
1199 close( pipe1
[ 0 ] );
1200 close( pipe1
[ 1 ] );
1201 close( pipe2
[ 0 ] );
1202 close( pipe1
[ 1 ] );
1204 else if ( pid
== 0 )
1207 extern const char * saved_argv0
;
1208 read_fd
= pipe1
[ 0 ];
1209 write_fd
= pipe2
[ 1 ];
1210 close( pipe2
[ 0 ] );
1211 close( pipe1
[ 1 ] );
1212 command_array
= child_commands
;
1213 argv
[ 0 ] = executable_path( saved_argv0
);
1214 debug_child_data
.argc
= argc
;
1215 debug_child_data
.argv
= argv
;
1216 command_input
= fdopen( read_fd
, "r" );
1217 command_output
= fdopen( write_fd
, "w" );
1218 longjmp( debug_child_data
.jmp
, 1 );
1223 read_fd
= pipe2
[ 0 ];
1224 write_fd
= pipe1
[ 1 ];
1225 close( pipe1
[ 0 ] );
1226 close( pipe2
[ 1 ] );
1227 command_output
= fdopen( write_fd
, "w" );
1228 command_child
= fdopen( read_fd
, "r" );
1231 debug_state
= DEBUG_RUN
;
1235 static void debug_parent_run( int argc
, const char * * argv
)
1237 if ( debug_state
== DEBUG_RUN
)
1239 fprintf( command_output
, "kill\n" );
1240 fflush( command_output
);
1241 debug_parent_wait( 1 );
1243 debug_parent_run_print( argc
, argv
);
1244 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1246 printf( "=thread-created,id=\"1\",group-id=\"i1\"\n" );
1247 debug_mi_format_token();
1248 printf( "^running\n(gdb) \n" );
1250 debug_start_child( argc
, argv
);
1251 debug_parent_wait( 1 );
1254 static int debug_parent_forward_nowait( int argc
, const char * * argv
, int print_message
, int require_child
)
1257 if ( debug_state
== DEBUG_NO_CHILD
)
1259 if ( require_child
)
1260 printf( "The program is not being run.\n" );
1263 fputs( argv
[ 0 ], command_output
);
1264 for( i
= 1; i
< argc
; ++i
)
1266 fputc( ' ', command_output
);
1267 fputs( argv
[ i
], command_output
);
1269 fputc( '\n', command_output
);
1270 fflush( command_output
);
1274 /* FIXME: This function should be eliminated when I finish all stdout to the parent. */
1275 static void debug_parent_forward( int argc
, const char * * argv
, int print_message
, int require_child
)
1277 if ( debug_parent_forward_nowait( argc
, argv
, print_message
, require_child
) != 0 )
1281 debug_parent_wait( print_message
);
1284 static void debug_parent_continue( int argc
, const char * * argv
)
1288 debug_error( "Too many arguments to continue." );
1291 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1293 debug_mi_format_token();
1294 printf( "^running\n(gdb) \n" );
1297 debug_parent_forward( 1, argv
, 1, 1 );
1300 static void debug_parent_kill( int argc
, const char * * argv
)
1304 debug_error( "Too many arguments to kill." );
1307 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1309 debug_mi_format_token();
1310 printf( "^done\n(gdb) \n" );
1313 debug_parent_forward( 1, argv
, 0, 1 );
1316 static void debug_parent_step( int argc
, const char * * argv
)
1320 debug_error( "Too many arguments to step." );
1323 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1325 debug_mi_format_token();
1326 printf( "^running\n(gdb) \n" );
1329 debug_parent_forward( 1, argv
, 1, 1 );
1332 static void debug_parent_next( int argc
, const char * * argv
)
1336 debug_error( "Too many arguments to next." );
1339 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1341 debug_mi_format_token();
1342 printf( "^running\n(gdb) \n" );
1345 debug_parent_forward( 1, argv
, 1, 1 );
1348 static void debug_parent_finish( int argc
, const char * * argv
)
1352 debug_error( "Too many arguments to finish." );
1355 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1357 debug_mi_format_token();
1358 printf( "^running\n(gdb) \n" );
1361 debug_parent_forward( 1, argv
, 1, 1 );
1364 static void debug_parent_break( int argc
, const char * * argv
)
1369 debug_error( "Missing argument to break." );
1372 else if ( argc
> 2 )
1374 debug_error( "Too many arguments to break." );
1377 id
= debug_add_breakpoint( argv
[ 1 ] );
1378 debug_parent_forward_nowait( argc
, argv
, 1, 0 );
1379 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
1381 printf( "Breakpoint %d set at %s\n", id
, argv
[ 1 ] );
1383 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
1385 debug_mi_format_token();
1386 printf( "^done\n(gdb) \n" );
1390 assert( !"wrong value of debug_interface." );
1394 int check_breakpoint_fn_args( int argc
, const char * * argv
)
1398 debug_error( "Missing argument to %s.", argv
[ 0 ] );
1401 else if ( argc
> 2 )
1403 debug_error( "Too many arguments to %s.", argv
[ 0 ] );
1409 long x
= strtol( argv
[ 1 ], &end
, 10 );
1412 debug_error( "Invalid breakpoint number %s.", argv
[ 1 ] );
1415 if ( x
< 1 || x
> num_breakpoints
|| breakpoints
[ x
- 1 ].status
== BREAKPOINT_DELETED
)
1417 debug_error( "Unknown breakpoint %s.", argv
[ 1 ] );
1424 static void debug_parent_disable( int argc
, const char * * argv
)
1426 if ( ! check_breakpoint_fn_args( argc
, argv
) )
1430 debug_child_disable( argc
, argv
);
1431 debug_parent_forward_nowait( 2, argv
, 1, 0 );
1432 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1434 debug_mi_format_token();
1435 printf( "^done\n(gdb) \n" );
1439 static void debug_parent_enable( int argc
, const char * * argv
)
1441 if ( ! check_breakpoint_fn_args( argc
, argv
) )
1445 debug_child_enable( argc
, argv
);
1446 debug_parent_forward_nowait( 2, argv
, 1, 0 );
1447 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1449 debug_mi_format_token();
1450 printf( "^done\n(gdb) \n" );
1454 static void debug_parent_delete( int argc
, const char * * argv
)
1456 if ( ! check_breakpoint_fn_args( argc
, argv
) )
1460 debug_child_delete( argc
, argv
);
1461 debug_parent_forward_nowait( 2, argv
, 1, 0 );
1462 if ( debug_interface
== DEBUG_INTERFACE_MI
)
1464 debug_mi_format_token();
1465 printf( "^done\n(gdb) \n" );
1469 static void debug_parent_clear( int argc
, const char * * argv
)
1472 const char * new_args
[ 2 ];
1476 debug_error( "Missing argument to clear." );
1479 else if ( argc
> 2 )
1481 debug_error( "Too many arguments to clear." );
1484 id
= get_breakpoint_by_name( argv
[ 1 ] );
1487 debug_error( "No breakpoint at %s.", argv
[ 1 ] );
1491 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
1493 printf( "Deleted breakpoint %d\n", id
);
1496 sprintf( buf
, "%d", id
);
1497 new_args
[ 0 ] = "delete";
1498 new_args
[ 1 ] = buf
;
1499 debug_parent_delete( 2, new_args
);
1502 static void debug_parent_print( int argc
, const char * * argv
)
1505 if ( debug_parent_forward_nowait( argc
, argv
, 1, 1 ) != 0 )
1509 result
= debug_list_read( command_child
);
1511 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
1513 list_print( result
);
1516 else if ( debug_interface
== DEBUG_INTERFACE_MI
)
1518 printf( "~\"$1 = " );
1519 list_print( result
);
1520 printf( "\"\n~\"\\n\"\n" );
1521 debug_mi_format_token();
1522 printf( "^done\n(gdb) \n" );
1526 static void debug_parent_backtrace( int argc
, const char * * argv
)
1528 const char * new_args
[ 3 ];
1534 if ( debug_state
== DEBUG_NO_CHILD
)
1536 debug_error( "The program is not being run." );
1540 new_args
[ 0 ] = "info";
1541 new_args
[ 1 ] = "frame";
1543 fprintf( command_output
, "info depth\n" );
1544 fflush( command_output
);
1545 depth_str
= debug_object_read( command_child
);
1546 depth
= atoi( object_str( depth_str
) );
1547 object_free( depth_str
);
1549 for ( i
= 0; i
< depth
; ++i
)
1552 sprintf( buf
, "%d", i
);
1553 new_args
[ 2 ] = buf
;
1554 debug_parent_forward_nowait( 3, new_args
, 0, 0 );
1555 debug_frame_read( command_child
, &frame
);
1556 printf( "#%d in ", i
);
1557 debug_print_frame_info( &frame
);
1563 static void debug_parent_quit( int argc
, const char * * argv
)
1565 if ( debug_state
== DEBUG_RUN
)
1567 fprintf( command_output
, "kill\n" );
1568 fflush( command_output
);
1569 debug_parent_wait( 0 );
1574 static const char * const help_text
[][2] =
1579 "Creates a new b2 child process passing <args> on the command line."
1580 " Terminates\nthe current child (if any).\n"
1584 "continue\nContinue debugging\n"
1588 "step\nContinue to the next statement\n"
1592 "next\nContinue to the next line in the current frame\n"
1596 "finish\nContinue to the end of the current frame\n"
1600 "break <location>\n"
1601 "Sets a breakpoint at <location>. <location> can be either a the name of a\nfunction or <filename>:<lineno>\n"
1605 "disable <breakpoint>\nDisable a breakpoint\n"
1609 "enable <breakpoint>\nEnable a breakpoint\n"
1613 "delete <breakpoint>\nDelete a breakpoint\n"
1617 "clear <location>\nDelete the breakpoint at <location>\n"
1621 "print <expression>\nDisplay the value of <expression>\n"
1625 "backtrace\nDisplay the call stack\n"
1629 "kill\nTerminate the child\n"
1633 "quit\nExit the debugger\n"
1637 "help\nhelp <command>\nShow help for debugger commands.\n"
1642 static void debug_parent_help( int argc
, const char * * argv
)
1647 "run - Start debugging\n"
1648 "continue - Continue debugging\n"
1649 "step - Continue to the next statement\n"
1650 "next - Continue to the next line in the current frame\n"
1651 "finish - Continue to the end of the current frame\n"
1652 "break - Set a breakpoint\n"
1653 "disable - Disable a breakpoint\n"
1654 "enable - Enable a breakpoint\n"
1655 "delete - Delete a breakpoint\n"
1656 "clear - Delete a breakpoint by location\n"
1659 "print - Display an expression\n"
1660 "backtrace - Display the call stack\n"
1661 "kill - Terminate the child\n"
1662 "quit - Exit the debugger\n"
1663 "help - Debugger help\n"
1666 else if ( argc
== 2 )
1669 for ( i
= 0; help_text
[ i
][ 0 ]; ++i
)
1671 if ( strcmp( argv
[ 1 ], help_text
[ i
][ 0 ] ) == 0 )
1673 printf( "%s", help_text
[ i
][ 1 ] );
1677 printf( "No command named %s\n", argv
[ 1 ] );
1681 static void debug_mi_break_insert( int argc
, const char * * argv
);
1682 static void debug_mi_break_delete( int argc
, const char * * argv
);
1683 static void debug_mi_break_disable( int argc
, const char * * argv
);
1684 static void debug_mi_break_enable( int argc
, const char * * argv
);
1685 static void debug_mi_break_info( int argc
, const char * * argv
);
1686 static void debug_mi_break_list( int argc
, const char * * argv
);
1687 static void debug_mi_inferior_tty_set( int argc
, const char * * argv
);
1688 static void debug_mi_gdb_exit( int argc
, const char * * argv
);
1689 static void debug_mi_gdb_set( int argc
, const char * * argv
);
1690 static void debug_mi_gdb_show( int argc
, const char * * argv
);
1691 static void debug_mi_not_implemented( int argc
, const char * * argv
);
1692 static void debug_mi_file_list_exec_source_files( int argc
, const char * * argv
);
1693 static void debug_mi_file_list_exec_source_file( int argc
, const char * * argv
);
1694 static void debug_mi_thread_info( int argc
, const char * * argv
);
1695 static void debug_mi_thread_select( int argc
, const char * * argv
);
1696 static void debug_mi_stack_info_frame( int argc
, const char * * argv
);
1697 static void debug_mi_stack_select_frame( int argc
, const char * * argv
);
1698 static void debug_mi_stack_list_variables( int argc
, const char * * argv
);
1699 static void debug_mi_stack_list_locals( int argc
, const char * * argv
);
1700 static void debug_mi_stack_list_frames( int argc
, const char * * argv
);
1701 static void debug_mi_list_target_features( int argc
, const char * * argv
);
1702 static void debug_mi_exec_run( int argc
, const char * * argv
);
1703 static void debug_mi_exec_continue( int argc
, const char * * argv
);
1704 static void debug_mi_exec_step( int argc
, const char * * argv
);
1705 static void debug_mi_exec_next( int argc
, const char * * argv
);
1706 static void debug_mi_exec_finish( int argc
, const char * * argv
);
1707 static void debug_mi_data_list_register_names( int argc
, const char * * argv
);
1708 static void debug_mi_data_evaluate_expression( int argc
, const char * * argv
);
1709 static void debug_mi_interpreter_exec( int argc
, const char * * argv
);
1711 static struct command_elem parent_commands
[] =
1713 { "run", &debug_parent_run
},
1714 { "continue", &debug_parent_continue
},
1715 { "kill", &debug_parent_kill
},
1716 { "step", &debug_parent_step
},
1717 { "next", &debug_parent_next
},
1718 { "finish", &debug_parent_finish
},
1719 { "break", &debug_parent_break
},
1720 { "disable", &debug_parent_disable
},
1721 { "enable", &debug_parent_enable
},
1722 { "delete", &debug_parent_delete
},
1723 { "clear", &debug_parent_clear
},
1724 { "print", &debug_parent_print
},
1725 { "backtrace", &debug_parent_backtrace
},
1726 { "quit", &debug_parent_quit
},
1727 { "help", &debug_parent_help
},
1728 { "-break-insert", &debug_mi_break_insert
},
1729 { "-break-delete", &debug_mi_break_delete
},
1730 { "-break-disable", &debug_mi_break_disable
},
1731 { "-break-enable", &debug_mi_break_enable
},
1732 { "-break-info", &debug_mi_break_info
},
1733 { "-break-list", &debug_mi_break_list
},
1734 { "-inferior-tty-set", &debug_mi_inferior_tty_set
},
1735 { "-gdb-exit", &debug_mi_gdb_exit
},
1736 { "-gdb-set", &debug_mi_gdb_set
},
1737 { "-gdb-show", &debug_mi_gdb_show
},
1738 { "-enable-pretty-printing", &debug_mi_not_implemented
},
1739 { "-file-list-exec-source-files", &debug_mi_file_list_exec_source_files
},
1740 { "-file-list-exec-source-file", &debug_mi_file_list_exec_source_file
},
1741 { "-thread-info", &debug_mi_thread_info
},
1742 { "-thread-select", &debug_mi_thread_select
},
1743 { "-stack-info-frame", &debug_mi_stack_info_frame
},
1744 { "-stack-select-frame", &debug_mi_stack_select_frame
},
1745 { "-stack-list-variables", &debug_mi_stack_list_variables
},
1746 { "-stack-list-locals", &debug_mi_stack_list_locals
},
1747 { "-stack-list-frames", &debug_mi_stack_list_frames
},
1748 { "-list-target-features", &debug_mi_list_target_features
},
1749 { "-exec-run", &debug_mi_exec_run
},
1750 { "-exec-continue", &debug_mi_exec_continue
},
1751 { "-exec-step", &debug_mi_exec_step
},
1752 { "-exec-next", &debug_mi_exec_next
},
1753 { "-exec-finish", &debug_mi_exec_finish
},
1754 { "-data-list-register-names", &debug_mi_data_list_register_names
},
1755 { "-data-evaluate-expression", &debug_mi_data_evaluate_expression
},
1756 { "-interpreter-exec", &debug_mi_interpreter_exec
},
1760 static void debug_mi_format_token( void )
1762 if ( current_token
!= 0 )
1764 printf( "%d", current_token
);
1768 static void debug_mi_format_breakpoint( int id
)
1770 struct breakpoint
* ptr
= &breakpoints
[ id
- 1 ];
1772 printf( "number=\"%d\"", id
);
1773 printf( ",type=\"breakpoint\"" );
1774 printf( ",disp=\"keep\"" ); /* FIXME: support temporary breakpoints. */
1775 printf( ",enabled=\"%s\"", ptr
->status
== BREAKPOINT_ENABLED
? "y" : "n" );
1777 if ( ptr
->line
== -1 )
1779 printf( ",func=\"%s\"", object_str( ptr
->file
) );
1783 printf( ",file=\"%s\"", object_str( ptr
->file
) );
1784 printf( ",line=\"%d\"", ptr
->line
);
1785 printf( ",fullname=\"%s\"", object_str( ptr
->file
) );
1793 static int breakpoint_id_parse( const char * name
)
1795 int id
= atoi( name
);
1796 if ( id
> num_breakpoints
|| id
< 1 || breakpoints
[ id
].status
== BREAKPOINT_DELETED
)
1801 static void debug_mi_break_after( int argc
, const char * * argv
)
1807 if ( argc
> 0 && strcmp( argv
[ 0 ], "--" ) == 0 )
1814 debug_mi_error( "not enough arguments for -break-after." );
1817 else if ( argc
> 2 )
1819 debug_mi_error( "too many arguments for -break-after." );
1822 id
= atoi( argv
[ 0 ] );
1823 count
= atoi( argv
[ 1 ] );
1824 /* FIXME: set ignore count */
1827 static void debug_mi_break_insert( int argc
, const char * * argv
)
1829 const char * inner_argv
[ 2 ];
1830 int temporary
= 0; /* FIXME: not supported yet */
1831 int hardware
= 0; /* unsupported */
1832 int force
= 1; /* We don't have global debug information... */
1834 int tracepoint
= 0; /* unsupported */
1836 int ignore_count
= 0;
1837 const char * condition
; /* FIXME: not supported yet */
1838 const char * location
;
1840 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
1842 if ( strcmp( *argv
, "-t" ) == 0 )
1846 else if ( strcmp( *argv
, "-h" ) == 0 )
1850 else if ( strcmp( *argv
, "-f" ) == 0 )
1854 else if ( strcmp( *argv
, "-d" ) == 0 )
1858 else if ( strcmp( *argv
, "-a" ) == 0 )
1862 else if ( strcmp( *argv
, "-c" ) == 0 )
1866 debug_mi_error( "Missing argument for -c." );
1870 condition
= argv
[ 1 ];
1874 else if ( strcmp( *argv
, "-i" ) == 0 )
1878 debug_mi_error( "Missing argument for -i." );
1882 ignore_count
= atoi( argv
[ 1 ] );
1886 else if ( strcmp( *argv
, "-p" ) == 0 )
1890 debug_mi_error( "Missing argument for -p." );
1894 thread_id
= atoi( argv
[ 1 ] );
1898 else if ( strcmp( *argv
, "--" ) == 0 )
1904 else if ( **argv
!= '-' )
1910 debug_mi_error( "Unknown argument." );
1916 debug_mi_error( "Too many arguments for -break-insert." );
1926 debug_mi_error( "Not implemented: -break-insert with no location." );
1929 inner_argv
[ 0 ] = "break";
1930 inner_argv
[ 1 ] = location
;
1932 id
= debug_add_breakpoint( location
);
1933 debug_parent_forward_nowait( 2, inner_argv
, 1, 0 );
1938 sprintf( buf
, "%d", num_breakpoints
);
1939 inner_argv
[ 0 ] = "disable";
1940 inner_argv
[ 1 ] = buf
;
1941 debug_child_disable( 2, inner_argv
);
1942 debug_parent_forward_nowait( 2, inner_argv
, 1, 0 );
1945 debug_mi_format_token();
1947 debug_mi_format_breakpoint( id
);
1948 printf( "\n(gdb) \n" );
1951 static void debug_mi_break_delete( int argc
, const char * * argv
)
1955 debug_mi_error( "Not enough arguments for -break-delete" );
1958 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
1960 const char * inner_argv
[ 2 ];
1961 int id
= breakpoint_id_parse( *argv
);
1964 debug_mi_error( "Not a valid breakpoint" );
1967 inner_argv
[ 0 ] = "delete";
1968 inner_argv
[ 1 ] = *argv
;
1969 debug_parent_delete( 2, inner_argv
);
1973 static void debug_mi_break_enable( int argc
, const char * * argv
)
1977 debug_mi_error( "Not enough arguments for -break-enable" );
1980 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
1982 const char * inner_argv
[ 2 ];
1983 int id
= breakpoint_id_parse( *argv
);
1986 debug_mi_error( "Not a valid breakpoint" );
1989 inner_argv
[ 0 ] = "enable";
1990 inner_argv
[ 1 ] = *argv
;
1991 debug_parent_enable( 2, inner_argv
);
1995 static void debug_mi_break_disable( int argc
, const char * * argv
)
1999 debug_mi_error( "Not enough arguments for -break-disable" );
2002 for ( --argc
, ++argv
; argc
; --argc
, ++argv
)
2004 const char * inner_argv
[ 2 ];
2005 int id
= breakpoint_id_parse( *argv
);
2008 debug_mi_error( "Not a valid breakpoint" );
2011 inner_argv
[ 0 ] = "disable";
2012 inner_argv
[ 1 ] = *argv
;
2013 debug_parent_disable( 2, inner_argv
);
2017 static void debug_mi_format_breakpoint_header_col( int width
, int alignment
, const char * col_name
, const char * colhdr
)
2019 printf( "{width=\"%d\",alignment=\"%d\",col_name=\"%s\",colhdr=\"%s\"}", width
, alignment
, col_name
, colhdr
);
2022 static void debug_mi_format_breakpoint_hdr( void )
2025 debug_mi_format_breakpoint_header_col( 7, -1, "number", "Num" );
2027 debug_mi_format_breakpoint_header_col( 14, -1, "type", "Type" );
2029 debug_mi_format_breakpoint_header_col( 4, -1, "disp", "Disp" );
2031 debug_mi_format_breakpoint_header_col( 3, -1, "enabled", "Enb" );
2033 debug_mi_format_breakpoint_header_col( 10, -1, "addr", "Address" );
2035 debug_mi_format_breakpoint_header_col( 40, 2, "what", "What" );
2039 static void debug_mi_break_info( int argc
, const char * * argv
)
2044 if ( strcmp( *argv
, "--" ) == 0 )
2051 debug_mi_error( "Not enough arguments for -break-info" );
2056 debug_mi_error( "Too many arguments for -break-info" );
2059 id
= breakpoint_id_parse( *argv
);
2062 debug_mi_error( "No such breakpoint." );
2066 printf( "^done,BreakpointTable={"
2067 "nr_rows=\"%d\",nr_cols=\"6\",", 1 );
2068 debug_mi_format_breakpoint_hdr();
2069 printf( ",body=[" );
2070 debug_mi_format_breakpoint( id
);
2072 printf("\n(gdb) \n");
2075 static void debug_mi_break_list( int argc
, const char * * argv
)
2080 if ( argc
> 2 || ( argc
== 2 && strcmp( argv
[ 1 ], "--" ) ) )
2082 debug_mi_error( "Too many arguments for -break-list" );
2087 for ( i
= 0; i
< num_breakpoints
; ++i
)
2088 if ( breakpoints
[ i
].status
!= BREAKPOINT_DELETED
)
2090 debug_mi_format_token();
2091 printf( "^done,BreakpointTable={"
2092 "nr_rows=\"%d\",nr_cols=\"6\",", number
);
2093 debug_mi_format_breakpoint_hdr();
2094 printf( ",body=[" );
2096 for ( i
= 0; i
< num_breakpoints
; ++i
)
2097 if ( breakpoints
[ i
].status
!= BREAKPOINT_DELETED
)
2099 if ( first
) first
= 0;
2101 debug_mi_format_breakpoint( i
+ 1 );
2104 printf("\n(gdb) \n");
2107 static void debug_mi_inferior_tty_set( int argc
, const char * * argv
)
2109 /* FIXME: implement this for real */
2110 debug_mi_format_token();
2111 printf( "^done\n(gdb) \n" );
2114 static void debug_mi_gdb_exit( int argc
, const char * * argv
)
2116 if ( debug_state
== DEBUG_RUN
)
2118 fprintf( command_output
, "kill\n" );
2119 fflush( command_output
);
2120 debug_parent_wait( 0 );
2122 debug_mi_format_token();
2123 printf( "^exit\n" );
2124 exit( EXIT_SUCCESS
);
2127 static void debug_mi_gdb_set( int argc
, const char * * argv
)
2129 /* FIXME: implement this for real */
2130 debug_mi_format_token();
2131 printf( "^done\n(gdb) \n" );
2134 static void debug_mi_gdb_show( int argc
, const char * * argv
)
2136 const char * value
= "";
2137 /* FIXME: implement this for real */
2138 debug_mi_format_token();
2140 printf( "^done,value=\"%s\"\n(gdb) \n", value
);
2143 static void debug_mi_not_implemented( int argc
, const char * * argv
)
2145 /* FIXME: implement this for real */
2146 debug_mi_format_token();
2147 printf( "^done\n(gdb) \n" );
2150 void debug_mi_file_list_exec_source_files( int argc
, const char * * argv
)
2152 /* FIXME: implement this for real */
2153 debug_mi_format_token();
2154 printf( "^done,files=[]\n(gdb) \n" );
2157 static void debug_mi_file_list_exec_source_file( int argc
, const char * * argv
)
2159 /* FIXME: implement this for real */
2160 debug_mi_format_token();
2161 printf( "^error,msg=\"Don't know how to handle this yet\"\n(gdb) \n" );
2164 static void debug_mi_thread_info( int argc
, const char * * argv
)
2166 if ( debug_state
== DEBUG_NO_CHILD
)
2168 debug_mi_format_token();
2169 printf( "^done,threads=[]\n(gdb) \n" );
2173 const char * new_args
[] = { "info", "frame" };
2175 debug_parent_forward_nowait( 2, new_args
, 0, 0 );
2176 debug_frame_read( command_child
, &info
);
2178 debug_mi_format_token();
2179 printf( "^done,threads=[{id=\"1\"," );
2180 debug_mi_print_frame_info( &info
);
2181 debug_frame_info_free( &info
);
2182 printf( "}],current-thread-id=\"1\"\n(gdb) \n" );
2186 static void debug_mi_thread_select( int argc
, const char * * argv
)
2188 if ( debug_state
== DEBUG_NO_CHILD
)
2190 /* FIXME: better error handling*/
2191 debug_mi_format_token();
2192 printf( "^error,msg=\"Thread ID 1 not known\"\n(gdb) \n" );
2196 const char * new_args
[] = { "info", "frame" };
2198 debug_parent_forward_nowait( 2, new_args
, 0, 0 );
2199 debug_frame_read( command_child
, &info
);
2201 debug_mi_format_token();
2202 printf( "^done,new-thread-id=\"1\"," );
2203 debug_mi_print_frame_info( &info
);
2204 debug_frame_info_free( &info
);
2205 printf( "\n(gdb) \n" );
2209 static void debug_mi_stack_select_frame( int argc
, const char * * argv
)
2211 if ( debug_state
== DEBUG_NO_CHILD
)
2213 debug_mi_format_token();
2214 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2218 const char * new_args
[ 2 ];
2219 new_args
[ 0 ] = "frame";
2220 new_args
[ 1 ] = argv
[ 1 ];
2221 debug_parent_forward_nowait( 2, new_args
, 0, 0 );
2222 debug_mi_format_token();
2223 printf( "^done\n(gdb) \n" );
2227 static void debug_mi_stack_info_frame( int argc
, const char * * argv
)
2229 if ( debug_state
== DEBUG_NO_CHILD
)
2231 debug_mi_format_token();
2232 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2237 fprintf( command_output
, "info frame\n" );
2238 fflush( command_output
);
2239 debug_frame_read( command_child
, &info
);
2240 debug_mi_format_token();
2242 debug_mi_print_frame_info( &info
);
2243 debug_frame_info_free( &info
);
2244 printf( "\n(gdb) \n" );
2248 static void debug_mi_stack_list_variables( int argc
, const char * * argv
)
2250 int print_values
= 0;
2251 #define DEBUG_PRINT_VARIABLES_NO_VALUES 1
2252 #define DEBUG_PRINT_VARIABLES_ALL_VALUES 2
2253 #define DEBUG_PRINT_VARIABLES_SIMPLE_VALUES 3
2254 if ( debug_state
== DEBUG_NO_CHILD
)
2256 debug_mi_format_token();
2257 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2262 for ( ; argc
; --argc
, ++argv
)
2264 if ( strcmp( *argv
, "--thread" ) == 0 )
2266 /* Only one thread. */
2270 else if ( strcmp( *argv
, "--no-values" ) == 0 )
2272 print_values
= DEBUG_PRINT_VARIABLES_NO_VALUES
;
2274 else if ( strcmp( *argv
, "--all-values" ) == 0 )
2276 print_values
= DEBUG_PRINT_VARIABLES_ALL_VALUES
;
2278 else if ( strcmp( *argv
, "--simple-values" ) == 0 )
2280 print_values
= DEBUG_PRINT_VARIABLES_SIMPLE_VALUES
;
2282 else if ( strcmp( *argv
, "--" ) == 0 )
2288 else if ( argv
[ 0 ][ 0 ] == '-' )
2290 debug_mi_format_token();
2291 printf( "^error,msg=\"Unknown argument %s\"\n(gdb) \n", *argv
);
2301 debug_mi_format_token();
2302 printf( "^error,msg=\"Too many arguments for -stack-list-variables\"\n(gdb) \n" );
2310 fprintf( command_output
, "info locals\n" );
2311 fflush( command_output
);
2312 vars
= debug_list_read( command_child
);
2313 debug_parent_wait( 0 );
2314 debug_mi_format_token();
2315 printf( "^done,variables=[" );
2316 for ( iter
= list_begin( vars
), end
= list_end( vars
); iter
!= end
; iter
= list_next( iter
) )
2318 OBJECT
* varname
= list_item( iter
);
2320 const char * new_args
[2];
2329 printf( "{name=\"%s\",value=\"", object_str( varname
) );
2331 string_new( varbuf
);
2332 string_append( varbuf
, "$(" );
2333 string_append( varbuf
, object_str( varname
) );
2334 string_append( varbuf
, ")" );
2335 new_args
[ 0 ] = "print";
2336 new_args
[ 1 ] = varbuf
->value
;
2337 debug_parent_forward( 2, new_args
, 0, 0 );
2338 string_free( varbuf
);
2341 printf( "]\n(gdb) \n" );
2347 static void debug_mi_stack_list_locals( int argc
, const char * * argv
)
2349 int print_values
= 0;
2350 #define DEBUG_PRINT_VARIABLES_NO_VALUES 1
2351 #define DEBUG_PRINT_VARIABLES_ALL_VALUES 2
2352 #define DEBUG_PRINT_VARIABLES_SIMPLE_VALUES 3
2353 if ( debug_state
== DEBUG_NO_CHILD
)
2355 debug_mi_format_token();
2356 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2361 for ( ; argc
; --argc
, ++argv
)
2363 if ( strcmp( *argv
, "--thread" ) == 0 )
2365 /* Only one thread. */
2370 debug_mi_format_token();
2371 printf( "^error,msg=\"Argument required for --thread.\"" );
2375 else if ( strcmp( *argv
, "--no-values" ) == 0 )
2377 print_values
= DEBUG_PRINT_VARIABLES_NO_VALUES
;
2379 else if ( strcmp( *argv
, "--all-values" ) == 0 )
2381 print_values
= DEBUG_PRINT_VARIABLES_ALL_VALUES
;
2383 else if ( strcmp( *argv
, "--simple-values" ) == 0 )
2385 print_values
= DEBUG_PRINT_VARIABLES_SIMPLE_VALUES
;
2387 else if ( strcmp( *argv
, "--" ) == 0 )
2393 else if ( argv
[ 0 ][ 0 ] == '-' )
2395 debug_mi_format_token();
2396 printf( "^error,msg=\"Unknown argument %s\"\n(gdb) \n", *argv
);
2406 debug_mi_format_token();
2407 printf( "^error,msg=\"Too many arguments for -stack-list-variables\"\n(gdb) \n" );
2415 fprintf( command_output
, "info locals\n" );
2416 fflush( command_output
);
2417 vars
= debug_list_read( command_child
);
2418 debug_parent_wait( 0 );
2419 debug_mi_format_token();
2420 printf( "^done,locals=[" );
2421 for ( iter
= list_begin( vars
), end
= list_end( vars
); iter
!= end
; iter
= list_next( iter
) )
2423 OBJECT
* varname
= list_item( iter
);
2425 const char * new_args
[2];
2434 printf( "{name=\"%s\",type=\"list\",value=\"", object_str( varname
) );
2436 string_new( varbuf
);
2437 string_append( varbuf
, "$(" );
2438 string_append( varbuf
, object_str( varname
) );
2439 string_append( varbuf
, ")" );
2440 new_args
[ 0 ] = "print";
2441 new_args
[ 1 ] = varbuf
->value
;
2442 debug_parent_forward( 2, new_args
, 0, 0 );
2443 string_free( varbuf
);
2446 printf( "]\n(gdb) \n" );
2452 static void debug_mi_stack_list_frames( int argc
, const char * * argv
)
2454 const char * new_args
[ 3 ];
2458 if ( debug_state
== DEBUG_NO_CHILD
)
2460 debug_mi_format_token();
2461 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2465 new_args
[ 0 ] = "info";
2466 new_args
[ 1 ] = "frame";
2468 fprintf( command_output
, "info depth\n" );
2469 fflush( command_output
);
2470 depth
= debug_int_read( command_child
);
2472 debug_mi_format_token();
2473 printf( "^done,stack=[" );
2474 for ( i
= 0; i
< depth
; ++i
)
2477 fprintf( command_output
, "info frame %d\n", i
);
2478 fflush( command_output
);
2483 debug_frame_read( command_child
, &frame
);
2484 debug_mi_print_frame_info( &frame
);
2486 printf( "]\n(gdb) \n" );
2490 static void debug_mi_list_target_features( int argc
, const char * * argv
)
2492 /* FIXME: implement this for real */
2493 debug_mi_format_token();
2494 printf( "^done,features=[\"async\"]\n(gdb) \n" );
2497 static void debug_mi_exec_run( int argc
, const char * * argv
)
2499 printf( "=thread-created,id=\"1\",group-id=\"i1\"\n" );
2500 debug_mi_format_token();
2501 printf( "^running\n(gdb) \n" );
2503 debug_start_child( argc
, argv
);
2504 debug_parent_wait( 1 );
2507 static void debug_mi_exec_continue( int argc
, const char * * argv
)
2509 if ( debug_state
== DEBUG_NO_CHILD
)
2511 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2515 const char * new_args
[] = { "continue" };
2516 debug_mi_format_token();
2517 printf( "^running\n(gdb) \n" );
2519 debug_parent_forward( 1, new_args
, 1, 0 );
2523 static void debug_mi_exec_step( int argc
, const char * * argv
)
2525 if ( debug_state
== DEBUG_NO_CHILD
)
2527 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2531 const char * new_args
[] = { "step" };
2532 debug_mi_format_token();
2533 printf( "^running\n(gdb) \n" );
2535 debug_parent_forward( 1, new_args
, 1, 0 );
2539 static void debug_mi_exec_next( int argc
, const char * * argv
)
2541 if ( debug_state
== DEBUG_NO_CHILD
)
2543 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2547 const char * new_args
[] = { "next" };
2548 debug_mi_format_token();
2549 printf( "^running\n(gdb) \n" );
2551 debug_parent_forward( 1, new_args
, 1, 0 );
2555 static void debug_mi_exec_finish( 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
[] = { "finish" };
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_data_list_register_names( int argc
, const char * * argv
)
2573 debug_mi_format_token();
2574 printf( "^done,register-names=[]\n(gdb) \n" );
2577 static void debug_mi_data_evaluate_expression( int argc
, const char * * argv
)
2581 printf( "^error,msg=\"Not enough arguments for -data-evaluate-expression\"\n(gdb) \n" );
2583 if ( debug_state
== DEBUG_NO_CHILD
)
2585 printf( "^error,msg=\"No child\"\n(gdb) \n" );
2589 const char * new_args
[ 2 ];
2590 debug_mi_format_token();
2591 printf( "^done,value=\"" );
2593 new_args
[ 0 ] = "print";
2594 new_args
[ 1 ] = argv
[ 1 ];
2595 debug_parent_forward( 2, new_args
, 1, 0 );
2596 printf( "\"\n(gdb) \n" );
2600 static int process_command( char * command
);
2602 static void debug_mi_interpreter_exec( int argc
, const char * * argv
)
2606 debug_mi_error( "Not enough arguments for -interpreter-exec" );
2608 process_command( (char *)argv
[ 2 ] );
2611 /* The debugger's main loop. */
2612 int debugger( void )
2614 command_array
= parent_commands
;
2615 command_input
= stdin
;
2616 if ( debug_interface
== DEBUG_INTERFACE_MI
)
2617 printf( "=thread-group-added,id=\"i1\"\n(gdb) \n" );
2620 if ( debug_interface
== DEBUG_INTERFACE_CONSOLE
)
2629 /* Runs the matching command in the current command_array. */
2630 static int run_command( int argc
, const char * * argv
)
2632 struct command_elem
* command
;
2633 const char * command_name
;
2638 command_name
= argv
[ 0 ];
2639 /* Skip the GDB/MI token when choosing the command to run. */
2640 while( isdigit( *command_name
) ) ++command_name
;
2641 current_token
= atoi( argv
[ 0 ] );
2642 for( command
= command_array
; command
->key
; ++command
)
2644 if ( strcmp( command
->key
, command_name
) == 0 )
2646 ( *command
->command
)( argc
, argv
);
2650 debug_error( "Unknown command: %s", command_name
);
2654 /* Parses a single command into whitespace separated tokens, and runs it. */
2655 static int process_command( char * line
)
2658 size_t capacity
= 8;
2659 const char * * buffer
= malloc( capacity
* sizeof( const char * ) );
2660 const char * * current
= buffer
;
2662 const char * saved
= iter
;
2667 while ( *iter
&& isspace( *iter
) )
2675 /* Find the next token */
2677 if ( *iter
== '\"' )
2680 /* FIXME: handle escaping */
2681 while ( *iter
&& *iter
!= '\"' )
2688 while ( *iter
&& ! isspace( *iter
) )
2693 /* resize the buffer if necessary */
2694 if ( current
== buffer
+ capacity
)
2696 buffer
= realloc( (void *)buffer
, capacity
* 2 * sizeof( const char * ) );
2697 current
= buffer
+ capacity
;
2699 /* append the token to the buffer */
2701 /* null terminate the token */
2707 result
= run_command( current
- buffer
, buffer
);
2708 free( (void *)buffer
);
2712 static int read_command( void )
2718 /* HACK: force line to be on the heap. */
2719 string_reserve( line
, 64 );
2720 while( ( ch
= fgetc( command_input
) ) != EOF
)
2728 string_push_back( line
, (char)ch
);
2731 result
= process_command( line
->value
);
2732 string_free( line
);
2736 static void debug_listen( void )
2738 debug_state
= DEBUG_STOPPED
;
2739 while ( debug_state
== DEBUG_STOPPED
)
2741 if ( feof( command_input
) )
2744 fflush( command_output
);
2747 debug_selected_frame_number
= 0;
2750 struct debug_child_data_t debug_child_data
;
2751 const char debugger_opt
[] = "--b2db-internal-debug-handle=";
2752 int debug_interface
;