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