1 /*
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)
6  */
7 
8 #include "debugger.h"
9 #include "constants.h"
10 #include "strings.h"
11 #include "pathsys.h"
12 #include "cwd.h"
13 #include "function.h"
14 #include <assert.h>
15 #include <stdarg.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <limits.h>
20 #include <signal.h>
21 #include <ctype.h>
22 
23 #ifdef NT
24 #include <windows.h>
25 #include <io.h>
26 #include <fcntl.h>
27 #else
28 #include <errno.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 #endif
32 
33 #undef debug_on_enter_function
34 #undef debug_on_exit_function
35 
36 struct breakpoint
37 {
38     OBJECT * file;
39     OBJECT * bound_file;
40     int line;
41     int status;
42 };
43 
44 #define BREAKPOINT_ENABLED 1
45 #define BREAKPOINT_DISABLED 2
46 #define BREAKPOINT_DELETED 3
47 
48 static struct breakpoint * breakpoints;
49 static int num_breakpoints;
50 static int breakpoints_capacity;
51 
52 #define DEBUG_NO_CHILD  0
53 #define DEBUG_RUN       1
54 #define DEBUG_STEP      2
55 #define DEBUG_NEXT      3
56 #define DEBUG_FINISH    4
57 #define DEBUG_STOPPED   5
58 
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
63 
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;
72 
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;
79 
80 struct command_elem
81 {
82     const char * key;
83     void (*command)( int, const char * * );
84 };
85 
86 static struct command_elem * command_array;
87 
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 );
93 
debug_string_write(FILE * out,const char * data)94 static void debug_string_write( FILE * out, const char * data )
95 {
96     fprintf( out, "%s", data );
97     fputc( '\0', out );
98 }
99 
debug_string_read(FILE * in)100 static char * debug_string_read( FILE * in )
101 {
102     string buf[ 1 ];
103     int ch;
104     char * result;
105     string_new( buf );
106     while( ( ch = fgetc( in ) ) > 0 )
107     {
108         string_push_back( buf, (char)ch );
109     }
110     result = strdup( buf->value );
111     string_free( buf );
112     return result;
113 }
114 
debug_object_write(FILE * out,OBJECT * data)115 static void debug_object_write( FILE * out, OBJECT * data )
116 {
117     debug_string_write( out, object_str( data ) );
118 }
119 
debug_object_read(FILE * in)120 static OBJECT * debug_object_read( FILE * in )
121 {
122     string buf[ 1 ];
123     int ch;
124     OBJECT * result;
125     string_new( buf );
126     while( ( ch = fgetc( in ) ) > 0 )
127     {
128         string_push_back( buf, (char)ch );
129     }
130     result = object_new( buf->value );
131     string_free( buf );
132     return result;
133 }
134 
debug_int_write(FILE * out,int i)135 static void debug_int_write( FILE * out, int i )
136 {
137     fprintf( out, "%d", i );
138     fputc( '\0', out );
139 }
140 
debug_int_read(FILE * in)141 static int debug_int_read( FILE * in )
142 {
143     OBJECT * str = debug_object_read( in );
144     int result = atoi( object_str( str ) );
145     object_free( str );
146     return result;
147 }
148 
debug_list_write(FILE * out,LIST * l)149 static void debug_list_write( FILE * out, LIST * l )
150 {
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 ) )
154     {
155         debug_object_write( out, list_item( iter ) );
156     }
157 }
158 
debug_list_read(FILE * in)159 static LIST * debug_list_read( FILE * in )
160 {
161     int len;
162     int i;
163     int ch;
164     LIST * result = L0;
165     fscanf( in, "%d", &len );
166     ch = fgetc( in );
167     assert( ch == '\n' );
168     for ( i = 0; i < len; ++i )
169     {
170         result = list_push_back( result, debug_object_read( in ) );
171     }
172     return result;
173 }
174 
debug_lol_write(FILE * out,LOL * lol)175 static void debug_lol_write( FILE * out, LOL * lol )
176 {
177     int i;
178     debug_int_write( out, lol->count );
179     for ( i = 0; i < lol->count; ++i )
180     {
181         debug_list_write( out, lol_get( lol, i ) );
182     }
183 }
184 
debug_lol_read(FILE * in,LOL * lol)185 static void debug_lol_read( FILE * in, LOL * lol )
186 {
187     int count, i;
188     lol_init( lol );
189     count = debug_int_read( in );
190     for ( i = 0; i < count; ++i )
191     {
192         lol_add( lol, debug_list_read( in ) );
193     }
194 }
195 
debug_format_rulename(string * out,FRAME * frame)196 static void debug_format_rulename ( string * out, FRAME * frame )
197 {
198     const char * pos = strchr( frame->rulename, '.' );
199     if ( frame->module->class_module && pos )
200     {
201         string_copy( out, object_str( frame->module->name ) );
202         string_push_back( out, '.' );
203         string_append( out, pos + 1 );
204     }
205     else
206     {
207         string_copy( out, frame->rulename );
208     }
209 }
210 
debug_frame_write(FILE * out,FRAME * frame)211 static void debug_frame_write( FILE * out, FRAME * frame )
212 {
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 );
226 }
227 
228 /*
229  * The information passed to the debugger for
230  * a frame is slightly different from the FRAME
231  * struct.
232  */
233 typedef struct _frame_info
234 {
235     OBJECT * file;
236     int line;
237     OBJECT * fullname;
238     LOL args[ 1 ];
239     char * rulename;
240 } FRAME_INFO;
241 
debug_frame_info_free(FRAME_INFO * frame)242 static void debug_frame_info_free( FRAME_INFO * frame )
243 {
244     object_free( frame->file );
245     object_free( frame->fullname );
246     lol_free( frame->args );
247     free( frame->rulename );
248 }
249 
debug_frame_read(FILE * in,FRAME_INFO * frame)250 static void debug_frame_read( FILE * in, FRAME_INFO * frame )
251 {
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 );
257 }
258 
add_breakpoint(struct breakpoint elem)259 static int add_breakpoint( struct breakpoint elem )
260 {
261     if ( num_breakpoints == breakpoints_capacity )
262     {
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;
267     }
268     breakpoints[ num_breakpoints++ ] = elem;
269     return num_breakpoints;
270 }
271 
add_line_breakpoint(OBJECT * file,int line)272 static int add_line_breakpoint( OBJECT * file, int line )
273 {
274     struct breakpoint elem;
275     elem.file = file;
276     elem.bound_file = NULL;
277     elem.line = line;
278     elem.status = BREAKPOINT_ENABLED;
279     return add_breakpoint( elem );
280 }
281 
add_function_breakpoint(OBJECT * name)282 static int add_function_breakpoint( OBJECT * name )
283 {
284     struct breakpoint elem;
285     elem.file = name;
286     elem.bound_file = object_copy( name );
287     elem.line = -1;
288     elem.status = BREAKPOINT_ENABLED;
289     return add_breakpoint( elem );
290 }
291 
292 /*
293  * Checks whether there is an active breakpoint at the
294  * specified location.  Returns the breakpoint id
295  * or -1 if none is found.
296  */
handle_line_breakpoint(OBJECT * file,int line)297 static int handle_line_breakpoint( OBJECT * file, int line )
298 {
299     int i;
300     if ( file == NULL ) return 0;
301     for ( i = 0; i < num_breakpoints; ++i )
302     {
303         if ( breakpoints[ i ].bound_file == NULL && is_same_file( breakpoints[ i ].file, file ) )
304         {
305             breakpoints[ i ].bound_file = object_copy( file );
306         }
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 )
311         {
312             return i + 1;
313         }
314     }
315     return 0;
316 }
317 
handle_function_breakpoint(OBJECT * name)318 static int handle_function_breakpoint( OBJECT * name )
319 {
320     return handle_line_breakpoint( name, -1 );
321 }
322 
make_absolute_path(OBJECT * filename)323 static OBJECT * make_absolute_path( OBJECT * filename )
324 {
325     PATHNAME path1[ 1 ];
326     string buf[ 1 ];
327     OBJECT * result;
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 );
332     string_new( buf );
333     path_build( path1, buf );
334     result = object_new( buf->value );
335     string_free( buf );
336     return result;
337 }
338 
get_filename(OBJECT * path)339 static OBJECT * get_filename( OBJECT * path )
340 {
341     PATHNAME path1[ 1 ];
342     string buf[ 1 ];
343     OBJECT * result;
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;
348     string_new( buf );
349     path_build( path1, buf );
350     result = object_new( buf->value );
351     string_free( buf );
352     return result;
353 }
354 
is_same_file(OBJECT * file1,OBJECT * file2)355 static int is_same_file( OBJECT * file1, OBJECT * file2 )
356 {
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 );
375     return result;
376 }
377 
debug_print_source(OBJECT * filename,int line)378 static void debug_print_source( OBJECT * filename, int line )
379 {
380     FILE * file;
381 
382     if ( filename == NULL || object_equal( filename, constant_builtin ) )
383         return;
384 
385     file = fopen( object_str( filename ), "r" );
386     if ( file )
387     {
388         int ch;
389         int printing = 0;
390         int current_line = 1;
391         if ( line == 1 )
392         {
393             printing = 1;
394             printf( "%d\t", current_line );
395         }
396         while ( ( ch = fgetc( file ) ) != EOF )
397         {
398             if ( printing )
399                 fputc( ch, stdout );
400 
401             if ( ch == '\n' )
402             {
403                 if ( printing )
404                     break;
405 
406                 ++current_line;
407                 if ( current_line == line )
408                 {
409                     printing = 1;
410                     printf( "%d\t", current_line );
411                 }
412             }
413         }
414         fclose( file );
415     }
416 }
417 
debug_print_frame(FRAME * frame)418 static void debug_print_frame( FRAME * frame )
419 {
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 )
424     {
425         printf( "( " );
426         if ( frame->args->count )
427         {
428             lol_print( frame->args );
429             printf( " " );
430         }
431         printf( ") " );
432     }
433     printf( "at %s:%d", object_str( file ), frame->line );
434 }
435 
debug_mi_print_frame(FRAME * frame)436 static void debug_mi_print_frame( FRAME * frame )
437 {
438     OBJECT * fullname = make_absolute_path( frame->file );
439     printf( "frame={func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}",
440         frame->rulename,
441         object_str( frame->file ),
442         object_str( fullname ),
443         frame->line );
444     object_free( fullname );
445 }
446 
debug_print_frame_info(FRAME_INFO * frame)447 static void debug_print_frame_info( FRAME_INFO * frame )
448 {
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 )
453     {
454         printf( "( " );
455         if ( frame->args->count )
456         {
457             lol_print( frame->args );
458             printf( " " );
459         }
460         printf( ") " );
461     }
462     printf( "at %s:%d", object_str( file ), frame->line );
463 }
464 
debug_mi_print_frame_info(FRAME_INFO * frame)465 static void debug_mi_print_frame_info( FRAME_INFO * frame )
466 {
467     printf( "frame={func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}",
468         frame->rulename,
469         object_str( frame->file ),
470         object_str( frame->fullname ),
471         frame->line );
472 }
473 
debug_on_breakpoint(int id)474 static void debug_on_breakpoint( int id )
475 {
476     fputc( DEBUG_MSG_BREAKPOINT, command_output );
477     debug_int_write( command_output, id );
478     fflush( command_output );
479     debug_listen();
480 }
481 
debug_end_stepping(void)482 static void debug_end_stepping( void )
483 {
484     fputc( DEBUG_MSG_END_STEPPING, command_output );
485     fflush( command_output );
486     debug_listen();
487 }
488 
debug_on_instruction(FRAME * frame,OBJECT * file,int line)489 void debug_on_instruction( FRAME * frame, OBJECT * file, int line )
490 {
491     int breakpoint_id;
492     assert( debug_is_debugging() );
493     if ( debug_state == DEBUG_NEXT &&
494         ( debug_depth < 0 || ( debug_depth == 0 && debug_line != line ) ) )
495     {
496         debug_file = file;
497         debug_line = line;
498         debug_frame = frame;
499         debug_end_stepping();
500     }
501     else if ( debug_state == DEBUG_STEP && debug_line != line )
502     {
503         debug_file = file;
504         debug_line = line;
505         debug_frame = frame;
506         debug_end_stepping();
507     }
508     else if ( debug_state == DEBUG_FINISH && debug_depth < 0 )
509     {
510         debug_file = file;
511         debug_line = line;
512         debug_frame = frame;
513         debug_end_stepping();
514     }
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 ) ) )
518     {
519         debug_file = file;
520         debug_line = line;
521         debug_frame = frame;
522         debug_on_breakpoint( breakpoint_id );
523     }
524     else if ( ( debug_state == DEBUG_RUN || debug_state == DEBUG_FINISH ) &&
525         ( debug_depth < 0 || ( debug_depth == 0 && debug_line != line ) ) )
526     {
527         debug_file = NULL;
528         debug_line = 0;
529     }
530 }
531 
debug_on_enter_function(FRAME * frame,OBJECT * name,OBJECT * file,int line)532 void debug_on_enter_function( FRAME * frame, OBJECT * name, OBJECT * file, int line )
533 {
534     int breakpoint_id;
535     assert( debug_is_debugging() );
536     ++debug_depth;
537     if ( debug_state == DEBUG_STEP && file )
538     {
539         debug_file = file;
540         debug_line = line;
541         debug_frame = frame;
542         debug_end_stepping();
543     }
544     else if ( ( breakpoint_id = handle_function_breakpoint( name ) ) ||
545         ( breakpoint_id = handle_line_breakpoint( file, line ) ) )
546     {
547         debug_file = file;
548         debug_line = line;
549         debug_frame = frame;
550         debug_on_breakpoint( breakpoint_id );
551     }
552 }
553 
debug_on_exit_function(OBJECT * name)554 void debug_on_exit_function( OBJECT * name )
555 {
556     assert( debug_is_debugging() );
557     --debug_depth;
558     if ( debug_depth < 0 )
559     {
560         /* The current location is no longer valid
561            after we return from the containing function. */
562         debug_file = NULL;
563         debug_line = 0;
564     }
565 }
566 
567 #if NT
568 static HANDLE child_handle;
569 static DWORD child_pid;
570 #else
571 static int child_pid;
572 #endif
573 
debug_child_continue(int argc,const char ** argv)574 static void debug_child_continue( int argc, const char * * argv )
575 {
576     debug_state = DEBUG_RUN;
577     debug_depth = 0;
578 }
579 
debug_child_step(int argc,const char ** argv)580 static void debug_child_step( int argc, const char * * argv )
581 {
582     debug_state = DEBUG_STEP;
583     debug_depth = 0;
584 }
585 
debug_child_next(int argc,const char ** argv)586 static void debug_child_next( int argc, const char * * argv )
587 {
588     debug_state = DEBUG_NEXT;
589     debug_depth = 0;
590 }
591 
debug_child_finish(int argc,const char ** argv)592 static void debug_child_finish( int argc, const char * * argv )
593 {
594     debug_state = DEBUG_FINISH;
595     debug_depth = 0;
596 }
597 
debug_child_kill(int argc,const char ** argv)598 static void debug_child_kill( int argc, const char * * argv )
599 {
600     exit( 0 );
601 }
602 
debug_add_breakpoint(const char * name)603 static int debug_add_breakpoint( const char * name )
604 {
605     const char * file_ptr = name;
606     const char * ptr = strrchr( file_ptr, ':' );
607     if ( ptr )
608     {
609         char * end;
610         long line = strtoul( ptr + 1, &end, 10 );
611         if ( line > 0 && line <= INT_MAX && end != ptr + 1 && *end == 0 )
612         {
613             OBJECT * file = object_new_range( file_ptr,  ptr - file_ptr );
614             return add_line_breakpoint( file, line );
615         }
616         else
617         {
618             OBJECT * name = object_new( file_ptr );
619             return add_function_breakpoint( name );
620         }
621     }
622     else
623     {
624         OBJECT * name = object_new( file_ptr );
625         return add_function_breakpoint( name );
626     }
627 }
628 
debug_child_break(int argc,const char ** argv)629 static void debug_child_break( int argc, const char * * argv )
630 {
631     if ( argc == 2 )
632     {
633         debug_add_breakpoint( argv[ 1 ] );
634     }
635 }
636 
get_breakpoint_by_name(const char * name)637 static int get_breakpoint_by_name( const char * name )
638 {
639     int result;
640     const char * file_ptr = name;
641     const char * ptr = strrchr( file_ptr, ':' );
642     if ( ptr )
643     {
644         char * end;
645         long line = strtoul( ptr + 1, &end, 10 );
646         if ( line > 0 && line <= INT_MAX && end != ptr + 1 && *end == 0 )
647         {
648             OBJECT * file = object_new_range( file_ptr,  ptr - file_ptr );
649             result = handle_line_breakpoint( file, line );
650             object_free( file );
651         }
652         else
653         {
654             OBJECT * name = object_new( file_ptr );
655             result = handle_function_breakpoint( name );
656             object_free( name );
657         }
658     }
659     else
660     {
661         OBJECT * name = object_new( file_ptr );
662         result = handle_function_breakpoint( name );
663         object_free( name );
664     }
665     return result;
666 }
667 
debug_child_disable(int argc,const char ** argv)668 static void debug_child_disable( int argc, const char * * argv )
669 {
670     if ( argc == 2 )
671     {
672         int id = atoi( argv[ 1 ] );
673         if ( id < 1 || id > num_breakpoints )
674             return;
675         --id;
676         if ( breakpoints[ id ].status == BREAKPOINT_DELETED )
677             return;
678         breakpoints[ id ].status = BREAKPOINT_DISABLED;
679     }
680 }
681 
debug_child_enable(int argc,const char ** argv)682 static void debug_child_enable( int argc, const char * * argv )
683 {
684     if ( argc == 2 )
685     {
686         int id = atoi( argv[ 1 ] );
687         if ( id < 1 || id > num_breakpoints )
688             return;
689         --id;
690         if ( breakpoints[ id ].status == BREAKPOINT_DELETED )
691             return;
692         breakpoints[ id ].status = BREAKPOINT_ENABLED;
693     }
694 }
695 
debug_child_delete(int argc,const char ** argv)696 static void debug_child_delete( int argc, const char * * argv )
697 {
698     if ( argc == 2 )
699     {
700         int id = atoi( argv[ 1 ] );
701         if ( id < 1 || id > num_breakpoints )
702             return;
703         --id;
704         breakpoints[ id ].status = BREAKPOINT_DELETED;
705     }
706 }
707 
debug_child_print(int argc,const char ** argv)708 static void debug_child_print( int argc, const char * * argv )
709 {
710     FRAME * saved_frame;
711     OBJECT * saved_file;
712     int saved_line;
713     string buf[ 1 ];
714     const char * lines[ 2 ];
715     int i;
716     FRAME new_frame = *debug_frame;
717     /* Save the current file/line, since running parse_string
718      * will likely change it.
719      */
720     saved_frame = debug_frame;
721     saved_file = debug_file;
722     saved_line = debug_line;
723     string_new( buf );
724     string_append( buf, "__DEBUG_PRINT_HELPER__" );
725     for ( i = 1; i < argc; ++i )
726     {
727         string_push_back( buf, ' ' );
728         string_append( buf, argv[ i ] );
729     }
730     string_append( buf, " ;\n" );
731     lines[ 0 ] = buf->value;
732     lines[ 1 ] = NULL;
733     parse_string( constant_builtin, lines, &new_frame );
734     string_free( buf );
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;
740 }
741 
debug_child_frame(int argc,const char ** argv)742 static void debug_child_frame( int argc, const char * * argv )
743 {
744     if ( argc == 2 )
745     {
746         debug_selected_frame_number = atoi( argv[ 1 ] );
747     }
748     else
749     {
750         assert( !"Wrong number of arguments to frame." );
751     }
752 }
753 
debug_child_info(int argc,const char ** argv)754 static void debug_child_info( int argc, const char * * argv )
755 {
756     if ( strcmp( argv[ 1 ], "locals" ) == 0 )
757     {
758         LIST * locals = L0;
759         if ( debug_frame->function )
760         {
761             locals = function_get_variables( (FUNCTION*)debug_frame->function );
762         }
763         debug_list_write( command_output, locals );
764         fflush( command_output );
765         list_free( locals );
766     }
767     else if ( strcmp( argv[ 1 ], "frame" ) == 0 )
768     {
769         int frame_number = debug_selected_frame_number;
770         int i;
771         OBJECT * fullname;
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 ] );
777 
778         for ( i = 0; i < frame_number; ++i ) frame = frame->prev;
779 
780         debug_frame_write( command_output, frame );
781     }
782     else if ( strcmp( argv[ 1 ], "depth" ) == 0 )
783     {
784         int result = 0;
785         FRAME * frame = debug_frame;
786         while ( frame )
787         {
788             frame = frame->prev;
789             ++result;
790         }
791         fprintf( command_output, "%d", result );
792         fputc( '\0', command_output );
793         fflush( command_output );
794     }
795 }
796 
797 /* Commands for the parent. */
798 
799 #ifdef NT
800 
get_module_filename(string * out)801 static int get_module_filename( string * out )
802 {
803     DWORD result;
804     string_reserve( out, 256 + 1 );
805     string_truncate( out, 256 );
806     while( ( result = GetModuleFileName( NULL, out->value, out->size ) ) == out->size )
807     {
808         string_reserve( out, out->size * 2 + 1);
809         string_truncate( out, out->size * 2 );
810     }
811     if ( result != 0 )
812     {
813         string_truncate( out, result );
814         return 1;
815     }
816     else
817     {
818         return 0;
819     }
820 }
821 
822 #endif
823 
824 static struct command_elem child_commands[] =
825 {
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 },
838     { NULL, NULL }
839 };
840 
debug_mi_error(const char * message)841 static void debug_mi_error( const char * message )
842 {
843     debug_mi_format_token();
844     printf( "^error,msg=\"%s\"\n(gdb) \n", message );
845 }
846 
debug_error_(const char * message)847 static void debug_error_( const char * message )
848 {
849     if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
850     {
851         printf( "%s\n", message );
852     }
853     else if ( debug_interface == DEBUG_INTERFACE_MI )
854     {
855         debug_mi_error( message );
856     }
857 }
858 
debug_format_message(const char * format,va_list vargs)859 static const char * debug_format_message( const char * format, va_list vargs )
860 {
861     char * buf;
862     int result;
863     int sz = 80;
864     for ( ; ; )
865     {
866         va_list args;
867         buf = (char *)malloc( sz );
868         if ( !buf )
869             return 0;
870         #ifndef va_copy
871         args = vargs;
872         #else
873         va_copy( args, vargs );
874         #endif
875         #if defined(_MSC_VER) && (_MSC_VER <= 1310)
876         result = _vsnprintf( buf, sz, format, args );
877         #else
878         result = vsnprintf( buf, sz, format, args );
879         #endif
880         va_end( args );
881         if ( 0 <= result && result < sz )
882 	    return buf;
883         free( buf );
884         if ( result < 0 )
885             return 0;
886         sz = result + 1;
887     }
888 }
889 
debug_error(const char * format,...)890 static void debug_error( const char * format, ... )
891 {
892     va_list args;
893     const char * msg;
894     va_start( args, format );
895     msg = debug_format_message( format, args );
896     va_end( args );
897     if ( !msg )
898     {
899         debug_error_( "Failed formatting error message." );
900         return;
901     }
902     debug_error_( msg );
903     free( ( void * )msg );
904 }
905 
debug_parent_child_exited(int pid,int exit_code)906 static void debug_parent_child_exited( int pid, int exit_code )
907 {
908     if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
909     {
910         printf( "Child %d exited with status %d\n", (int)child_pid, (int)exit_code );
911     }
912     else if ( debug_interface == DEBUG_INTERFACE_MI )
913     {
914         if ( exit_code == 0 )
915             printf( "*stopped,reason=\"exited-normally\"\n(gdb) \n" );
916         else
917             printf( "*stopped,reason=\"exited\",exit-code=\"%d\"\n(gdb) \n", exit_code );
918     }
919     else
920     {
921         assert( !"Wrong value of debug_interface." );
922     }
923 }
924 
debug_parent_child_signalled(int pid,int sigid)925 static void debug_parent_child_signalled( int pid, int sigid )
926 {
927 
928     if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
929     {
930         printf( "Child %d exited on signal %d\n", child_pid, sigid );
931     }
932     else if ( debug_interface == DEBUG_INTERFACE_MI )
933     {
934         const char * name = "unknown";
935         const char * meaning = "unknown";
936         switch( sigid )
937         {
938         case SIGINT: name = "SIGINT"; meaning = "Interrupt"; break;
939         }
940         printf("*stopped,reason=\"exited-signalled\",signal-name=\"%s\",signal-meaning=\"%s\"\n(gdb) \n", name, meaning);
941     }
942     else
943     {
944         assert( !"Wrong value of debug_interface." );
945     }
946 }
947 
debug_parent_on_breakpoint(void)948 static void debug_parent_on_breakpoint( void )
949 {
950     FRAME_INFO base;
951     int id;
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 )
957     {
958         printf( "Breakpoint %d, ", id );
959         debug_print_frame_info( &base );
960         printf( "\n" );
961         debug_print_source( base.file, base.line );
962     }
963     else if ( debug_interface == DEBUG_INTERFACE_MI )
964     {
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" );
969     }
970     else
971     {
972         assert( !"Wrong value if debug_interface" );
973     }
974     fflush( stdout );
975 }
976 
debug_parent_on_end_stepping(void)977 static void debug_parent_on_end_stepping( void )
978 {
979     FRAME_INFO base;
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 )
984     {
985         debug_print_source( base.file, base.line );
986     }
987     else
988     {
989         printf( "*stopped,reason=\"end-stepping-range\"," );
990         debug_mi_print_frame_info( &base );
991         printf( ",thread-id=\"1\"" );
992         printf( "\n(gdb) \n" );
993     }
994     fflush( stdout );
995 }
996 
997 /* Waits for events from the child. */
debug_parent_wait(int print_message)998 static void debug_parent_wait( int print_message )
999 {
1000     int ch = fgetc( command_child );
1001     if ( ch == DEBUG_MSG_BREAKPOINT )
1002     {
1003         debug_parent_on_breakpoint();
1004     }
1005     else if ( ch == DEBUG_MSG_END_STEPPING )
1006     {
1007         debug_parent_on_end_stepping();
1008     }
1009     else if ( ch == DEBUG_MSG_SETUP )
1010     {
1011         /* FIXME: This is handled in the caller, but it would make
1012            more sense to handle it here. */
1013         return;
1014     }
1015     else if ( ch == EOF )
1016     {
1017 #if NT
1018         WaitForSingleObject( child_handle, INFINITE );
1019         if ( print_message )
1020         {
1021             DWORD exit_code;
1022             GetExitCodeProcess( child_handle, &exit_code );
1023             debug_parent_child_exited( (int)child_pid, (int)exit_code );
1024         }
1025         CloseHandle( child_handle );
1026 #else
1027         int status;
1028         int pid;
1029         while ( ( pid = waitpid( child_pid, &status, 0 ) ) == -1 )
1030             if ( errno != EINTR )
1031                 break;
1032         if ( print_message )
1033         {
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 ) );
1038         }
1039 #endif
1040         fclose( command_child );
1041         fclose( command_output );
1042         debug_state = DEBUG_NO_CHILD;
1043     }
1044 }
1045 
1046 /* Prints the message for starting the child. */
debug_parent_run_print(int argc,const char ** argv)1047 static void debug_parent_run_print( int argc, const char * * argv )
1048 {
1049     int i;
1050     extern char const * saved_argv0;
1051     char * name = executable_path( saved_argv0 );
1052     printf( "Starting program: %s", name );
1053     free( name );
1054     for ( i = 1; i < argc; ++i )
1055     {
1056         printf( " %s", argv[ i ] );
1057     }
1058     printf( "\n" );
1059     fflush( stdout );
1060 }
1061 
1062 #if NT
1063 
debug_init_handles(const char * in,const char * out)1064 void debug_init_handles( const char * in, const char * out )
1065 {
1066     HANDLE read_handle;
1067     int read_fd;
1068     HANDLE write_handle;
1069     int write_fd;
1070 
1071     sscanf( in, "%p", &read_handle );
1072     read_fd = _open_osfhandle( (intptr_t)read_handle, _O_RDONLY );
1073     command_input = _fdopen( read_fd, "r" );
1074 
1075     sscanf( out, "%p", &write_handle );
1076     write_fd = _open_osfhandle( (intptr_t)write_handle, _O_WRONLY );
1077     command_output = _fdopen( write_fd, "w" );
1078 
1079     command_array = child_commands;
1080 
1081     /* Handle the initial setup */
1082     /* wake up the parent */
1083     fputc( DEBUG_MSG_SETUP, command_output );
1084     debug_listen();
1085 }
1086 
init_parent_handles(HANDLE out,HANDLE in)1087 static void init_parent_handles( HANDLE out, HANDLE in )
1088 {
1089     int read_fd, write_fd;
1090 
1091     command_child = _fdopen( _open_osfhandle( (intptr_t)in, _O_RDONLY ), "r" );
1092     command_output = _fdopen( _open_osfhandle( (intptr_t)out, _O_WRONLY ), "w" );
1093 }
1094 
debug_parent_copy_breakpoints(void)1095 static void debug_parent_copy_breakpoints( void )
1096 {
1097     int i;
1098     for ( i = 0; i < num_breakpoints; ++i )
1099     {
1100         fprintf( command_output, "break %s", object_str( breakpoints[ i ].file ) );
1101         if ( breakpoints[ i ].line != -1 )
1102         {
1103             fprintf( command_output, ":%d", breakpoints[ i ].line );
1104         }
1105         fprintf( command_output, "\n" );
1106 
1107         switch ( breakpoints[ i ].status )
1108         {
1109         case BREAKPOINT_ENABLED:
1110             break;
1111         case BREAKPOINT_DISABLED:
1112             fprintf( command_output, "disable %d\n", i + 1 );
1113             break;
1114         case BREAKPOINT_DELETED:
1115             fprintf( command_output, "delete %d\n", i + 1 );
1116             break;
1117         default:
1118             assert( !"Wrong breakpoint status." );
1119         }
1120     }
1121     fflush( command_output );
1122 }
1123 
1124 #endif
1125 
debug_start_child(int argc,const char ** argv)1126 static void debug_start_child( int argc, const char * * argv )
1127 {
1128 #if NT
1129     char buf[ 80 ];
1130     HANDLE pipe1[ 2 ];
1131     HANDLE pipe2[ 2 ];
1132     string self[ 1 ];
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,
1137         0, 0, 0, 0, 0, 0 };
1138     assert( debug_state == DEBUG_NO_CHILD );
1139     if ( ! CreatePipe( &pipe1[ 0 ], &pipe1[ 1 ], &sa, 0 ) )
1140     {
1141         printf("internal error: CreatePipe:1: 0x$08x\n", GetLastError());
1142         return;
1143     }
1144     if ( ! CreatePipe( &pipe2[ 0 ], &pipe2[ 1 ], &sa, 0 ) )
1145     {
1146         printf("internal error: CreatePipe:2: 0x$08x\n", GetLastError());
1147         CloseHandle( pipe1[ 0 ] );
1148         CloseHandle( pipe1[ 1 ] );
1149         return;
1150     }
1151     string_new( self );
1152     if ( ! get_module_filename( self ) )
1153     {
1154         printf("internal error\n");
1155         CloseHandle( pipe1[ 0 ] );
1156         CloseHandle( pipe1[ 1 ] );
1157         CloseHandle( pipe2[ 0 ] );
1158         CloseHandle( pipe2[ 1 ] );
1159         return;
1160     }
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. */
1171 	{
1172         int i;
1173         for ( i = 1; i < argc; ++i )
1174         {
1175             string_push_back( command_line, ' ' );
1176             string_append( command_line, argv[ i ] );
1177         }
1178     }
1179     SetHandleInformation( pipe1[ 1 ], HANDLE_FLAG_INHERIT, 0 );
1180     SetHandleInformation( pipe2[ 0 ], HANDLE_FLAG_INHERIT, 0 );
1181     if ( ! CreateProcess(
1182         self->value,
1183         command_line->value,
1184         NULL,
1185         NULL,
1186         TRUE,
1187         0,
1188         NULL,
1189         NULL,
1190         &si,
1191         &pi
1192         ) )
1193     {
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 );
1201         return;
1202     }
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 );
1210 
1211     debug_state = DEBUG_RUN;
1212 
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 );
1218 #else
1219     int pipe1[2];
1220     int pipe2[2];
1221     int write_fd;
1222     int read_fd;
1223     int pid;
1224     int i;
1225     assert( debug_state == DEBUG_NO_CHILD );
1226     if (pipe(pipe1) == -1)
1227     {
1228         printf("internal error: pipe:1: %s\n", strerror(errno));
1229         return;
1230     }
1231     if (pipe(pipe2) == -1)
1232     {
1233         close( pipe1[ 0 ] );
1234         close( pipe1[ 1 ] );
1235         printf("internal error: pipe:2: %s\n", strerror(errno));
1236         return;
1237     }
1238 
1239     pid = fork();
1240     if ( pid == -1 )
1241     {
1242         /* error */
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));
1248         return;
1249     }
1250     else if ( pid == 0 )
1251     {
1252         /* child */
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 );
1265     }
1266     else
1267     {
1268         /* parent */
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" );
1275         child_pid = pid;
1276     }
1277     debug_state = DEBUG_RUN;
1278 #endif
1279 }
1280 
debug_parent_run(int argc,const char ** argv)1281 static void debug_parent_run( int argc, const char * * argv )
1282 {
1283     if ( debug_state == DEBUG_RUN )
1284     {
1285         fprintf( command_output, "kill\n" );
1286         fflush( command_output );
1287         debug_parent_wait( 1 );
1288     }
1289     debug_parent_run_print( argc, argv );
1290     if ( debug_interface == DEBUG_INTERFACE_MI )
1291     {
1292         printf( "=thread-created,id=\"1\",group-id=\"i1\"\n" );
1293         debug_mi_format_token();
1294         printf( "^running\n(gdb) \n" );
1295     }
1296     debug_start_child( argc, argv );
1297     debug_parent_wait( 1 );
1298 }
1299 
debug_parent_forward_nowait(int argc,const char ** argv,int print_message,int require_child)1300 static int debug_parent_forward_nowait( int argc, const char * * argv, int print_message, int require_child )
1301 {
1302     int i;
1303     if ( debug_state == DEBUG_NO_CHILD )
1304     {
1305         if ( require_child )
1306             printf( "The program is not being run.\n" );
1307         return 1;
1308     }
1309     fputs( argv[ 0 ], command_output );
1310     for( i = 1; i < argc; ++i )
1311     {
1312         fputc( ' ', command_output );
1313         fputs( argv[ i ], command_output );
1314     }
1315     fputc( '\n', command_output );
1316     fflush( command_output );
1317     return 0;
1318 }
1319 
1320 /* FIXME: This function should be eliminated when I finish all stdout to the parent. */
debug_parent_forward(int argc,const char ** argv,int print_message,int require_child)1321 static void debug_parent_forward( int argc, const char * * argv, int print_message, int require_child )
1322 {
1323     if ( debug_parent_forward_nowait( argc, argv, print_message, require_child ) != 0 )
1324     {
1325         return;
1326     }
1327     debug_parent_wait( print_message );
1328 }
1329 
debug_parent_continue(int argc,const char ** argv)1330 static void debug_parent_continue( int argc, const char * * argv )
1331 {
1332     if ( argc > 1 )
1333     {
1334         debug_error( "Too many arguments to continue." );
1335         return;
1336     }
1337     if ( debug_interface == DEBUG_INTERFACE_MI )
1338     {
1339         debug_mi_format_token();
1340         printf( "^running\n(gdb) \n" );
1341         fflush( stdout );
1342     }
1343     debug_parent_forward( 1, argv, 1, 1 );
1344 }
1345 
debug_parent_kill(int argc,const char ** argv)1346 static void debug_parent_kill( int argc, const char * * argv )
1347 {
1348     if ( argc > 1 )
1349     {
1350         debug_error( "Too many arguments to kill." );
1351         return;
1352     }
1353     if ( debug_interface == DEBUG_INTERFACE_MI )
1354     {
1355         debug_mi_format_token();
1356         printf( "^done\n(gdb) \n" );
1357         fflush( stdout );
1358     }
1359     debug_parent_forward( 1, argv, 0, 1 );
1360 }
1361 
debug_parent_step(int argc,const char ** argv)1362 static void debug_parent_step( int argc, const char * * argv )
1363 {
1364     if ( argc > 1 )
1365     {
1366         debug_error( "Too many arguments to step." );
1367         return;
1368     }
1369     if ( debug_interface == DEBUG_INTERFACE_MI )
1370     {
1371         debug_mi_format_token();
1372         printf( "^running\n(gdb) \n" );
1373         fflush( stdout );
1374     }
1375     debug_parent_forward( 1, argv, 1, 1 );
1376 }
1377 
debug_parent_next(int argc,const char ** argv)1378 static void debug_parent_next( int argc, const char * * argv )
1379 {
1380     if ( argc > 1 )
1381     {
1382         debug_error( "Too many arguments to next." );
1383         return;
1384     }
1385     if ( debug_interface == DEBUG_INTERFACE_MI )
1386     {
1387         debug_mi_format_token();
1388         printf( "^running\n(gdb) \n" );
1389         fflush( stdout );
1390     }
1391     debug_parent_forward( 1, argv, 1, 1 );
1392 }
1393 
debug_parent_finish(int argc,const char ** argv)1394 static void debug_parent_finish( int argc, const char * * argv )
1395 {
1396     if ( argc > 1 )
1397     {
1398         debug_error( "Too many arguments to finish." );
1399         return;
1400     }
1401     if ( debug_interface == DEBUG_INTERFACE_MI )
1402     {
1403         debug_mi_format_token();
1404         printf( "^running\n(gdb) \n" );
1405         fflush( stdout );
1406     }
1407     debug_parent_forward( 1, argv, 1, 1 );
1408 }
1409 
debug_parent_break(int argc,const char ** argv)1410 static void debug_parent_break( int argc, const char * * argv )
1411 {
1412     int id;
1413     if ( argc < 2 )
1414     {
1415         debug_error( "Missing argument to break." );
1416         return;
1417     }
1418     else if ( argc > 2 )
1419     {
1420         debug_error( "Too many arguments to break." );
1421         return;
1422     }
1423     id = debug_add_breakpoint( argv[ 1 ] );
1424     debug_parent_forward_nowait( argc, argv, 1, 0 );
1425     if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
1426     {
1427         printf( "Breakpoint %d set at %s\n", id, argv[ 1 ] );
1428     }
1429     else if ( debug_interface == DEBUG_INTERFACE_MI )
1430     {
1431         debug_mi_format_token();
1432         printf( "^done\n(gdb) \n" );
1433     }
1434     else
1435     {
1436         assert( !"wrong value of debug_interface." );
1437     }
1438 }
1439 
check_breakpoint_fn_args(int argc,const char ** argv)1440 int check_breakpoint_fn_args( int argc, const char * * argv )
1441 {
1442     if ( argc < 2 )
1443     {
1444         debug_error( "Missing argument to %s.", argv[ 0 ] );
1445         return 0;
1446     }
1447     else if ( argc > 2 )
1448     {
1449         debug_error( "Too many arguments to %s.", argv[ 0 ] );
1450         return 0;
1451     }
1452     else
1453     {
1454         char * end;
1455         long x = strtol( argv[ 1 ], &end, 10 );
1456         if ( *end )
1457         {
1458             debug_error( "Invalid breakpoint number %s.", argv[ 1 ] );
1459             return 0;
1460         }
1461         if ( x < 1 || x > num_breakpoints || breakpoints[ x - 1 ].status == BREAKPOINT_DELETED )
1462         {
1463             debug_error( "Unknown breakpoint %s.", argv[ 1 ] );
1464             return 0;
1465         }
1466     }
1467     return 1;
1468 }
1469 
debug_parent_disable(int argc,const char ** argv)1470 static void debug_parent_disable( int argc, const char * * argv )
1471 {
1472     if ( ! check_breakpoint_fn_args( argc, argv ) )
1473     {
1474         return;
1475     }
1476     debug_child_disable( argc, argv );
1477     debug_parent_forward_nowait( 2, argv, 1, 0 );
1478     if ( debug_interface == DEBUG_INTERFACE_MI )
1479     {
1480         debug_mi_format_token();
1481         printf( "^done\n(gdb) \n" );
1482     }
1483 }
1484 
debug_parent_enable(int argc,const char ** argv)1485 static void debug_parent_enable( int argc, const char * * argv )
1486 {
1487     if ( ! check_breakpoint_fn_args( argc, argv ) )
1488     {
1489         return;
1490     }
1491     debug_child_enable( argc, argv );
1492     debug_parent_forward_nowait( 2, argv, 1, 0 );
1493     if ( debug_interface == DEBUG_INTERFACE_MI )
1494     {
1495         debug_mi_format_token();
1496         printf( "^done\n(gdb) \n" );
1497     }
1498 }
1499 
debug_parent_delete(int argc,const char ** argv)1500 static void debug_parent_delete( int argc, const char * * argv )
1501 {
1502     if ( ! check_breakpoint_fn_args( argc, argv ) )
1503     {
1504         return;
1505     }
1506     debug_child_delete( argc, argv );
1507     debug_parent_forward_nowait( 2, argv, 1, 0 );
1508     if ( debug_interface == DEBUG_INTERFACE_MI )
1509     {
1510         debug_mi_format_token();
1511         printf( "^done\n(gdb) \n" );
1512     }
1513 }
1514 
debug_parent_clear(int argc,const char ** argv)1515 static void debug_parent_clear( int argc, const char * * argv )
1516 {
1517     char buf[ 16 ];
1518     const char * new_args[ 2 ];
1519     int id;
1520     if ( argc < 2 )
1521     {
1522         debug_error( "Missing argument to clear." );
1523         return;
1524     }
1525     else if ( argc > 2 )
1526     {
1527         debug_error( "Too many arguments to clear." );
1528         return;
1529     }
1530     id = get_breakpoint_by_name( argv[ 1 ] );
1531     if ( id == 0 )
1532     {
1533         debug_error( "No breakpoint at %s.", argv[ 1 ] );
1534         return;
1535     }
1536 
1537     if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
1538     {
1539         printf( "Deleted breakpoint %d\n", id );
1540     }
1541 
1542     sprintf( buf, "%d", id );
1543     new_args[ 0 ] = "delete";
1544     new_args[ 1 ] = buf;
1545     debug_parent_delete( 2, new_args );
1546 }
1547 
debug_parent_print(int argc,const char ** argv)1548 static void debug_parent_print( int argc, const char * * argv )
1549 {
1550     LIST * result;
1551     if ( debug_parent_forward_nowait( argc, argv, 1, 1 ) != 0 )
1552     {
1553         return;
1554     }
1555     result = debug_list_read( command_child );
1556 
1557     if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
1558     {
1559         list_print( result );
1560         printf( "\n" );
1561     }
1562     else if ( debug_interface == DEBUG_INTERFACE_MI )
1563     {
1564         printf( "~\"$1 = " );
1565         list_print( result );
1566         printf( "\"\n~\"\\n\"\n" );
1567         debug_mi_format_token();
1568         printf( "^done\n(gdb) \n" );
1569     }
1570 
1571     list_free( result );
1572 }
1573 
debug_parent_backtrace(int argc,const char ** argv)1574 static void debug_parent_backtrace( int argc, const char * * argv )
1575 {
1576     const char * new_args[ 3 ];
1577     OBJECT * depth_str;
1578     int depth;
1579     int i;
1580     FRAME_INFO frame;
1581 
1582     if ( debug_state == DEBUG_NO_CHILD )
1583     {
1584         debug_error( "The program is not being run." );
1585         return;
1586     }
1587 
1588     new_args[ 0 ] = "info";
1589     new_args[ 1 ] = "frame";
1590 
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 );
1596 
1597     for ( i = 0; i < depth; ++i )
1598     {
1599         char buf[ 16 ];
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 );
1606         printf( "\n" );
1607     }
1608     fflush( stdout );
1609 }
1610 
debug_parent_quit(int argc,const char ** argv)1611 static void debug_parent_quit( int argc, const char * * argv )
1612 {
1613     if ( debug_state == DEBUG_RUN )
1614     {
1615         fprintf( command_output, "kill\n" );
1616         fflush( command_output );
1617         debug_parent_wait( 0 );
1618     }
1619     exit( 0 );
1620 }
1621 
1622 static const char * const help_text[][2] =
1623 {
1624     {
1625         "run",
1626         "run <args>\n"
1627         "Creates a new b2 child process passing <args> on the command line."
1628         "  Terminates\nthe current child (if any).\n"
1629     },
1630     {
1631         "continue",
1632         "continue\nContinue debugging\n"
1633     },
1634     {
1635         "step",
1636         "step\nContinue to the next statement\n"
1637     },
1638     {
1639         "next",
1640         "next\nContinue to the next line in the current frame\n"
1641     },
1642     {
1643         "finish",
1644         "finish\nContinue to the end of the current frame\n"
1645     },
1646     {
1647         "break",
1648         "break <location>\n"
1649         "Sets a breakpoint at <location>.  <location> can be either a the name of a\nfunction or <filename>:<lineno>\n"
1650     },
1651     {
1652         "disable",
1653         "disable <breakpoint>\nDisable a breakpoint\n"
1654     },
1655     {
1656         "enable",
1657         "enable <breakpoint>\nEnable a breakpoint\n"
1658     },
1659     {
1660         "delete",
1661         "delete <breakpoint>\nDelete a breakpoint\n"
1662     },
1663     {
1664         "clear",
1665         "clear <location>\nDelete the breakpoint at <location>\n"
1666     },
1667     {
1668         "print",
1669         "print <expression>\nDisplay the value of <expression>\n"
1670     },
1671     {
1672         "backtrace",
1673         "backtrace\nDisplay the call stack\n"
1674     },
1675     {
1676         "kill",
1677         "kill\nTerminate the child\n"
1678     },
1679     {
1680         "quit",
1681         "quit\nExit the debugger\n"
1682     },
1683     {
1684         "help",
1685         "help\nhelp <command>\nShow help for debugger commands.\n"
1686     },
1687     { 0, 0 }
1688 };
1689 
debug_parent_help(int argc,const char ** argv)1690 static void debug_parent_help( int argc, const char * * argv )
1691 {
1692     if ( argc == 1 )
1693     {
1694         printf(
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"
1705             );
1706         printf(
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"
1712             );
1713     }
1714     else if ( argc == 2 )
1715     {
1716         int i;
1717         for ( i = 0; help_text[ i ][ 0 ]; ++i )
1718         {
1719             if ( strcmp( argv[ 1 ], help_text[ i ][ 0 ] ) == 0 )
1720             {
1721                 printf( "%s", help_text[ i ][ 1 ] );
1722                 return;
1723             }
1724         }
1725         printf( "No command named %s\n", argv[ 1 ] );
1726     }
1727 }
1728 
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 );
1758 
1759 static struct command_elem parent_commands[] =
1760 {
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 },
1805     { NULL, NULL }
1806 };
1807 
debug_mi_format_token(void)1808 static void debug_mi_format_token( void )
1809 {
1810     if ( current_token != 0 )
1811     {
1812         printf( "%d", current_token );
1813     }
1814 }
1815 
debug_mi_format_breakpoint(int id)1816 static void debug_mi_format_breakpoint( int id )
1817 {
1818     struct breakpoint * ptr = &breakpoints[ id - 1 ];
1819     printf( "bkpt={" );
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" );
1824     /* addr */
1825     if ( ptr->line == -1 )
1826     {
1827         printf( ",func=\"%s\"", object_str( ptr->file ) );
1828     }
1829     else
1830     {
1831         printf( ",file=\"%s\"", object_str( ptr->file ) );
1832         printf( ",line=\"%d\"", ptr->line );
1833         printf( ",fullname=\"%s\"", object_str( ptr->file ) );
1834     }
1835     /* fullname */
1836     /* times */
1837     printf( "" );
1838     printf( "}" );
1839 }
1840 
breakpoint_id_parse(const char * name)1841 static int breakpoint_id_parse( const char * name )
1842 {
1843     int id = atoi( name );
1844     if ( id > num_breakpoints || id < 1 || breakpoints[ id ].status == BREAKPOINT_DELETED )
1845         return -1;
1846     return id;
1847 }
1848 
debug_mi_break_after(int argc,const char ** argv)1849 static void debug_mi_break_after( int argc, const char * * argv )
1850 {
1851     int id;
1852     int count;
1853     --argc;
1854     ++argv;
1855     if ( argc > 0 && strcmp( argv[ 0 ], "--" ) == 0 )
1856     {
1857         ++argv;
1858         --argc;
1859     }
1860     if ( argc < 2 )
1861     {
1862         debug_mi_error( "not enough arguments for -break-after." );
1863         return;
1864     }
1865     else if ( argc > 2 )
1866     {
1867         debug_mi_error( "too many arguments for -break-after." );
1868         return;
1869     }
1870     id = atoi( argv[ 0 ] );
1871     count = atoi( argv[ 1 ] );
1872     /* FIXME: set ignore count */
1873 }
1874 
debug_mi_break_insert(int argc,const char ** argv)1875 static void debug_mi_break_insert( int argc, const char * * argv )
1876 {
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... */
1881     int disabled = 0;
1882     int tracepoint = 0; /* unsupported */
1883     int thread_id = 0;
1884     int ignore_count = 0;
1885     const char * condition; /* FIXME: not supported yet */
1886     const char * location;
1887     int id;
1888     for ( --argc, ++argv; argc; --argc, ++argv )
1889     {
1890         if ( strcmp( *argv, "-t" ) == 0 )
1891         {
1892             temporary = 1;
1893         }
1894         else if ( strcmp( *argv, "-h" ) == 0 )
1895         {
1896             hardware = 1;
1897         }
1898         else if ( strcmp( *argv, "-f" ) == 0 )
1899         {
1900             force = 1;
1901         }
1902         else if ( strcmp( *argv, "-d" ) == 0 )
1903         {
1904             disabled = 1;
1905         }
1906         else if ( strcmp( *argv, "-a" ) == 0 )
1907         {
1908             tracepoint = 1;
1909         }
1910         else if ( strcmp( *argv, "-c" ) == 0 )
1911         {
1912             if ( argc < 2 )
1913             {
1914                 debug_mi_error( "Missing argument for -c." );
1915                 return;
1916             }
1917 
1918             condition = argv[ 1 ];
1919             --argc;
1920             ++argv;
1921         }
1922         else if ( strcmp( *argv, "-i" ) == 0 )
1923         {
1924             if ( argc < 2 )
1925             {
1926                 debug_mi_error( "Missing argument for -i." );
1927                 return;
1928             }
1929 
1930             ignore_count = atoi( argv[ 1 ] );
1931             --argc;
1932             ++argv;
1933         }
1934         else if ( strcmp( *argv, "-p" ) == 0 )
1935         {
1936             if ( argc < 2 )
1937             {
1938                 debug_mi_error( "Missing argument for -p." );
1939                 return;
1940             }
1941 
1942             thread_id = atoi( argv[ 1 ] );
1943             --argc;
1944             ++argv;
1945         }
1946         else if ( strcmp( *argv, "--" ) == 0 )
1947         {
1948             --argc;
1949             ++argv;
1950             break;
1951         }
1952         else if ( **argv != '-' )
1953         {
1954             break;
1955         }
1956         else
1957         {
1958             debug_mi_error( "Unknown argument." );
1959             return;
1960         }
1961     }
1962     if ( argc > 1 )
1963     {
1964         debug_mi_error( "Too many arguments for -break-insert." );
1965         return;
1966     }
1967 
1968     if ( argc == 1 )
1969     {
1970         location = *argv;
1971     }
1972     else
1973     {
1974         debug_mi_error( "Not implemented: -break-insert with no location." );
1975         return;
1976     }
1977     inner_argv[ 0 ] = "break";
1978     inner_argv[ 1 ] = location;
1979 
1980     id = debug_add_breakpoint( location );
1981     debug_parent_forward_nowait( 2, inner_argv, 1, 0 );
1982 
1983     if ( disabled )
1984     {
1985         char buf[ 80 ];
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 );
1991     }
1992 
1993     debug_mi_format_token();
1994     printf( "^done," );
1995     debug_mi_format_breakpoint( id );
1996     printf( "\n(gdb) \n" );
1997 }
1998 
debug_mi_break_delete(int argc,const char ** argv)1999 static void debug_mi_break_delete( int argc, const char * * argv )
2000 {
2001     if ( argc < 2 )
2002     {
2003         debug_mi_error( "Not enough arguments for -break-delete" );
2004         return;
2005     }
2006     for ( --argc, ++argv; argc; --argc, ++argv )
2007     {
2008         const char * inner_argv[ 2 ];
2009         int id = breakpoint_id_parse( *argv );
2010         if ( id == -1 )
2011         {
2012             debug_mi_error( "Not a valid breakpoint" );
2013             return;
2014         }
2015         inner_argv[ 0 ] = "delete";
2016         inner_argv[ 1 ] = *argv;
2017         debug_parent_delete( 2, inner_argv );
2018     }
2019 }
2020 
debug_mi_break_enable(int argc,const char ** argv)2021 static void debug_mi_break_enable( int argc, const char * * argv )
2022 {
2023     if ( argc < 2 )
2024     {
2025         debug_mi_error( "Not enough arguments for -break-enable" );
2026         return;
2027     }
2028     for ( --argc, ++argv; argc; --argc, ++argv )
2029     {
2030         const char * inner_argv[ 2 ];
2031         int id = breakpoint_id_parse( *argv );
2032         if ( id == -1 )
2033         {
2034             debug_mi_error( "Not a valid breakpoint" );
2035             return;
2036         }
2037         inner_argv[ 0 ] = "enable";
2038         inner_argv[ 1 ] = *argv;
2039         debug_parent_enable( 2, inner_argv );
2040     }
2041 }
2042 
debug_mi_break_disable(int argc,const char ** argv)2043 static void debug_mi_break_disable( int argc, const char * * argv )
2044 {
2045     if ( argc < 2 )
2046     {
2047         debug_mi_error( "Not enough arguments for -break-disable" );
2048         return;
2049     }
2050     for ( --argc, ++argv; argc; --argc, ++argv )
2051     {
2052         const char * inner_argv[ 2 ];
2053         int id = breakpoint_id_parse( *argv );
2054         if ( id == -1 )
2055         {
2056             debug_mi_error( "Not a valid breakpoint" );
2057             return;
2058         }
2059         inner_argv[ 0 ] = "disable";
2060         inner_argv[ 1 ] = *argv;
2061         debug_parent_disable( 2, inner_argv );
2062     }
2063 }
2064 
debug_mi_format_breakpoint_header_col(int width,int alignment,const char * col_name,const char * colhdr)2065 static void debug_mi_format_breakpoint_header_col( int width, int alignment, const char * col_name, const char * colhdr )
2066 {
2067     printf( "{width=\"%d\",alignment=\"%d\",col_name=\"%s\",colhdr=\"%s\"}", width, alignment, col_name, colhdr );
2068 }
2069 
debug_mi_format_breakpoint_hdr(void)2070 static void debug_mi_format_breakpoint_hdr( void )
2071 {
2072     printf( "hdr=[" );
2073     debug_mi_format_breakpoint_header_col( 7, -1, "number", "Num" );
2074     printf( "," );
2075     debug_mi_format_breakpoint_header_col( 14, -1, "type", "Type" );
2076     printf( "," );
2077     debug_mi_format_breakpoint_header_col( 4, -1, "disp", "Disp" );
2078     printf( "," );
2079     debug_mi_format_breakpoint_header_col( 3, -1, "enabled", "Enb" );
2080     printf( "," );
2081     debug_mi_format_breakpoint_header_col( 10, -1, "addr", "Address" );
2082     printf( "," );
2083     debug_mi_format_breakpoint_header_col( 40, 2, "what", "What" );
2084     printf( "]" );
2085 }
2086 
debug_mi_break_info(int argc,const char ** argv)2087 static void debug_mi_break_info( int argc, const char * * argv )
2088 {
2089     int id;
2090     --argc;
2091     ++argv;
2092     if ( strcmp( *argv, "--" ) == 0 )
2093     {
2094         --argc;
2095         ++argv;
2096     }
2097     if ( argc < 1 )
2098     {
2099         debug_mi_error( "Not enough arguments for -break-info" );
2100         return;
2101     }
2102     if ( argc > 1 )
2103     {
2104         debug_mi_error( "Too many arguments for -break-info" );
2105     }
2106 
2107     id = breakpoint_id_parse( *argv );
2108     if ( id == -1 )
2109     {
2110         debug_mi_error( "No such breakpoint." );
2111         return;
2112     }
2113 
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 );
2119     printf( "]}" );
2120     printf("\n(gdb) \n");
2121 }
2122 
debug_mi_break_list(int argc,const char ** argv)2123 static void debug_mi_break_list( int argc, const char * * argv )
2124 {
2125     int number;
2126     int i;
2127     int first;
2128     if ( argc > 2 || ( argc == 2 && strcmp( argv[ 1 ], "--" ) ) )
2129     {
2130         debug_mi_error( "Too many arguments for -break-list" );
2131         return;
2132     }
2133 
2134     number = 0;
2135     for ( i = 0; i < num_breakpoints; ++i )
2136         if ( breakpoints[ i ].status != BREAKPOINT_DELETED )
2137             ++number;
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=[" );
2143     first = 1;
2144     for ( i = 0; i < num_breakpoints; ++i )
2145         if ( breakpoints[ i ].status != BREAKPOINT_DELETED )
2146         {
2147             if ( first ) first = 0;
2148             else printf( "," );
2149             debug_mi_format_breakpoint( i + 1 );
2150         }
2151     printf( "]}" );
2152     printf("\n(gdb) \n");
2153 }
2154 
debug_mi_inferior_tty_set(int argc,const char ** argv)2155 static void debug_mi_inferior_tty_set( int argc, const char * * argv )
2156 {
2157     /* FIXME: implement this for real */
2158     debug_mi_format_token();
2159     printf( "^done\n(gdb) \n" );
2160 }
2161 
debug_mi_gdb_exit(int argc,const char ** argv)2162 static void debug_mi_gdb_exit( int argc, const char * * argv )
2163 {
2164     if ( debug_state == DEBUG_RUN )
2165     {
2166         fprintf( command_output, "kill\n" );
2167         fflush( command_output );
2168         debug_parent_wait( 0 );
2169     }
2170     debug_mi_format_token();
2171     printf( "^exit\n" );
2172     exit( EXIT_SUCCESS );
2173 }
2174 
debug_mi_gdb_set(int argc,const char ** argv)2175 static void debug_mi_gdb_set( int argc, const char * * argv )
2176 {
2177     /* FIXME: implement this for real */
2178     debug_mi_format_token();
2179     printf( "^done\n(gdb) \n" );
2180 }
2181 
debug_mi_gdb_show(int argc,const char ** argv)2182 static void debug_mi_gdb_show( int argc, const char * * argv )
2183 {
2184     const char * value = "";
2185     /* FIXME: implement this for real */
2186     debug_mi_format_token();
2187     value = "(gdb) ";
2188     printf( "^done,value=\"%s\"\n(gdb) \n", value );
2189 }
2190 
debug_mi_not_implemented(int argc,const char ** argv)2191 static void debug_mi_not_implemented( int argc, const char * * argv )
2192 {
2193     /* FIXME: implement this for real */
2194     debug_mi_format_token();
2195     printf( "^done\n(gdb) \n" );
2196 }
2197 
debug_mi_file_list_exec_source_files(int argc,const char ** argv)2198 void debug_mi_file_list_exec_source_files( int argc, const char * * argv )
2199 {
2200     /* FIXME: implement this for real */
2201     debug_mi_format_token();
2202     printf( "^done,files=[]\n(gdb) \n" );
2203 }
2204 
debug_mi_file_list_exec_source_file(int argc,const char ** argv)2205 static void debug_mi_file_list_exec_source_file( int argc, const char * * argv )
2206 {
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" );
2210 }
2211 
debug_mi_thread_info(int argc,const char ** argv)2212 static void debug_mi_thread_info( int argc, const char * * argv )
2213 {
2214     if ( debug_state == DEBUG_NO_CHILD )
2215     {
2216         debug_mi_format_token();
2217         printf( "^done,threads=[]\n(gdb) \n" );
2218     }
2219     else
2220     {
2221         const char * new_args[] = { "info", "frame" };
2222         FRAME_INFO info;
2223         debug_parent_forward_nowait( 2, new_args, 0, 0 );
2224         debug_frame_read( command_child, &info );
2225 
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" );
2231     }
2232 }
2233 
debug_mi_thread_select(int argc,const char ** argv)2234 static void debug_mi_thread_select( int argc, const char * * argv )
2235 {
2236     if ( debug_state == DEBUG_NO_CHILD )
2237     {
2238         /* FIXME: better error handling*/
2239         debug_mi_format_token();
2240         printf( "^error,msg=\"Thread ID 1 not known\"\n(gdb) \n" );
2241     }
2242     else
2243     {
2244         const char * new_args[] = { "info", "frame" };
2245         FRAME_INFO info;
2246         debug_parent_forward_nowait( 2, new_args, 0, 0 );
2247         debug_frame_read( command_child, &info );
2248 
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" );
2254     }
2255 }
2256 
debug_mi_stack_select_frame(int argc,const char ** argv)2257 static void debug_mi_stack_select_frame( int argc, const char * * argv )
2258 {
2259     if ( debug_state == DEBUG_NO_CHILD )
2260     {
2261         debug_mi_format_token();
2262         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2263     }
2264     else
2265     {
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" );
2272     }
2273 }
2274 
debug_mi_stack_info_frame(int argc,const char ** argv)2275 static void debug_mi_stack_info_frame( int argc, const char * * argv )
2276 {
2277     if ( debug_state == DEBUG_NO_CHILD )
2278     {
2279         debug_mi_format_token();
2280         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2281     }
2282     else
2283     {
2284         FRAME_INFO info;
2285         fprintf( command_output, "info frame\n" );
2286         fflush( command_output );
2287         debug_frame_read( command_child, &info );
2288         debug_mi_format_token();
2289         printf( "^done," );
2290         debug_mi_print_frame_info( &info );
2291         debug_frame_info_free( &info );
2292         printf( "\n(gdb) \n" );
2293     }
2294 }
2295 
debug_mi_stack_list_variables(int argc,const char ** argv)2296 static void debug_mi_stack_list_variables( int argc, const char * * argv )
2297 {
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 )
2303     {
2304         debug_mi_format_token();
2305         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2306         return;
2307     }
2308     --argc;
2309     ++argv;
2310     for ( ; argc; --argc, ++argv )
2311     {
2312         if ( strcmp( *argv, "--thread" ) == 0 )
2313         {
2314             /* Only one thread. */
2315             --argc;
2316             ++argv;
2317         }
2318         else if ( strcmp( *argv, "--no-values" ) == 0 )
2319         {
2320             print_values = DEBUG_PRINT_VARIABLES_NO_VALUES;
2321         }
2322         else if ( strcmp( *argv, "--all-values" ) == 0 )
2323         {
2324             print_values = DEBUG_PRINT_VARIABLES_ALL_VALUES;
2325         }
2326         else if ( strcmp( *argv, "--simple-values" ) == 0 )
2327         {
2328             print_values = DEBUG_PRINT_VARIABLES_SIMPLE_VALUES;
2329         }
2330         else if ( strcmp( *argv, "--" ) == 0 )
2331         {
2332             --argc;
2333             ++argv;
2334             break;
2335         }
2336         else if ( argv[ 0 ][ 0 ] == '-' )
2337         {
2338             debug_mi_format_token();
2339             printf( "^error,msg=\"Unknown argument %s\"\n(gdb) \n", *argv );
2340             return;
2341         }
2342         else
2343         {
2344             break;
2345         }
2346     }
2347     if ( argc != 0 )
2348     {
2349         debug_mi_format_token();
2350         printf( "^error,msg=\"Too many arguments for -stack-list-variables\"\n(gdb) \n" );
2351         return;
2352     }
2353 
2354     {
2355         LIST * vars;
2356         LISTITER iter, end;
2357         int first = 1;
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 ) )
2365         {
2366             OBJECT * varname = list_item( iter );
2367             string varbuf[1];
2368             const char * new_args[2];
2369             if ( first )
2370             {
2371                 first = 0;
2372             }
2373             else
2374             {
2375                 printf( "," );
2376             }
2377             printf( "{name=\"%s\",value=\"", object_str( varname ) );
2378             fflush( stdout );
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 );
2387             printf( "\"}" );
2388         }
2389         printf( "]\n(gdb) \n" );
2390         fflush( stdout );
2391         list_free( vars );
2392     }
2393 }
2394 
debug_mi_stack_list_locals(int argc,const char ** argv)2395 static void debug_mi_stack_list_locals( int argc, const char * * argv )
2396 {
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 )
2402     {
2403         debug_mi_format_token();
2404         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2405         return;
2406     }
2407     --argc;
2408     ++argv;
2409     for ( ; argc; --argc, ++argv )
2410     {
2411         if ( strcmp( *argv, "--thread" ) == 0 )
2412         {
2413             /* Only one thread. */
2414             --argc;
2415             ++argv;
2416             if ( argc == 0 )
2417             {
2418                 debug_mi_format_token();
2419                 printf( "^error,msg=\"Argument required for --thread.\"" );
2420                 return;
2421             }
2422         }
2423         else if ( strcmp( *argv, "--no-values" ) == 0 )
2424         {
2425             print_values = DEBUG_PRINT_VARIABLES_NO_VALUES;
2426         }
2427         else if ( strcmp( *argv, "--all-values" ) == 0 )
2428         {
2429             print_values = DEBUG_PRINT_VARIABLES_ALL_VALUES;
2430         }
2431         else if ( strcmp( *argv, "--simple-values" ) == 0 )
2432         {
2433             print_values = DEBUG_PRINT_VARIABLES_SIMPLE_VALUES;
2434         }
2435         else if ( strcmp( *argv, "--" ) == 0 )
2436         {
2437             --argc;
2438             ++argv;
2439             break;
2440         }
2441         else if ( argv[ 0 ][ 0 ] == '-' )
2442         {
2443             debug_mi_format_token();
2444             printf( "^error,msg=\"Unknown argument %s\"\n(gdb) \n", *argv );
2445             return;
2446         }
2447         else
2448         {
2449             break;
2450         }
2451     }
2452     if ( argc != 0 )
2453     {
2454         debug_mi_format_token();
2455         printf( "^error,msg=\"Too many arguments for -stack-list-variables\"\n(gdb) \n" );
2456         return;
2457     }
2458 
2459     {
2460         LIST * vars;
2461         LISTITER iter, end;
2462         int first = 1;
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 ) )
2470         {
2471             OBJECT * varname = list_item( iter );
2472             string varbuf[1];
2473             const char * new_args[2];
2474             if ( first )
2475             {
2476                 first = 0;
2477             }
2478             else
2479             {
2480                 printf( "," );
2481             }
2482             printf( "{name=\"%s\",type=\"list\",value=\"", object_str( varname ) );
2483             fflush( stdout );
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 );
2492             printf( "\"}" );
2493         }
2494         printf( "]\n(gdb) \n" );
2495         fflush( stdout );
2496         list_free( vars );
2497     }
2498 }
2499 
debug_mi_stack_list_frames(int argc,const char ** argv)2500 static void debug_mi_stack_list_frames( int argc, const char * * argv )
2501 {
2502     const char * new_args[ 3 ];
2503     int depth;
2504     int i;
2505 
2506     if ( debug_state == DEBUG_NO_CHILD )
2507     {
2508         debug_mi_format_token();
2509         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2510         return;
2511     }
2512 
2513     new_args[ 0 ] = "info";
2514     new_args[ 1 ] = "frame";
2515 
2516     fprintf( command_output, "info depth\n" );
2517     fflush( command_output );
2518     depth = debug_int_read( command_child );
2519 
2520     debug_mi_format_token();
2521     printf( "^done,stack=[" );
2522     for ( i = 0; i < depth; ++i )
2523     {
2524         FRAME_INFO frame;
2525         fprintf( command_output, "info frame %d\n", i );
2526         fflush( command_output );
2527         if ( i != 0 )
2528         {
2529             printf( "," );
2530         }
2531         debug_frame_read( command_child, &frame );
2532         debug_mi_print_frame_info( &frame );
2533     }
2534     printf( "]\n(gdb) \n" );
2535     fflush( stdout );
2536 }
2537 
debug_mi_list_target_features(int argc,const char ** argv)2538 static void debug_mi_list_target_features( int argc, const char * * argv )
2539 {
2540     /* FIXME: implement this for real */
2541     debug_mi_format_token();
2542     printf( "^done,features=[\"async\"]\n(gdb) \n" );
2543 }
2544 
debug_mi_exec_run(int argc,const char ** argv)2545 static void debug_mi_exec_run( int argc, const char * * argv )
2546 {
2547     printf( "=thread-created,id=\"1\",group-id=\"i1\"\n" );
2548     debug_mi_format_token();
2549     printf( "^running\n(gdb) \n" );
2550     fflush( stdout );
2551     debug_start_child( argc, argv );
2552     debug_parent_wait( 1 );
2553 }
2554 
debug_mi_exec_continue(int argc,const char ** argv)2555 static void debug_mi_exec_continue( int argc, const char * * argv )
2556 {
2557     if ( debug_state == DEBUG_NO_CHILD )
2558     {
2559         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2560     }
2561     else
2562     {
2563         const char * new_args[] = { "continue" };
2564         debug_mi_format_token();
2565         printf( "^running\n(gdb) \n" );
2566         fflush( stdout );
2567         debug_parent_forward( 1, new_args, 1, 0 );
2568     }
2569 }
2570 
debug_mi_exec_step(int argc,const char ** argv)2571 static void debug_mi_exec_step( int argc, const char * * argv )
2572 {
2573     if ( debug_state == DEBUG_NO_CHILD )
2574     {
2575         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2576     }
2577     else
2578     {
2579         const char * new_args[] = { "step" };
2580         debug_mi_format_token();
2581         printf( "^running\n(gdb) \n" );
2582         fflush( stdout );
2583         debug_parent_forward( 1, new_args, 1, 0 );
2584     }
2585 }
2586 
debug_mi_exec_next(int argc,const char ** argv)2587 static void debug_mi_exec_next( int argc, const char * * argv )
2588 {
2589     if ( debug_state == DEBUG_NO_CHILD )
2590     {
2591         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2592     }
2593     else
2594     {
2595         const char * new_args[] = { "next" };
2596         debug_mi_format_token();
2597         printf( "^running\n(gdb) \n" );
2598         fflush( stdout );
2599         debug_parent_forward( 1, new_args, 1, 0 );
2600     }
2601 }
2602 
debug_mi_exec_finish(int argc,const char ** argv)2603 static void debug_mi_exec_finish( int argc, const char * * argv )
2604 {
2605     if ( debug_state == DEBUG_NO_CHILD )
2606     {
2607         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2608     }
2609     else
2610     {
2611         const char * new_args[] = { "finish" };
2612         debug_mi_format_token();
2613         printf( "^running\n(gdb) \n" );
2614         fflush( stdout );
2615         debug_parent_forward( 1, new_args, 1, 0 );
2616     }
2617 }
2618 
debug_mi_data_list_register_names(int argc,const char ** argv)2619 static void debug_mi_data_list_register_names( int argc, const char * * argv )
2620 {
2621     debug_mi_format_token();
2622     printf( "^done,register-names=[]\n(gdb) \n" );
2623 }
2624 
debug_mi_data_evaluate_expression(int argc,const char ** argv)2625 static void debug_mi_data_evaluate_expression( int argc, const char * * argv )
2626 {
2627     if ( argc < 2 )
2628     {
2629         printf( "^error,msg=\"Not enough arguments for -data-evaluate-expression\"\n(gdb) \n" );
2630     }
2631     if ( debug_state == DEBUG_NO_CHILD )
2632     {
2633         printf( "^error,msg=\"No child\"\n(gdb) \n" );
2634     }
2635     else
2636     {
2637         const char * new_args[ 2 ];
2638         debug_mi_format_token();
2639         printf( "^done,value=\"" );
2640         fflush( stdout );
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" );
2645     }
2646 }
2647 
2648 static int process_command( char * command );
2649 
debug_mi_interpreter_exec(int argc,const char ** argv)2650 static void debug_mi_interpreter_exec( int argc, const char * * argv )
2651 {
2652     if ( argc < 3 )
2653     {
2654         debug_mi_error( "Not enough arguments for -interpreter-exec" );
2655     }
2656     process_command( (char *)argv[ 2 ] );
2657 }
2658 
2659 /* The debugger's main loop. */
debugger(void)2660 int debugger( void )
2661 {
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" );
2666     while ( 1 )
2667     {
2668         if ( debug_interface == DEBUG_INTERFACE_CONSOLE )
2669             printf("(b2db) ");
2670         fflush( stdout );
2671         read_command();
2672     }
2673     return 0;
2674 }
2675 
2676 
2677 /* Runs the matching command in the current command_array. */
run_command(int argc,const char ** argv)2678 static int run_command( int argc, const char * * argv )
2679 {
2680     struct command_elem * command;
2681     const char * command_name;
2682     if ( argc == 0 )
2683     {
2684         return 1;
2685     }
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 )
2691     {
2692         if ( strcmp( command->key, command_name ) == 0 )
2693         {
2694             ( *command->command )( argc, argv );
2695             return 1;
2696         }
2697     }
2698     debug_error( "Unknown command: %s", command_name );
2699     return 0;
2700 }
2701 
2702 /* Parses a single command into whitespace separated tokens, and runs it. */
process_command(char * line)2703 static int process_command( char * line )
2704 {
2705     int result;
2706     size_t capacity = 8;
2707     char * * buffer = (char **)malloc( capacity * sizeof( char * ) );
2708     char * * current = buffer;
2709     char * iter = line;
2710     char * saved = iter;
2711     *current = iter;
2712     for ( ; ; )
2713     {
2714         /* skip spaces */
2715         while ( *iter && isspace( *iter ) )
2716         {
2717             ++iter;
2718         }
2719         if ( ! *iter )
2720         {
2721             break;
2722         }
2723         /* Find the next token */
2724         saved = iter;
2725         if ( *iter == '\"' )
2726         {
2727             saved = ++iter;
2728             /* FIXME: handle escaping */
2729             while ( *iter && *iter != '\"' )
2730             {
2731                 ++iter;
2732             }
2733         }
2734         else
2735         {
2736             while ( *iter && ! isspace( *iter ) )
2737             {
2738                 ++iter;
2739             }
2740         }
2741         /* resize the buffer if necessary */
2742         if ( current == buffer + capacity )
2743         {
2744             buffer = (char**)realloc( (void *)buffer, capacity * 2 * sizeof( char * ) );
2745             current = buffer + capacity;
2746         }
2747         /* append the token to the buffer */
2748         *current++ = saved;
2749         /* null terminate the token */
2750         if ( *iter )
2751         {
2752             *iter++ = '\0';
2753         }
2754     }
2755     result = run_command( current - buffer, (const char **)buffer );
2756     free( (void *)buffer );
2757     return result;
2758 }
2759 
read_command(void)2760 static int read_command( void )
2761 {
2762     int result;
2763     int ch;
2764     string line[ 1 ];
2765     string_new( line );
2766     /* HACK: force line to be on the heap. */
2767     string_reserve( line, 64 );
2768     while( ( ch = fgetc( command_input ) )  != EOF )
2769     {
2770         if ( ch == '\n' )
2771         {
2772             break;
2773         }
2774         else
2775         {
2776             string_push_back( line, (char)ch );
2777         }
2778     }
2779     result = process_command( line->value );
2780     string_free( line );
2781     return result;
2782 }
2783 
debug_listen(void)2784 static void debug_listen( void )
2785 {
2786     debug_state = DEBUG_STOPPED;
2787     while ( debug_state == DEBUG_STOPPED )
2788     {
2789         if ( feof( command_input ) )
2790             exit( 1 );
2791         fflush(stdout);
2792         fflush( command_output );
2793         read_command();
2794     }
2795     debug_selected_frame_number = 0;
2796 }
2797 
2798 struct debug_child_data_t debug_child_data;
2799 const char debugger_opt[] = "--b2db-internal-debug-handle=";
2800 int debug_interface;
2801