]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/debugger.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / tools / build / src / engine / debugger.cpp
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
94 static void debug_string_write( FILE * out, const char * data )
95 {
96 fprintf( out, "%s", data );
97 fputc( '\0', out );
98 }
99
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
115 static void debug_object_write( FILE * out, OBJECT * data )
116 {
117 debug_string_write( out, object_str( data ) );
118 }
119
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
135 static void debug_int_write( FILE * out, int i )
136 {
137 fprintf( out, "%d", i );
138 fputc( '\0', out );
139 }
140
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
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
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
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
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
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
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
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
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
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
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
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 */
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
318 static int handle_function_breakpoint( OBJECT * name )
319 {
320 return handle_line_breakpoint( name, -1 );
321 }
322
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
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
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
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
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
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
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
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
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
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
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
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
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
574 static void debug_child_continue( int argc, const char * * argv )
575 {
576 debug_state = DEBUG_RUN;
577 debug_depth = 0;
578 }
579
580 static void debug_child_step( int argc, const char * * argv )
581 {
582 debug_state = DEBUG_STEP;
583 debug_depth = 0;
584 }
585
586 static void debug_child_next( int argc, const char * * argv )
587 {
588 debug_state = DEBUG_NEXT;
589 debug_depth = 0;
590 }
591
592 static void debug_child_finish( int argc, const char * * argv )
593 {
594 debug_state = DEBUG_FINISH;
595 debug_depth = 0;
596 }
597
598 static void debug_child_kill( int argc, const char * * argv )
599 {
600 exit( 0 );
601 }
602
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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. */
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. */
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
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
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
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
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
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
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. */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1808 static void debug_mi_format_token( void )
1809 {
1810 if ( current_token != 0 )
1811 {
1812 printf( "%d", current_token );
1813 }
1814 }
1815
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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. */
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. */
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. */
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
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
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;