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