1 /*
2  *      dbm_gdm.c
3  *
4  *      Copyright 2010 Alexander Petukhov <devel(at)apetukhov.ru>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *      MA 02110-1301, USA.
20  */
21 
22 /*
23  * 		Implementation of struct _dbg_module for GDB
24  */
25 
26 #include <string.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <wctype.h>
30 #include <unistd.h>
31 
32 #ifdef HAVE_CONFIG_H
33 	#include "config.h"
34 #endif
35 #include <geanyplugin.h>
36 extern GeanyData		*geany_data;
37 
38 #include "breakpoint.h"
39 #include "debug_module.h"
40 #include "gdb_mi.h"
41 
42 /* module features */
43 #define MODULE_FEATURES MF_ASYNC_BREAKS
44 
45 /* GDB spawn flags */
46 #define GDB_SPAWN_FLAGS \
47 	G_SPAWN_SEARCH_PATH | \
48 	G_SPAWN_DO_NOT_REAP_CHILD
49 
50 /* GDB prompt */
51 #define GDB_PROMPT "(gdb) \n"
52 
53 /* enumeration for GDB command execution status */
54 typedef enum _result_class {
55 	RC_DONE,
56 	RC_EXIT,
57 	RC_ERROR
58 } result_class;
59 
60 /* structure to keep async command data (command line, messages) */
61 typedef struct _queue_item {
62 	gchar *message;
63 	gchar *command;
64 	gchar *error_message;
65 	gboolean format_error_message;
66 } queue_item;
67 
68 /* enumeration for stop reason */
69 enum sr {
70 	SR_BREAKPOINT_HIT,
71 	SR_END_STEPPING_RANGE,
72 	SR_EXITED_NORMALLY,
73 	SR_SIGNAL_RECIEVED,
74 	SR_EXITED_SIGNALLED,
75 	SR_EXITED_WITH_CODE,
76 } stop_reason;
77 
78 /* callbacks to use for messaging, error reporting and state change alerting */
79 static dbg_callbacks* dbg_cbs;
80 
81 /* GDB command line arguments*/
82 static const gchar *gdb_args[] = { "gdb", "-i=mi", NULL };
83 
84 /* GDB pid*/
85 static GPid gdb_pid = 0;
86 
87 /* target pid*/
88 static GPid target_pid = 0;
89 
90 /* GSource to watch GDB exit */
91 static guint gdb_src_id;
92 
93 /* channels for GDB input/output */
94 static gint gdb_in;
95 static gint gdb_out;
96 static GIOChannel *gdb_ch_in;
97 static GIOChannel *gdb_ch_out;
98 
99 /* GDB output event source id */
100 static guint gdb_id_out;
101 
102 /* buffer for the error message */
103 char err_message[1000];
104 
105 /* flag, showing that on debugger stop we have to call a callback */
106 gboolean requested_interrupt = FALSE;
107 
108 /* autos list */
109 static GList *autos = NULL;
110 
111 /* watches list */
112 static GList *watches = NULL;
113 
114 /* loaded files list */
115 static GList *files = NULL;
116 
117 /* set to true if library was loaded/unloaded
118 and it's nessesary to refresh files list */
119 static gboolean file_refresh_needed = FALSE;
120 
121 /* current frame number */
122 static int active_frame = 0;
123 
124 /* forward declarations */
125 static void stop(void);
126 static variable* add_watch(gchar* expression);
127 static void update_watches(void);
128 static void update_autos(void);
129 static void update_files(void);
130 
131 /*
132  * print message using color, based on message type
133  */
colorize_message(gchar * message)134 static void colorize_message(gchar *message)
135 {
136 	const gchar *color;
137 	if ('=' == *message)
138 		color = "rose";
139 	else if ('^' == *message)
140 		color = "brown";
141 	else if ('*' == *message)
142 		color = "blue";
143 	else if ('~' == *message)
144 		color = "grey";
145 	else
146 		color = "red";
147 
148 	dbg_cbs->send_message(message, color);
149 }
150 
151 /*
152  * shutdown GIOChannel
153  */
shutdown_channel(GIOChannel ** ch)154 static void shutdown_channel(GIOChannel ** ch)
155 {
156 	if (*ch)
157 	{
158 		gint fd = g_io_channel_unix_get_fd(*ch);
159 		g_io_channel_shutdown(*ch, TRUE, NULL);
160 		g_io_channel_unref(*ch);
161 		*ch = NULL;
162 		if (fd >= 0)
163 		{
164 			close(fd);
165 		}
166 	}
167 }
168 
169 /*
170  * called on GDB exit
171  */
on_gdb_exit(GPid pid,gint status,gpointer data)172 static void on_gdb_exit(GPid pid, gint status, gpointer data)
173 {
174 	gdb_pid = target_pid = 0;
175 	g_spawn_close_pid(pid);
176 	shutdown_channel(&gdb_ch_in);
177 	shutdown_channel(&gdb_ch_out);
178 
179 	/* delete autos */
180 	g_list_foreach(autos, (GFunc)g_free, NULL);
181 	g_list_free(autos);
182 	autos = NULL;
183 
184 	/* delete watches */
185 	g_list_foreach(watches, (GFunc)g_free, NULL);
186 	g_list_free(watches);
187 	watches = NULL;
188 
189 	/* delete files */
190 	g_list_foreach(files, (GFunc)g_free, NULL);
191 	g_list_free(files);
192 	files = NULL;
193 
194 	g_source_remove(gdb_src_id);
195 	gdb_src_id = 0;
196 
197 	dbg_cbs->set_exited(0);
198 }
199 
200 /*
201  * reads gdb_out until "(gdb)" prompt met
202  */
read_until_prompt(void)203 static GList* read_until_prompt(void)
204 {
205 	GList *lines = NULL;
206 
207 	gchar *line = NULL;
208 	gsize terminator;
209 	while (G_IO_STATUS_NORMAL == g_io_channel_read_line(gdb_ch_out, &line, NULL, &terminator, NULL))
210 	{
211 		if (!strcmp(GDB_PROMPT, line))
212 			break;
213 
214 		line[terminator] = '\0';
215 		lines = g_list_prepend (lines, line);
216 	}
217 
218 	return g_list_reverse(lines);
219 }
220 
221 /*
222  * write a command to a gdb channel and flush with a newlinw character
223  */
gdb_input_write_line(const gchar * line)224 static void gdb_input_write_line(const gchar *line)
225 {
226 	GIOStatus st;
227 	GError *err = NULL;
228 	gsize count;
229 	const char *p;
230 	char command[1000];
231 	g_snprintf(command, sizeof command, "%s\n", line);
232 
233 	for (p = command; *p; p += count)
234 	{
235 		st = g_io_channel_write_chars(gdb_ch_in, p, strlen(p), &count, &err);
236 		if (err || (st == G_IO_STATUS_ERROR) || (st == G_IO_STATUS_EOF))
237 		{
238 			if (err)
239 			{
240 #ifdef DEBUG_OUTPUT
241 				dbg_cbs->send_message(err->message, "red");
242 #endif
243 				g_clear_error(&err);
244 			}
245 			break;
246 		}
247 	}
248 
249 	st = g_io_channel_flush(gdb_ch_in, &err);
250 	if (err || (st == G_IO_STATUS_ERROR) || (st == G_IO_STATUS_EOF))
251 	{
252 		if (err)
253 		{
254 			#ifdef DEBUG_OUTPUT
255 			dbg_cbs->send_message(err->message, "red");
256 			#endif
257 			g_clear_error(&err);
258 		}
259 	}
260 }
261 
262 /*
263  * free memory occupied by a queue item
264  */
free_queue_item(queue_item * item)265 static void free_queue_item(queue_item *item)
266 {
267 	g_free(item->message);
268 	g_free(item->command);
269 	g_free(item->error_message);
270 	g_free(item);
271 }
272 
273 /*
274  * free a list of "queue_item" structures
275  */
free_commands_queue(GList * queue)276 static void free_commands_queue(GList *queue)
277 {
278 	/* all commands completed */
279 	queue = g_list_first(queue);
280 	g_list_foreach(queue, (GFunc)free_queue_item, NULL);
281 	g_list_free(queue);
282 }
283 
284 /*
285  * add a new command ("queue_item" structure) to a list
286  */
add_to_queue(GList * queue,const gchar * message,const gchar * command,const gchar * error_message,gboolean format_error_message)287 static GList* add_to_queue(GList* queue, const gchar *message, const gchar *command, const gchar *error_message, gboolean format_error_message)
288 {
289 	queue_item *item = (queue_item*)g_malloc(sizeof(queue_item));
290 
291 	memset((void*)item, 0, sizeof(queue_item));
292 
293 	item->message = g_strdup(message);
294 	item->command = g_strdup(command);
295 	item->error_message = g_strdup(error_message);
296 	item->format_error_message = format_error_message;
297 
298 	return g_list_append(queue, (gpointer)item);
299 }
300 
301 /*
302  * asyncronous output reader
303  * reads from startup async commands.
304  * looks for a command completion (normal or abnormal), if noraml - executes next command
305  */
306 static void exec_async_command(const gchar* command);
on_read_async_output(GIOChannel * src,GIOCondition cond,gpointer data)307 static gboolean on_read_async_output(GIOChannel * src, GIOCondition cond, gpointer data)
308 {
309 	gchar *line;
310 	gsize length;
311 	struct gdb_mi_record *record;
312 
313 	if (G_IO_STATUS_NORMAL != g_io_channel_read_line(src, &line, NULL, &length, NULL))
314 		return TRUE;
315 
316 	record = gdb_mi_record_parse(line);
317 
318 	if (record && record->type == '^')
319 	{
320 		/* got some result */
321 
322 		GList *lines;
323 		GList *commands = (GList*)data;
324 
325 		if (gdb_id_out)
326 		{
327 			g_source_remove(gdb_id_out);
328 			gdb_id_out = 0;
329 		}
330 
331 		lines = read_until_prompt();
332 		g_list_foreach(lines, (GFunc)g_free, NULL);
333 		g_list_free (lines);
334 
335 		if (!strcmp(record->klass, "done"))
336 		{
337 			/* command completed succesfully - run next command if exists */
338 			if (commands->next)
339 			{
340 				/* if there are commads left */
341 				queue_item *item;
342 
343 				commands = commands->next;
344 				item = (queue_item*)commands->data;
345 
346 				/* send message to debugger messages window */
347 				if (item->message)
348 				{
349 					dbg_cbs->send_message(item->message, "grey");
350 				}
351 
352 				gdb_input_write_line(item->command);
353 
354 				gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands);
355 			}
356 			else
357 			{
358 				/* all commands completed */
359 				free_commands_queue(commands);
360 
361 				/* removing read callback */
362 				if (gdb_id_out)
363 				{
364 					g_source_remove(gdb_id_out);
365 					gdb_id_out = 0;
366 				}
367 
368 				/* update source files list */
369 				update_files();
370 
371 				/* -exec-run */
372 				exec_async_command("-exec-run");
373 			}
374 		}
375 		else
376 		{
377 			queue_item *item = (queue_item*)commands->data;
378 			if(item->error_message)
379 			{
380 				if (item->format_error_message)
381 				{
382 					const gchar* gdb_msg = gdb_mi_result_var(record->first, "msg", GDB_MI_VAL_STRING);
383 					gchar *msg = g_strdup_printf(item->error_message, gdb_msg);
384 
385 					dbg_cbs->report_error(msg);
386 					g_free(msg);
387 				}
388 				else
389 				{
390 					dbg_cbs->report_error(item->error_message);
391 				}
392 			}
393 
394 			/* free commands queue */
395 			free_commands_queue(commands);
396 
397 			stop();
398 		}
399 	}
400 
401 	gdb_mi_record_free(record);
402 	g_free(line);
403 
404 	return TRUE;
405 }
406 
407 /*
408  * asyncronous gdb output reader
409  * looks for a stopped event, then notifies "debug" module and removes async handler
410  */
411 enum dbs debug_get_state(void);
on_read_from_gdb(GIOChannel * src,GIOCondition cond,gpointer data)412 static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer data)
413 {
414 	gchar *line;
415 	gsize length;
416 	const gchar *id;
417 	struct gdb_mi_record *record;
418 
419 	if (G_IO_STATUS_NORMAL != g_io_channel_read_line(src, &line, NULL, &length, NULL))
420 		return TRUE;
421 
422 	record = gdb_mi_record_parse(line);
423 
424 	if (! record || record->type != GDB_MI_TYPE_PROMPT)
425 	{
426 		line[length] = '\0';
427 		if ((record && '~' == record->type) || '~' == line[0])
428 		{
429 			colorize_message(line);
430 		}
431 		else
432 		{
433 			gchar *compressed = g_strcompress(line);
434 			colorize_message(compressed);
435 			g_free(compressed);
436 		}
437 	}
438 
439 	if (! record)
440 	{
441 		g_free(line);
442 		return TRUE;
443 	}
444 
445 	if (!target_pid &&
446 		/* FIXME: =thread-group-created doesn't seem to exist, at least not in latest GDB docs */
447 		(gdb_mi_record_matches(record, '=', "thread-group-created", "id", &id, NULL) ||
448 		 gdb_mi_record_matches(record, '=', "thread-group-started", "pid", &id, NULL)))
449 	{
450 		target_pid = atoi(id);
451 	}
452 	else if (gdb_mi_record_matches(record, '=', "thread-created", "id", &id, NULL))
453 	{
454 		dbg_cbs->add_thread(atoi(id));
455 	}
456 	else if (gdb_mi_record_matches(record, '=', "thread-exited", "id", &id, NULL))
457 	{
458 		dbg_cbs->remove_thread(atoi(id));
459 	}
460 	else if (gdb_mi_record_matches(record, '=', "library-loaded", NULL) ||
461 			 gdb_mi_record_matches(record, '=', "library-unloaded", NULL))
462 	{
463 		file_refresh_needed = TRUE;
464 	}
465 	else if (gdb_mi_record_matches(record, '*', "running", NULL))
466 		dbg_cbs->set_run();
467 	else if (gdb_mi_record_matches(record, '*', "stopped", NULL))
468 	{
469 		const gchar *reason;
470 
471 		/* removing read callback (will pulling all output left manually) */
472 		if (gdb_id_out)
473 		{
474 			g_source_remove(gdb_id_out);
475 			gdb_id_out = 0;
476 		}
477 
478 		/* looking for a reason to stop */
479 		if ((reason = gdb_mi_result_var(record->first, "reason", GDB_MI_VAL_STRING)) != NULL)
480 		{
481 			if (!strcmp(reason, "breakpoint-hit"))
482 				stop_reason = SR_BREAKPOINT_HIT;
483 			else if (!strcmp(reason, "end-stepping-range"))
484 				stop_reason = SR_END_STEPPING_RANGE;
485 			else if (!strcmp(reason, "signal-received"))
486 				stop_reason = SR_SIGNAL_RECIEVED;
487 			else if (!strcmp(reason, "exited-normally"))
488 				stop_reason = SR_EXITED_NORMALLY;
489 			else if (!strcmp(reason, "exited-signalled"))
490 				stop_reason = SR_EXITED_SIGNALLED;
491 			else if (!strcmp(reason, "exited"))
492 				stop_reason = SR_EXITED_WITH_CODE;
493 			/* FIXME: handle "location-reached" */
494 		}
495 		else
496 		{
497 			/* somehow, sometimes there can be no stop reason */
498 			stop_reason = SR_EXITED_NORMALLY;
499 		}
500 
501 		if (SR_BREAKPOINT_HIT == stop_reason || SR_END_STEPPING_RANGE == stop_reason || SR_SIGNAL_RECIEVED == stop_reason)
502 		{
503 			const gchar *thread_id = gdb_mi_result_var(record->first, "thread-id", GDB_MI_VAL_STRING);
504 
505 			active_frame = 0;
506 
507 			if (SR_BREAKPOINT_HIT == stop_reason || SR_END_STEPPING_RANGE == stop_reason)
508 			{
509 				/* update autos */
510 				update_autos();
511 
512 				/* update watches */
513 				update_watches();
514 
515 				/* update files */
516 				if (file_refresh_needed)
517 				{
518 					update_files();
519 					file_refresh_needed = FALSE;
520 				}
521 			}
522 			else
523 			{
524 				if (!requested_interrupt)
525 				{
526 					gchar *msg = g_strdup_printf(_("Program received signal %s (%s)"),
527 					                             (gchar *) gdb_mi_result_var(record->first, "signal-name", GDB_MI_VAL_STRING),
528 					                             (gchar *) gdb_mi_result_var(record->first, "signal-meaning", GDB_MI_VAL_STRING));
529 
530 					dbg_cbs->report_error(msg);
531 					g_free(msg);
532 				}
533 				else
534 					requested_interrupt = FALSE;
535 			}
536 
537 			dbg_cbs->set_stopped(thread_id ? atoi(thread_id) : 0);
538 		}
539 		else if (stop_reason == SR_EXITED_NORMALLY || stop_reason == SR_EXITED_SIGNALLED || stop_reason == SR_EXITED_WITH_CODE)
540 		{
541 			if (stop_reason == SR_EXITED_WITH_CODE)
542 			{
543 				const gchar *exit_code = gdb_mi_result_var(record->first, "exit-code", GDB_MI_VAL_STRING);
544 				long int code = exit_code ? strtol(exit_code, NULL, 8) : 0;
545 				gchar *message;
546 
547 				message = g_strdup_printf(_("Program exited with code \"%i\""), (int)(char)code);
548 				dbg_cbs->report_error(message);
549 
550 				g_free(message);
551 			}
552 
553 			stop();
554 		}
555 	}
556 	else if (gdb_mi_record_matches(record, '^', "error", NULL))
557 	{
558 		GList *lines, *iter;
559 		const gchar *msg = gdb_mi_result_var(record->first, "msg", GDB_MI_VAL_STRING);
560 
561 		/* removing read callback (will pulling all output left manually) */
562 		if (gdb_id_out)
563 		{
564 			g_source_remove(gdb_id_out);
565 			gdb_id_out = 0;
566 		}
567 
568 		/* set debugger stopped if is running */
569 		if (DBS_STOPPED != debug_get_state())
570 		{
571 			/* FIXME: does GDB/MI ever return a thread-id with an error?? */
572 			const gchar *thread_id = gdb_mi_result_var(record->first, "thread-id", GDB_MI_VAL_STRING);
573 
574 			dbg_cbs->set_stopped(thread_id ? atoi(thread_id) : 0);
575 		}
576 
577 		/* reading until prompt */
578 		lines = read_until_prompt();
579 		for (iter = lines; iter; iter = iter->next)
580 		{
581 			gchar *l = (gchar*)iter->data;
582 			if (strcmp(l, GDB_PROMPT))
583 				colorize_message(l);
584 			g_free(l);
585 		}
586 		g_list_free (lines);
587 
588 		/* send error message */
589 		dbg_cbs->report_error(msg);
590 	}
591 
592 	g_free(line);
593 	gdb_mi_record_free(record);
594 
595 	return TRUE;
596 }
597 
598 /*
599  * execute "command" asyncronously
600  * after writing command to an input channel
601  * connects reader to output channel and exits
602  * after execution
603  */
exec_async_command(const gchar * command)604 static void exec_async_command(const gchar* command)
605 {
606 #ifdef DEBUG_OUTPUT
607 	dbg_cbs->send_message(command, "red");
608 #endif
609 
610 	gdb_input_write_line(command);
611 
612 	/* connect read callback to the output chanel */
613 	gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_from_gdb, NULL);
614 }
615 
616 /*
617  * execute "command" syncronously
618  * i.e. reading output right
619  * after execution
620  */
exec_sync_command(const gchar * command,gboolean wait4prompt,struct gdb_mi_record ** command_record)621 static result_class exec_sync_command(const gchar* command, gboolean wait4prompt, struct gdb_mi_record ** command_record)
622 {
623 	GList *lines, *iter;
624 	result_class rc;
625 
626 #ifdef DEBUG_OUTPUT
627 	dbg_cbs->send_message(command, "red");
628 #endif
629 
630 	/* write command to gdb input channel */
631 	gdb_input_write_line(command);
632 
633 	if (!wait4prompt)
634 		return RC_DONE;
635 
636 	if (command_record)
637 		*command_record = NULL;
638 
639 	lines = read_until_prompt();
640 
641 #ifdef DEBUG_OUTPUT
642 	for (iter = lines; iter; iter = iter->next)
643 	{
644 		dbg_cbs->send_message((gchar*)iter->data, "red");
645 	}
646 #endif
647 
648 	rc = RC_ERROR;
649 
650 	for (iter = lines; iter; iter = iter->next)
651 	{
652 		gchar *line = (gchar*)iter->data;
653 		struct gdb_mi_record *record = gdb_mi_record_parse(line);
654 
655 		if (record && '^' == record->type)
656 		{
657 			if (gdb_mi_record_matches(record, '^', "done", NULL))
658 				rc = RC_DONE;
659 			else if (gdb_mi_record_matches(record, '^', "error", NULL))
660 			{
661 				/* save error message */
662 				const gchar *msg = gdb_mi_result_var(record->first, "msg", GDB_MI_VAL_STRING);
663 				strncpy(err_message, msg ? msg : "", G_N_ELEMENTS(err_message) - 1);
664 
665 				rc = RC_ERROR;
666 			}
667 			else if (gdb_mi_record_matches(record, '^', "exit", NULL))
668 				rc = RC_EXIT;
669 
670 			if (command_record)
671 			{
672 				*command_record = record;
673 				record = NULL;
674 			}
675 		}
676 		else if (! record || '&' != record->type)
677 		{
678 			colorize_message (line);
679 		}
680 		gdb_mi_record_free(record);
681 	}
682 
683 	g_list_foreach(lines, (GFunc)g_free, NULL);
684 	g_list_free(lines);
685 
686 	return rc;
687 }
688 
689 
690 /* escapes @str so it is valid to put it inside a quoted argument
691  * escapes '\' and '"'
692  * unlike g_strescape(), it doesn't escape non-ASCII characters so keeps
693  * all of UTF-8 */
escape_string(const gchar * str)694 static gchar *escape_string(const gchar *str)
695 {
696 	gchar *new = g_malloc(strlen(str) * 2 + 1);
697 	gchar *p;
698 
699 	for (p = new; *str; str++) {
700 		switch (*str) {
701 			/* FIXME: what to do with '\n'?  can't seem to find a way to escape it */
702 			case '\\':
703 			case '"':
704 				*p++ = '\\';
705 				/* fallthrough */
706 			default:
707 				*p++ = *str;
708 		}
709 	}
710 	*p = 0;
711 
712 	return new;
713 }
714 
715 /*
716  * starts gdb, collects commands and start the first one
717  */
run(const gchar * file,const gchar * commandline,GList * env,GList * witer,GList * biter,const gchar * terminal_device,dbg_callbacks * callbacks)718 static gboolean run(const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks)
719 {
720 	const gchar *exclude[] = { "LANG", NULL };
721 	gchar **gdb_env = utils_copy_environment(exclude, "LANG", "C", NULL);
722 	gchar *working_directory = g_path_get_dirname(file);
723 	GList *lines, *iter;
724 	GList *commands = NULL;
725 	gchar *command;
726 	gchar *escaped;
727 	int bp_index;
728 	queue_item *item;
729 
730 	dbg_cbs = callbacks;
731 
732 	/* spawn GDB */
733 	if (!g_spawn_async_with_pipes(working_directory, (gchar**)gdb_args, gdb_env,
734 				     GDB_SPAWN_FLAGS, NULL,
735 				     NULL, &gdb_pid, &gdb_in, &gdb_out, NULL, NULL))
736 	{
737 		dbg_cbs->report_error(_("Failed to spawn gdb process"));
738 		g_free(working_directory);
739 		g_strfreev(gdb_env);
740 		return FALSE;
741 	}
742 	g_free(working_directory);
743 	g_strfreev(gdb_env);
744 
745 	/* move gdb to it's own process group */
746 	setpgid(gdb_pid, 0);
747 
748 	/* set handler for gdb process exit event */
749 	gdb_src_id = g_child_watch_add(gdb_pid, on_gdb_exit, NULL);
750 
751 	/* create GDB GIO chanels */
752 	gdb_ch_in = g_io_channel_unix_new(gdb_in);
753 	gdb_ch_out = g_io_channel_unix_new(gdb_out);
754 
755 	/* reading starting gdb messages */
756 	lines = read_until_prompt();
757 	for (iter = lines; iter; iter = iter->next)
758 	{
759 		gchar *unescaped = g_strcompress((gchar*)iter->data);
760 		if (strlen(unescaped))
761 		{
762 			colorize_message((gchar*)iter->data);
763 		}
764 	}
765 	g_list_foreach(lines, (GFunc)g_free, NULL);
766 	g_list_free(lines);
767 
768 	/* add initial watches to the list */
769 	while (witer)
770 	{
771 		gchar *name = (gchar*)witer->data;
772 
773 		variable *var = variable_new(name, VT_WATCH);
774 		watches = g_list_append(watches, var);
775 
776 		witer = witer->next;
777 	}
778 
779 	/* collect commands */
780 
781 	/* loading file */
782 	escaped = escape_string(file);
783 	command = g_strdup_printf("-file-exec-and-symbols \"%s\"", escaped);
784 	commands = add_to_queue(commands, _("~\"Loading target file.\\n\""), command, _("Error loading file"), FALSE);
785 	g_free(command);
786 	g_free(escaped);
787 
788 	/* setting asyncronous mode */
789 	commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE);
790 
791 	/* setting null-stop array printing */
792 	commands = add_to_queue(commands, NULL, "-interpreter-exec console \"set print null-stop\"", _("Error configuring GDB"), FALSE);
793 
794 	/* enable pretty printing */
795 	commands = add_to_queue(commands, NULL, "-enable-pretty-printing", _("Error configuring GDB"), FALSE);
796 
797 	/* set locale */
798 	command = g_strdup_printf("-gdb-set environment LANG=%s", g_getenv("LANG"));
799 	commands = add_to_queue(commands, NULL, command, NULL, FALSE);
800 	g_free(command);
801 
802 	/* set arguments */
803 	command = g_strdup_printf("-exec-arguments %s", commandline);
804 	commands = add_to_queue(commands, NULL, command, NULL, FALSE);
805 	g_free(command);
806 
807 	/* set passed evironment */
808 	iter = env;
809 	while (iter)
810 	{
811 		gchar *name, *value;
812 
813 		name = (gchar*)iter->data;
814 		iter = iter->next;
815 		value = (gchar*)iter->data;
816 
817 		command = g_strdup_printf("-gdb-set environment %s=%s", name, value);
818 		commands = add_to_queue(commands, NULL, command, NULL, FALSE);
819 		g_free(command);
820 
821 		iter = iter->next;
822 	}
823 
824 	/* set breaks */
825 	bp_index = 1;
826 	while (biter)
827 	{
828 		breakpoint *bp = (breakpoint*)biter->data;
829 		gchar *error_message;
830 
831 		escaped = escape_string(bp->file);
832 		command = g_strdup_printf("-break-insert -f \"\\\"%s\\\":%i\"", escaped, bp->line);
833 		g_free(escaped);
834 
835 		error_message = g_strdup_printf(_("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s");
836 
837 		commands = add_to_queue(commands, NULL, command, error_message, TRUE);
838 
839 		g_free(command);
840 
841 		if (bp->hitscount)
842 		{
843 			command = g_strdup_printf("-break-after %i %i", bp_index, bp->hitscount);
844 			commands = add_to_queue(commands, NULL, command, error_message, TRUE);
845 			g_free(command);
846 		}
847 		if (strlen(bp->condition))
848 		{
849 			command = g_strdup_printf ("-break-condition %i %s", bp_index, bp->condition);
850 			commands = add_to_queue(commands, NULL, command, error_message, TRUE);
851 			g_free(command);
852 		}
853 		if (!bp->enabled)
854 		{
855 			command = g_strdup_printf ("-break-disable %i", bp_index);
856 			commands = add_to_queue(commands, NULL, command, error_message, TRUE);
857 			g_free(command);
858 		}
859 
860 		g_free(error_message);
861 
862 		bp_index++;
863 		biter = biter->next;
864 	}
865 
866 	/* set debugging terminal */
867 	command = g_strconcat("-inferior-tty-set ", terminal_device, NULL);
868 	commands = add_to_queue(commands, NULL, command, NULL, FALSE);
869 	g_free(command);
870 
871 	/* connect read callback to the output chanel */
872 	gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands);
873 
874 	item = (queue_item*)commands->data;
875 
876 	/* send message to debugger messages window */
877 	if (item->message)
878 	{
879 		dbg_cbs->send_message(item->message, "grey");
880 	}
881 
882 	/* send first command */
883 	gdb_input_write_line(item->command);
884 
885 	return TRUE;
886 }
887 
888 /*
889  * starts debugging
890  */
restart(void)891 static void restart(void)
892 {
893 	dbg_cbs->clear_messages();
894 	exec_async_command("-exec-run");
895 }
896 
897 /*
898  * stops GDB
899  */
stop(void)900 static void stop(void)
901 {
902 	exec_sync_command("-gdb-exit", FALSE, NULL);
903 }
904 
905 /*
906  * resumes GDB
907  */
resume(void)908 static void resume(void)
909 {
910 	exec_async_command("-exec-continue");
911 }
912 
913 /*
914  * step over
915  */
step_over(void)916 static void step_over(void)
917 {
918 	exec_async_command("-exec-next");
919 }
920 
921 /*
922  * step into
923  */
step_into(void)924 static void step_into(void)
925 {
926 	exec_async_command("-exec-step");
927 }
928 
929 /*
930  * step out
931  */
step_out(void)932 static void step_out(void)
933 {
934 	exec_async_command("-exec-finish");
935 }
936 
937 /*
938  * execute until
939  */
execute_until(const gchar * file,int line)940 static void execute_until(const gchar *file, int line)
941 {
942 	gchar command[1000];
943 	g_snprintf(command, sizeof command, "-exec-until %s:%i", file, line);
944 	exec_async_command(command);
945 }
946 
947 /*
948  * gets breakpoint number by file and line
949  */
get_break_number(char * file,int line)950 static int get_break_number(char* file, int line)
951 {
952 	struct gdb_mi_record *record;
953 	const struct gdb_mi_result *table, *body, *bkpt;
954 	int break_number = -1;
955 
956 	exec_sync_command("-break-list", TRUE, &record);
957 	if (! record)
958 		return -1;
959 
960 	table = gdb_mi_result_var(record->first, "BreakpointTable", GDB_MI_VAL_LIST);
961 	body = gdb_mi_result_var(table, "body", GDB_MI_VAL_LIST);
962 	gdb_mi_result_foreach_matched (bkpt, body, "bkpt", GDB_MI_VAL_LIST)
963 	{
964 		const gchar *number = gdb_mi_result_var(bkpt->val->v.list, "number", GDB_MI_VAL_STRING);
965 		const gchar *location = gdb_mi_result_var(bkpt->val->v.list, "original-location", GDB_MI_VAL_STRING);
966 		const gchar *colon;
967 		gboolean break_found = FALSE;
968 
969 		if (! number || ! location)
970 			continue;
971 
972 		colon = strrchr(location, ':');
973 		if (colon && atoi(colon + 1) == line)
974 		{
975 			gchar *fname;
976 
977 			/* quotes around filename (location not found or something?) */
978 			if (*location == '"' && colon - location > 2)
979 				fname = g_strndup(location + 1, colon - location - 2);
980 			else
981 				fname = g_strndup(location, colon - location);
982 			break_found = strcmp(fname, file) == 0;
983 			g_free(fname);
984 		}
985 		if (break_found)
986 		{
987 			break_number = atoi(number);
988 			break;
989 		}
990 	}
991 
992 	gdb_mi_record_free(record);
993 
994 	return break_number;
995 }
996 
997 /*
998  * set breakpoint
999  */
set_break(breakpoint * bp,break_set_activity bsa)1000 static gboolean set_break(breakpoint* bp, break_set_activity bsa)
1001 {
1002 	char command[1000];
1003 	if (BSA_NEW_BREAK == bsa)
1004 	{
1005 		/* new breakpoint */
1006 		struct gdb_mi_record *record;
1007 		const struct gdb_mi_result *bkpt;
1008 		const gchar *number;
1009 		gchar *escaped;
1010 		int num = 0;
1011 
1012 		/* 1. insert breakpoint */
1013 		escaped = escape_string(bp->file);
1014 		g_snprintf(command, sizeof command, "-break-insert \"\\\"%s\\\":%i\"", escaped, bp->line);
1015 		if (RC_DONE != exec_sync_command(command, TRUE, &record) || !record)
1016 		{
1017 			gdb_mi_record_free(record);
1018 			record = NULL;
1019 			g_snprintf(command, sizeof command, "-break-insert -f \"\\\"%s\\\":%i\"", escaped, bp->line);
1020 			if (RC_DONE != exec_sync_command(command, TRUE, &record) || !record)
1021 			{
1022 				gdb_mi_record_free(record);
1023 				g_free(escaped);
1024 				return FALSE;
1025 			}
1026 		}
1027 		/* lookup break-number */
1028 		bkpt = gdb_mi_result_var(record->first, "bkpt", GDB_MI_VAL_LIST);
1029 		if ((number = gdb_mi_result_var(bkpt, "number", GDB_MI_VAL_STRING)))
1030 			num = atoi(number);
1031 		gdb_mi_record_free(record);
1032 		g_free(escaped);
1033 		/* 2. set hits count if differs from 0 */
1034 		if (bp->hitscount)
1035 		{
1036 			g_snprintf(command, sizeof command, "-break-after %i %i", num, bp->hitscount);
1037 			exec_sync_command(command, TRUE, NULL);
1038 		}
1039 		/* 3. set condition if exists */
1040 		if (strlen(bp->condition))
1041 		{
1042 			g_snprintf(command, sizeof command, "-break-condition %i %s", num, bp->condition);
1043 			if (RC_DONE != exec_sync_command(command, TRUE, NULL))
1044 				return FALSE;
1045 		}
1046 		/* 4. disable if disabled */
1047 		if (!bp->enabled)
1048 		{
1049 			g_snprintf(command, sizeof command, "-break-disable %i", num);
1050 			exec_sync_command(command, TRUE, NULL);
1051 		}
1052 
1053 		return TRUE;
1054 	}
1055 	else
1056 	{
1057 		/* modify existing breakpoint */
1058 		int bnumber = get_break_number(bp->file, bp->line);
1059 		if (-1 == bnumber)
1060 			return FALSE;
1061 
1062 		if (BSA_UPDATE_ENABLE == bsa)
1063 			g_snprintf(command, sizeof command, bp->enabled ? "-break-enable %i" : "-break-disable %i", bnumber);
1064 		else if (BSA_UPDATE_HITS_COUNT == bsa)
1065 			g_snprintf(command, sizeof command, "-break-after %i %i", bnumber, bp->hitscount);
1066 		else if (BSA_UPDATE_CONDITION == bsa)
1067 			g_snprintf(command, sizeof command, "-break-condition %i %s", bnumber, bp->condition);
1068 
1069 		return RC_DONE == exec_sync_command(command, TRUE, NULL);
1070 	}
1071 
1072 	return FALSE;
1073 }
1074 
1075 /*
1076  * removes breakpoint
1077  */
remove_break(breakpoint * bp)1078 static gboolean remove_break(breakpoint* bp)
1079 {
1080 	/* find break number */
1081 	int number = get_break_number(bp->file, bp->line);
1082 	if (-1 != number)
1083 	{
1084 		result_class rc;
1085 		gchar command[100];
1086 
1087 		g_snprintf(command, sizeof command, "-break-delete %i", number);
1088 		rc = exec_sync_command(command, TRUE, NULL);
1089 
1090 		return RC_DONE == rc;
1091 	}
1092 	return FALSE;
1093 }
1094 
1095 /*
1096  * get active  frame
1097  */
get_active_frame(void)1098 static int get_active_frame(void)
1099 {
1100 	return active_frame;
1101 }
1102 
1103 /*
1104  * select frame
1105  */
set_active_frame(int frame_number)1106 static void set_active_frame(int frame_number)
1107 {
1108 	gchar *command = g_strdup_printf("-stack-select-frame %i", frame_number);
1109 	if (RC_DONE == exec_sync_command(command, TRUE, NULL))
1110 	{
1111 		active_frame = frame_number;
1112 		update_autos();
1113 		update_watches();
1114 	}
1115 	g_free(command);
1116 }
1117 
get_active_thread(void)1118 static int get_active_thread(void)
1119 {
1120 	struct gdb_mi_record *record = NULL;
1121 	int current_thread = 0;
1122 
1123 	if (RC_DONE == exec_sync_command("-thread-info", TRUE, &record))
1124 	{
1125 		const gchar *id = gdb_mi_result_var(record->first, "current-thread-id", GDB_MI_VAL_STRING);
1126 		current_thread = id ? atoi(id) : 0;
1127 	}
1128 	gdb_mi_record_free(record);
1129 
1130 	return current_thread;
1131 }
1132 
set_active_thread(int thread_id)1133 static gboolean set_active_thread(int thread_id)
1134 {
1135 	gchar *command = g_strdup_printf("-thread-select %i", thread_id);
1136 	gboolean success = (RC_DONE == exec_sync_command(command, TRUE, NULL));
1137 
1138 	if (success)
1139 		set_active_frame(0);
1140 
1141 	g_free(command);
1142 
1143 	return success;
1144 }
1145 
1146 /*
1147  * gets stack
1148  */
get_stack(void)1149 static GList* get_stack(void)
1150 {
1151 	struct gdb_mi_record *record = NULL;
1152 	const struct gdb_mi_result *stack_node, *frame_node;
1153 	GList *stack = NULL;
1154 
1155 	if (RC_DONE != exec_sync_command("-stack-list-frames", TRUE, &record) || ! record)
1156 	{
1157 		gdb_mi_record_free(record);
1158 		return NULL;
1159 	}
1160 
1161 	stack_node = gdb_mi_result_var(record->first, "stack", GDB_MI_VAL_LIST);
1162 	gdb_mi_result_foreach_matched (frame_node, stack_node, "frame", GDB_MI_VAL_LIST)
1163 	{
1164 		const gchar *addr = gdb_mi_result_var(frame_node->val->v.list, "addr", GDB_MI_VAL_STRING);
1165 		const gchar *func = gdb_mi_result_var(frame_node->val->v.list, "func", GDB_MI_VAL_STRING);
1166 		const gchar *line = gdb_mi_result_var(frame_node->val->v.list, "line", GDB_MI_VAL_STRING);
1167 		const gchar *file, *fullname;
1168 		frame *f = frame_new();
1169 
1170 		f->address = g_strdup(addr);
1171 		f->function = g_strdup(func);
1172 
1173 		/* file: fullname | file | from */
1174 		if ((fullname = file = gdb_mi_result_var(frame_node->val->v.list, "fullname", GDB_MI_VAL_STRING)) ||
1175 			(file = gdb_mi_result_var(frame_node->val->v.list, "file", GDB_MI_VAL_STRING)) ||
1176 			(file = gdb_mi_result_var(frame_node->val->v.list, "from", GDB_MI_VAL_STRING)))
1177 		{
1178 			f->file = g_strdup(file);
1179 		}
1180 		else
1181 		{
1182 			f->file = g_strdup("");
1183 		}
1184 
1185 		/* whether source is available */
1186 		f->have_source = fullname ? TRUE : FALSE;
1187 
1188 		/* line */
1189 		f->line = line ? atoi(line) : 0;
1190 
1191 		stack = g_list_prepend(stack, f);
1192 	}
1193 	gdb_mi_record_free(record);
1194 
1195 	return g_list_reverse(stack);
1196 }
1197 
1198 /*
1199  * updates variables from vars list
1200  */
get_variables(GList * vars)1201 static void get_variables (GList *vars)
1202 {
1203 	while (vars)
1204 	{
1205 		gchar command[1000];
1206 
1207 		variable *var = (variable*)vars->data;
1208 
1209 		gchar *varname = var->internal->str;
1210 		struct gdb_mi_record *record = NULL;
1211 		const gchar *expression = NULL;
1212 		const gchar *numchild = NULL;
1213 		const gchar *value = NULL;
1214 		const gchar *type = NULL;
1215 
1216 		/* path expression */
1217 		g_snprintf(command, sizeof command, "-var-info-path-expression \"%s\"", varname);
1218 		exec_sync_command(command, TRUE, &record);
1219 		if (record)
1220 			expression = gdb_mi_result_var(record->first, "path_expr", GDB_MI_VAL_STRING);
1221 		g_string_assign(var->expression, expression ? expression : "");
1222 		gdb_mi_record_free(record);
1223 
1224 		/* children number */
1225 		g_snprintf(command, sizeof command, "-var-info-num-children \"%s\"", varname);
1226 		exec_sync_command(command, TRUE, &record);
1227 		if (record)
1228 			numchild = gdb_mi_result_var(record->first, "numchild", GDB_MI_VAL_STRING);
1229 		var->has_children = numchild && atoi(numchild) > 0;
1230 		gdb_mi_record_free(record);
1231 
1232 		/* value */
1233 		g_snprintf(command, sizeof command, "-data-evaluate-expression \"%s\"", var->expression->str);
1234 		exec_sync_command(command, TRUE, &record);
1235 		if (record)
1236 			value = gdb_mi_result_var(record->first, "value", GDB_MI_VAL_STRING);
1237 		if (!value)
1238 		{
1239 			gdb_mi_record_free(record);
1240 			g_snprintf(command, sizeof command, "-var-evaluate-expression \"%s\"", varname);
1241 			exec_sync_command(command, TRUE, &record);
1242 			if (record)
1243 				value = gdb_mi_result_var(record->first, "value", GDB_MI_VAL_STRING);
1244 		}
1245 		g_string_assign(var->value, value ? value : "");
1246 		gdb_mi_record_free(record);
1247 
1248 		/* type */
1249 		g_snprintf(command, sizeof command, "-var-info-type \"%s\"", varname);
1250 		exec_sync_command(command, TRUE, &record);
1251 		if (record)
1252 			type = gdb_mi_result_var(record->first, "type", GDB_MI_VAL_STRING);
1253 		g_string_assign(var->type, type ? type : "");
1254 		gdb_mi_record_free(record);
1255 
1256 		vars = vars->next;
1257 	}
1258 }
1259 
1260 /*
1261  * updates files list
1262  */
update_files(void)1263 static void update_files(void)
1264 {
1265 	GHashTable *ht;
1266 	struct gdb_mi_record *record = NULL;
1267 	const struct gdb_mi_result *files_node;
1268 
1269 	if (files)
1270 	{
1271 		/* free previous list */
1272 		g_list_foreach(files, (GFunc)g_free, NULL);
1273 		g_list_free(files);
1274 		files = NULL;
1275 	}
1276 
1277 	exec_sync_command("-file-list-exec-source-files", TRUE, &record);
1278 	if (! record)
1279 		return;
1280 
1281 	ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
1282 
1283 	files_node = gdb_mi_result_var(record->first, "files", GDB_MI_VAL_LIST);
1284 	gdb_mi_result_foreach_matched (files_node, files_node, NULL, GDB_MI_VAL_LIST)
1285 	{
1286 		const gchar *fullname = gdb_mi_result_var(files_node->val->v.list, "fullname", GDB_MI_VAL_STRING);
1287 
1288 		if (fullname && !g_hash_table_lookup(ht, fullname))
1289 		{
1290 			g_hash_table_insert(ht, (gpointer)fullname, (gpointer)1);
1291 			files = g_list_append(files, g_strdup(fullname));
1292 		}
1293 	}
1294 
1295 	g_hash_table_destroy(ht);
1296 	gdb_mi_record_free(record);
1297 }
1298 
1299 /*
1300  * updates watches list
1301  */
update_watches(void)1302 static void update_watches(void)
1303 {
1304 	gchar command[1000];
1305 	GList *updating = NULL;
1306 	GList *iter;
1307 
1308 	/* delete all GDB variables */
1309 	for (iter = watches; iter; iter = iter->next)
1310 	{
1311 		variable *var = (variable*)iter->data;
1312 
1313 		if (var->internal->len)
1314 		{
1315 			g_snprintf(command, sizeof command, "-var-delete %s", var->internal->str);
1316 			exec_sync_command(command, TRUE, NULL);
1317 		}
1318 
1319 		/* reset all variables fields */
1320 		variable_reset(var);
1321 	}
1322 
1323 	/* create GDB variables, adding successfully created
1324 	variables to the list then passed for updatind */
1325 	for (iter = watches; iter; iter = iter->next)
1326 	{
1327 		variable *var = (variable*)iter->data;
1328 		struct gdb_mi_record *record = NULL;
1329 		const gchar *name;
1330 		gchar *escaped;
1331 
1332 		/* try to create variable */
1333 		escaped = escape_string(var->name->str);
1334 		g_snprintf(command, sizeof command, "-var-create - * \"%s\"", escaped);
1335 		g_free(escaped);
1336 
1337 		if (RC_DONE != exec_sync_command(command, TRUE, &record) || !record)
1338 		{
1339 			/* do not include to updating list, move to next watch */
1340 			var->evaluated = FALSE;
1341 			g_string_assign(var->internal, "");
1342 			gdb_mi_record_free(record);
1343 
1344 			continue;
1345 		}
1346 
1347 		/* find and assign internal name */
1348 		name = gdb_mi_result_var(record->first, "name", GDB_MI_VAL_STRING);
1349 		g_string_assign(var->internal, name ? name : "");
1350 		gdb_mi_record_free(record);
1351 
1352 		var->evaluated = name != NULL;
1353 
1354 		/* add to updating list */
1355 		updating = g_list_prepend(updating, var);
1356 	}
1357 	updating = g_list_reverse(updating);
1358 
1359 	/* update watches */
1360 	get_variables(updating);
1361 
1362 	/* free updating list */
1363 	g_list_free(updating);
1364 }
1365 
1366 /*
1367  * updates autos list
1368  */
update_autos(void)1369 static void update_autos(void)
1370 {
1371 	gchar command[1000];
1372 	GList *unevaluated = NULL, *vars = NULL, *iter;
1373 
1374 	/* remove all previous GDB variables for autos */
1375 	for (iter = autos; iter; iter = iter->next)
1376 	{
1377 		variable *var = (variable*)iter->data;
1378 
1379 		g_snprintf(command, sizeof command, "-var-delete %s", var->internal->str);
1380 		exec_sync_command(command, TRUE, NULL);
1381 	}
1382 
1383 	g_list_foreach(autos, (GFunc)variable_free, NULL);
1384 	g_list_free(autos);
1385 	autos = NULL;
1386 
1387 	/* add current autos to the list */
1388 
1389 	struct gdb_mi_record *record = NULL;
1390 
1391 	g_snprintf(command, sizeof command, "-stack-list-arguments 0 %i %i", active_frame, active_frame);
1392 	if (RC_DONE == exec_sync_command(command, TRUE, &record) && record)
1393 	{
1394 		const struct gdb_mi_result *stack_args = gdb_mi_result_var(record->first, "stack-args", GDB_MI_VAL_LIST);
1395 
1396 		gdb_mi_result_foreach_matched (stack_args, stack_args, "frame", GDB_MI_VAL_LIST)
1397 		{
1398 			const struct gdb_mi_result *args = gdb_mi_result_var(stack_args->val->v.list, "args", GDB_MI_VAL_LIST);
1399 
1400 			gdb_mi_result_foreach_matched (args, args, "name", GDB_MI_VAL_STRING)
1401 			{
1402 				variable *var = variable_new(args->val->v.string, VT_ARGUMENT);
1403 				vars = g_list_append(vars, var);
1404 			}
1405 		}
1406 	}
1407 	gdb_mi_record_free(record);
1408 
1409 	if (RC_DONE == exec_sync_command("-stack-list-locals 0", TRUE, &record) && record)
1410 	{
1411 		const struct gdb_mi_result *locals = gdb_mi_result_var(record->first, "locals", GDB_MI_VAL_LIST);
1412 
1413 		gdb_mi_result_foreach_matched (locals, locals, "name", GDB_MI_VAL_STRING)
1414 		{
1415 			variable *var = variable_new(locals->val->v.string, VT_LOCAL);
1416 			vars = g_list_append(vars, var);
1417 		}
1418 	}
1419 	gdb_mi_record_free(record);
1420 
1421 	for (iter = vars; iter; iter = iter->next)
1422 	{
1423 		variable *var = iter->data;
1424 		struct gdb_mi_record *create_record = NULL;
1425 		gchar *escaped;
1426 		const gchar *intname;
1427 
1428 		/* create new gdb variable */
1429 		escaped = escape_string(var->name->str);
1430 		g_snprintf(command, sizeof command, "-var-create - * \"%s\"", escaped);
1431 		g_free(escaped);
1432 
1433 		/* form new variable */
1434 		if (RC_DONE == exec_sync_command(command, TRUE, &create_record) && create_record &&
1435 			(intname = gdb_mi_result_var(create_record->first, "name", GDB_MI_VAL_STRING)))
1436 		{
1437 			var->evaluated = TRUE;
1438 			g_string_assign(var->internal, intname);
1439 			autos = g_list_append(autos, var);
1440 		}
1441 		else
1442 		{
1443 			var->evaluated = FALSE;
1444 			g_string_assign(var->internal, "");
1445 			unevaluated = g_list_append(unevaluated, var);
1446 		}
1447 		gdb_mi_record_free(create_record);
1448 	}
1449 	g_list_free(vars);
1450 
1451 	/* get values for the autos (without incorrect variables) */
1452 	get_variables(autos);
1453 
1454 	/* add incorrect variables */
1455 	autos = g_list_concat(autos, unevaluated);
1456 }
1457 
1458 /*
1459  * get autos list
1460  */
get_autos(void)1461 static GList* get_autos (void)
1462 {
1463 	return g_list_copy(autos);
1464 }
1465 
1466 /*
1467  * get watches list
1468  */
get_watches(void)1469 static GList* get_watches (void)
1470 {
1471 	return g_list_copy(watches);
1472 }
1473 
1474 /*
1475  * get files list
1476  */
get_files(void)1477 static GList* get_files (void)
1478 {
1479 	return g_list_copy(files);
1480 }
1481 
1482 /*
1483  * get list of children
1484  */
get_children(gchar * path)1485 static GList* get_children (gchar* path)
1486 {
1487 	GList *children = NULL;
1488 
1489 	gchar command[1000];
1490 	result_class rc;
1491 	struct gdb_mi_record *record = NULL;
1492 	const gchar *numchild;
1493 	int n;
1494 
1495 	/* children number */
1496 	g_snprintf(command, sizeof command, "-var-info-num-children \"%s\"", path);
1497 	rc = exec_sync_command(command, TRUE, &record);
1498 	if (RC_DONE != rc || ! record)
1499 	{
1500 		gdb_mi_record_free(record);
1501 		return NULL;
1502 	}
1503 	numchild = gdb_mi_result_var(record->first, "numchild", GDB_MI_VAL_STRING);
1504 	n = numchild ? atoi(numchild) : 0;
1505 	gdb_mi_record_free(record);
1506 	if (!n)
1507 		return NULL;
1508 
1509 	/* recursive get children and put into list */
1510 	g_snprintf(command, sizeof command, "-var-list-children \"%s\"", path);
1511 	rc = exec_sync_command(command, TRUE, &record);
1512 	if (RC_DONE == rc && record)
1513 	{
1514 		const struct gdb_mi_result *child_node = gdb_mi_result_var(record->first, "children", GDB_MI_VAL_LIST);
1515 
1516 		gdb_mi_result_foreach_matched (child_node, child_node, "child", GDB_MI_VAL_LIST)
1517 		{
1518 			const gchar *internal = gdb_mi_result_var(child_node->val->v.list, "name", GDB_MI_VAL_STRING);
1519 			const gchar *name = gdb_mi_result_var(child_node->val->v.list, "exp", GDB_MI_VAL_STRING);
1520 			variable *var;
1521 
1522 			if (! name || ! internal)
1523 				continue;
1524 
1525 			var = variable_new2(name, internal, VT_CHILD);
1526 			var->evaluated = TRUE;
1527 
1528 			children = g_list_prepend(children, var);
1529 		}
1530 	}
1531 	gdb_mi_record_free(record);
1532 
1533 	children = g_list_reverse(children);
1534 	get_variables(children);
1535 
1536 	return children;
1537 }
1538 
1539 /*
1540  * add new watch
1541  */
add_watch(gchar * expression)1542 static variable* add_watch(gchar* expression)
1543 {
1544 	gchar command[1000];
1545 	gchar *escaped;
1546 	struct gdb_mi_record *record = NULL;
1547 	const gchar *name;
1548 	GList *vars = NULL;
1549 	variable *var = variable_new(expression, VT_WATCH);
1550 
1551 	watches = g_list_append(watches, var);
1552 
1553 	/* try to create a variable */
1554 	escaped = escape_string(var->name->str);
1555 	g_snprintf(command, sizeof command, "-var-create - * \"%s\"", escaped);
1556 	g_free(escaped);
1557 
1558 	if (RC_DONE != exec_sync_command(command, TRUE, &record) || !record)
1559 	{
1560 		gdb_mi_record_free(record);
1561 		return var;
1562 	}
1563 
1564 	name = gdb_mi_result_var(record->first, "name", GDB_MI_VAL_STRING);
1565 	g_string_assign(var->internal, name ? name : "");
1566 	var->evaluated = name != NULL;
1567 
1568 	vars = g_list_append(NULL, var);
1569 	get_variables(vars);
1570 
1571 	gdb_mi_record_free(record);
1572 	g_list_free(vars);
1573 
1574 	return var;
1575 }
1576 
1577 /*
1578  * remove watch
1579  */
remove_watch(gchar * internal)1580 static void remove_watch(gchar* internal)
1581 {
1582 	GList *iter = watches;
1583 	while (iter)
1584 	{
1585 		variable *var = (variable*)iter->data;
1586 		if (!strcmp(var->internal->str, internal))
1587 		{
1588 			gchar command[1000];
1589 			g_snprintf(command, sizeof command, "-var-delete %s", internal);
1590 			exec_sync_command(command, TRUE, NULL);
1591 			variable_free(var);
1592 			watches = g_list_delete_link(watches, iter);
1593 		}
1594 		iter = iter->next;
1595 	}
1596 }
1597 
1598 /*
1599  * evaluates given expression and returns the result
1600  */
evaluate_expression(gchar * expression)1601 static gchar *evaluate_expression(gchar *expression)
1602 {
1603 	struct gdb_mi_record *record = NULL;
1604 	gchar *value;
1605 	char command[1000];
1606 
1607 	g_snprintf(command, sizeof command, "-data-evaluate-expression \"%s\"", expression);
1608 	if (RC_DONE != exec_sync_command(command, TRUE, &record) || ! record)
1609 	{
1610 		gdb_mi_record_free(record);
1611 		return NULL;
1612 	}
1613 
1614 	value = g_strdup(gdb_mi_result_var(record->first, "value", GDB_MI_VAL_STRING));
1615 	gdb_mi_record_free(record);
1616 
1617 	return value;
1618 }
1619 
1620 /*
1621  * request GDB interrupt
1622  */
request_interrupt(void)1623 static gboolean request_interrupt(void)
1624 {
1625 #ifdef DEBUG_OUTPUT
1626 	char msg[1000];
1627 	g_snprintf(msg, sizeof msg, "interrupting pid=%i", target_pid);
1628 	dbg_cbs->send_message(msg, "red");
1629 #endif
1630 
1631 	requested_interrupt = TRUE;
1632 	kill(target_pid, SIGINT);
1633 
1634 	return TRUE;
1635 }
1636 
1637 /*
1638  * get GDB error messages
1639  */
error_message(void)1640 static gchar* error_message(void)
1641 {
1642 	return err_message;
1643 }
1644 
1645 /*
1646  * define GDB debug module
1647  */
1648 DBG_MODULE_DEFINE(gdb);
1649 
1650 
1651