* gdbtk-cmds.c (gdb_listfuncs): When stripping out "global destructors"
[deliverable/binutils-gdb.git] / gdb / gdbtk-cmds.c
1 /* Tcl/Tk command definitions for gdbtk.
2 Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3
4 Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "symtab.h"
24 #include "inferior.h"
25 #include "command.h"
26 #include "bfd.h"
27 #include "symfile.h"
28 #include "objfiles.h"
29 #include "target.h"
30 #include "gdbcore.h"
31 #include "tracepoint.h"
32 #include "demangle.h"
33
34 #ifdef _WIN32
35 #include <winuser.h>
36 #endif
37
38 #include <sys/stat.h>
39
40 #include <tcl.h>
41 #include <tk.h>
42 #include <itcl.h>
43 #include <tix.h>
44 #include "guitcl.h"
45 #include "gdbtk.h"
46
47 #ifdef IDE
48 /* start-sanitize-ide */
49 #include "event.h"
50 #include "idetcl.h"
51 #include "ilutk.h"
52 /* end-sanitize-ide */
53 #endif
54
55 #ifdef ANSI_PROTOTYPES
56 #include <stdarg.h>
57 #else
58 #include <varargs.h>
59 #endif
60 #include <signal.h>
61 #include <fcntl.h>
62 #include <unistd.h>
63 #include <setjmp.h>
64 #include "top.h"
65 #include <sys/ioctl.h>
66 #include "gdb_string.h"
67 #include "dis-asm.h"
68 #include <stdio.h>
69 #include "gdbcmd.h"
70
71 #include "annotate.h"
72 #include <sys/time.h>
73
74 /* This structure filled in call_wrapper and passed to
75 the wrapped call function.
76 It stores the command pointer and arguments
77 run in the wrapper function. */
78
79 struct wrapped_call_args
80 {
81 Tcl_Interp *interp;
82 Tcl_ObjCmdProc *func;
83 int objc;
84 Tcl_Obj *CONST *objv;
85 int val;
86 };
87
88 /* These two objects hold boolean true and false,
89 and are shared by all the list objects that gdb_listfuncs
90 returns. */
91
92 static Tcl_Obj *mangled, *not_mangled;
93
94 /* These two control how the GUI behaves when gdb is either tracing or loading.
95 They are used in this file & gdbtk_hooks.c */
96
97 int No_Update = 0;
98 int load_in_progress = 0;
99
100 /*
101 * This is used in the register fetching routines
102 */
103
104 #ifndef REGISTER_CONVERTIBLE
105 #define REGISTER_CONVERTIBLE(x) (0 != 0)
106 #endif
107
108 #ifndef REGISTER_CONVERT_TO_VIRTUAL
109 #define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a)
110 #endif
111
112 #ifndef INVALID_FLOAT
113 #define INVALID_FLOAT(x, y) (0 != 0)
114 #endif
115
116
117
118 /* This Structure is used in gdb_disassemble.
119 We need a different sort of line table from the normal one cuz we can't
120 depend upon implicit line-end pc's for lines to do the
121 reordering in this function. */
122
123 struct my_line_entry {
124 int line;
125 CORE_ADDR start_pc;
126 CORE_ADDR end_pc;
127 };
128
129 /* This contains the previous values of the registers, since the last call to
130 gdb_changed_register_list. */
131
132 static char old_regs[REGISTER_BYTES];
133
134 /*
135 * These are routines we need from breakpoint.c.
136 * at some point make these static in breakpoint.c and move GUI code there
137 */
138
139 extern struct breakpoint *set_raw_breakpoint (struct symtab_and_line sal);
140 extern void set_breakpoint_count (int);
141 extern int breakpoint_count;
142
143
144 /*
145 * Declarations for routines exported from this file
146 */
147
148 int Gdbtk_Init (Tcl_Interp *interp);
149
150 /*
151 * Declarations for routines used only in this file.
152 */
153
154 static int compare_lines PARAMS ((const PTR, const PTR));
155 static int comp_files PARAMS ((const void *, const void *));
156 static int call_wrapper PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
157 static int gdb_actions_command PARAMS ((ClientData, Tcl_Interp *, int,
158 Tcl_Obj *CONST objv[]));
159 static int gdb_changed_register_list PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
160 static int gdb_clear_file PARAMS ((ClientData, Tcl_Interp *interp, int, Tcl_Obj *CONST []));
161 static int gdb_cmd PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
162 static int gdb_confirm_quit PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
163 static int gdb_disassemble PARAMS ((ClientData, Tcl_Interp *, int,
164 Tcl_Obj *CONST []));
165 static int gdb_eval PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
166 static int gdb_fetch_registers PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
167 static int gdb_find_file_command PARAMS ((ClientData, Tcl_Interp *, int,
168 Tcl_Obj *CONST objv[]));
169 static int gdb_force_quit PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
170 static struct symtab *full_lookup_symtab PARAMS ((char *file));
171 static int gdb_get_args_command PARAMS ((ClientData, Tcl_Interp *, int,
172 Tcl_Obj *CONST objv[]));
173 static int gdb_get_breakpoint_info PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
174 static int gdb_get_breakpoint_list PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
175 static int gdb_get_file_command PARAMS ((ClientData, Tcl_Interp *, int,
176 Tcl_Obj *CONST objv[]));
177 static int gdb_get_function_command PARAMS ((ClientData, Tcl_Interp *, int,
178 Tcl_Obj *CONST objv[]));
179 static int gdb_get_line_command PARAMS ((ClientData, Tcl_Interp *, int,
180 Tcl_Obj *CONST objv[]));
181 static int gdb_get_locals_command PARAMS ((ClientData, Tcl_Interp *, int,
182 Tcl_Obj *CONST objv[]));
183 static int gdb_get_mem PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
184 static int gdb_get_trace_frame_num PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
185 static int gdb_get_tracepoint_list PARAMS ((ClientData, Tcl_Interp *, int,
186 Tcl_Obj *CONST objv[]));
187 static int gdb_get_vars_command PARAMS ((ClientData, Tcl_Interp *, int,
188 Tcl_Obj *CONST objv[]));
189 static int gdb_immediate_command PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
190 static int gdb_listfiles PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
191 static int gdb_listfuncs PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
192 static int gdb_loadfile PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
193 static int gdb_load_info PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
194 static int gdb_loc PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
195 static int gdb_path_conv PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
196 static int gdb_prompt_command PARAMS ((ClientData, Tcl_Interp *, int,
197 Tcl_Obj *CONST objv[]));
198 static int gdb_regnames PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
199 static int gdb_search PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST
200 objv[]));
201 static int gdb_set_bp PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]));
202 static int gdb_stop PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
203 static int gdb_target_has_execution_command PARAMS ((ClientData, Tcl_Interp *,
204 int,
205 Tcl_Obj *CONST []));
206 static int gdb_trace_status PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
207 static int gdb_tracepoint_exists_command PARAMS ((ClientData, Tcl_Interp *,
208 int,
209 Tcl_Obj *CONST objv[]));
210 static int gdb_get_tracepoint_info PARAMS ((ClientData, Tcl_Interp *, int,
211 Tcl_Obj *CONST objv[]));
212 static int gdbtk_dis_asm_read_memory PARAMS ((bfd_vma, bfd_byte *, int, disassemble_info *));
213 static int get_pc_register PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
214 static int gdb_stack PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
215
216 char * get_prompt PARAMS ((void));
217 static void get_register PARAMS ((int, void *));
218 static void get_register_name PARAMS ((int, void *));
219 static int map_arg_registers PARAMS ((int, Tcl_Obj *CONST [], void (*) (int, void *), void *));
220 static int perror_with_name_wrapper PARAMS ((char *args));
221 static void register_changed_p PARAMS ((int, void *));
222 void TclDebug PARAMS ((const char *fmt, ...));
223 static int wrapped_call (char *opaque_args);
224 static void get_frame_name PARAMS ((Tcl_Interp *interp, Tcl_Obj *list, struct frame_info *fi));
225 \f
226 /* Gdbtk_Init
227 * This loads all the Tcl commands into the Tcl interpreter.
228 *
229 * Arguments:
230 * interp - The interpreter into which to load the commands.
231 *
232 * Result:
233 * A standard Tcl result.
234 */
235
236 int
237 Gdbtk_Init (interp)
238 Tcl_Interp *interp;
239 {
240 Tcl_CreateObjCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
241 Tcl_CreateObjCommand (interp, "gdb_immediate", call_wrapper,
242 gdb_immediate_command, NULL);
243 Tcl_CreateObjCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
244 Tcl_CreateObjCommand (interp, "gdb_path_conv", call_wrapper, gdb_path_conv, NULL);
245 Tcl_CreateObjCommand (interp, "gdb_listfiles", call_wrapper, gdb_listfiles, NULL);
246 Tcl_CreateObjCommand (interp, "gdb_listfuncs", call_wrapper, gdb_listfuncs,
247 NULL);
248 Tcl_CreateObjCommand (interp, "gdb_get_mem", call_wrapper, gdb_get_mem,
249 NULL);
250 Tcl_CreateObjCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
251 Tcl_CreateObjCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
252 Tcl_CreateObjCommand (interp, "gdb_fetch_registers", call_wrapper,
253 gdb_fetch_registers, NULL);
254 Tcl_CreateObjCommand (interp, "gdb_changed_register_list", call_wrapper,
255 gdb_changed_register_list, NULL);
256 Tcl_CreateObjCommand (interp, "gdb_disassemble", call_wrapper,
257 gdb_disassemble, NULL);
258 Tcl_CreateObjCommand (interp, "gdb_eval", call_wrapper, gdb_eval, NULL);
259 Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_list", call_wrapper,
260 gdb_get_breakpoint_list, NULL);
261 Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_info", call_wrapper,
262 gdb_get_breakpoint_info, NULL);
263 Tcl_CreateObjCommand (interp, "gdb_clear_file", call_wrapper,
264 gdb_clear_file, NULL);
265 Tcl_CreateObjCommand (interp, "gdb_confirm_quit", call_wrapper,
266 gdb_confirm_quit, NULL);
267 Tcl_CreateObjCommand (interp, "gdb_force_quit", call_wrapper,
268 gdb_force_quit, NULL);
269 Tcl_CreateObjCommand (interp, "gdb_target_has_execution",
270 call_wrapper,
271 gdb_target_has_execution_command, NULL);
272 Tcl_CreateObjCommand (interp, "gdb_is_tracing",
273 call_wrapper, gdb_trace_status,
274 NULL);
275 Tcl_CreateObjCommand (interp, "gdb_load_info", call_wrapper, gdb_load_info, NULL);
276 Tcl_CreateObjCommand (interp, "gdb_get_locals", call_wrapper, gdb_get_locals_command,
277 NULL);
278 Tcl_CreateObjCommand (interp, "gdb_get_args", call_wrapper, gdb_get_args_command,
279 NULL);
280 Tcl_CreateObjCommand (interp, "gdb_get_function", call_wrapper, gdb_get_function_command,
281 NULL);
282 Tcl_CreateObjCommand (interp, "gdb_get_line", call_wrapper, gdb_get_line_command,
283 NULL);
284 Tcl_CreateObjCommand (interp, "gdb_get_file", call_wrapper, gdb_get_file_command,
285 NULL);
286 Tcl_CreateObjCommand (interp, "gdb_tracepoint_exists",
287 call_wrapper, gdb_tracepoint_exists_command, NULL);
288 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_info",
289 call_wrapper, gdb_get_tracepoint_info, NULL);
290 Tcl_CreateObjCommand (interp, "gdb_actions",
291 call_wrapper, gdb_actions_command, NULL);
292 Tcl_CreateObjCommand (interp, "gdb_prompt",
293 call_wrapper, gdb_prompt_command, NULL);
294 Tcl_CreateObjCommand (interp, "gdb_find_file",
295 call_wrapper, gdb_find_file_command, NULL);
296 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_list",
297 call_wrapper, gdb_get_tracepoint_list, NULL);
298 Tcl_CreateObjCommand (interp, "gdb_pc_reg", call_wrapper, get_pc_register, NULL);
299 Tcl_CreateObjCommand (interp, "gdb_loadfile", call_wrapper, gdb_loadfile, NULL);
300 Tcl_CreateObjCommand (gdbtk_interp, "gdb_search", call_wrapper,
301 gdb_search, NULL);
302 Tcl_CreateObjCommand (interp, "gdb_set_bp", call_wrapper, gdb_set_bp, NULL);
303 Tcl_CreateObjCommand (interp, "gdb_get_trace_frame_num",
304 call_wrapper, gdb_get_trace_frame_num, NULL);
305 Tcl_CreateObjCommand (interp, "gdb_stack", call_wrapper, gdb_stack, NULL);
306
307 Tcl_LinkVar (interp, "gdb_selected_frame_level",
308 (char *) &selected_frame_level,
309 TCL_LINK_INT | TCL_LINK_READ_ONLY);
310
311 /* gdb_context is used for debugging multiple threads or tasks */
312 Tcl_LinkVar (interp, "gdb_context_id",
313 (char *) &gdb_context,
314 TCL_LINK_INT | TCL_LINK_READ_ONLY);
315
316 Tcl_PkgProvide(interp, "Gdbtk", GDBTK_VERSION);
317 return TCL_OK;
318 }
319
320 /* This routine acts as a top-level for all GDB code called by Tcl/Tk. It
321 handles cleanups, and uses catch_errors to trap calls to return_to_top_level
322 (usually via error).
323 This is necessary in order to prevent a longjmp out of the bowels of Tk,
324 possibly leaving things in a bad state. Since this routine can be called
325 recursively, it needs to save and restore the contents of the result_ptr as
326 necessary. */
327
328 static int
329 call_wrapper (clientData, interp, objc, objv)
330 ClientData clientData;
331 Tcl_Interp *interp;
332 int objc;
333 Tcl_Obj *CONST objv[];
334 {
335 struct wrapped_call_args wrapped_args;
336 gdbtk_result new_result, *old_result_ptr;
337
338 old_result_ptr = result_ptr;
339 result_ptr = &new_result;
340 result_ptr->obj_ptr = Tcl_NewObj();
341 result_ptr->flags = GDBTK_TO_RESULT;
342
343 wrapped_args.func = (Tcl_ObjCmdProc *) clientData;
344 wrapped_args.interp = interp;
345 wrapped_args.objc = objc;
346 wrapped_args.objv = objv;
347 wrapped_args.val = TCL_OK;
348
349 if (!catch_errors (wrapped_call, &wrapped_args, "", RETURN_MASK_ALL))
350 {
351
352 wrapped_args.val = TCL_ERROR; /* Flag an error for TCL */
353
354 /* Make sure the timer interrupts are turned off. */
355
356 gdbtk_stop_timer ();
357
358 gdb_flush (gdb_stderr); /* Flush error output */
359 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
360
361 /* If we errored out here, and the results were going to the
362 console, then gdbtk_fputs will have gathered the result into the
363 result_ptr. We also need to echo them out to the console here */
364
365 gdb_flush (gdb_stderr); /* Flush error output */
366 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
367
368 /* In case of an error, we may need to force the GUI into idle
369 mode because gdbtk_call_command may have bombed out while in
370 the command routine. */
371
372 running_now = 0;
373 Tcl_Eval (interp, "gdbtk_tcl_idle");
374
375 }
376
377 /* do not suppress any errors -- a remote target could have errored */
378 load_in_progress = 0;
379
380 /*
381 * Now copy the result over to the true Tcl result. If GDBTK_TO_RESULT flag
382 * bit is set , this just copies a null object over to the Tcl result, which is
383 * fine because we should reset the result in this case anyway.
384 */
385 if (result_ptr->flags & GDBTK_IN_TCL_RESULT)
386 {
387 Tcl_DecrRefCount(result_ptr->obj_ptr);
388 }
389 else
390 {
391 Tcl_SetObjResult (interp, result_ptr->obj_ptr);
392 }
393
394 result_ptr = old_result_ptr;
395
396 #ifdef _WIN32
397 close_bfds ();
398 #endif
399
400 return wrapped_args.val;
401 }
402
403 /*
404 * This is the wrapper that is passed to catch_errors.
405 */
406
407 static int
408 wrapped_call (opaque_args)
409 char *opaque_args;
410 {
411 struct wrapped_call_args *args = (struct wrapped_call_args *) opaque_args;
412 args->val = (*args->func) (args->func, args->interp, args->objc, args->objv);
413 return 1;
414 }
415
416 /* This is a convenience function to sprintf something(s) into a
417 * new element in a Tcl list object.
418 */
419
420 static void
421 #ifdef ANSI_PROTOTYPES
422 sprintf_append_element_to_obj (Tcl_Obj *objp, char *format, ...)
423 #else
424 sprintf_append_element_to_obj (va_alist)
425 va_dcl
426 #endif
427 {
428 va_list args;
429 char buf[1024];
430
431 #ifdef ANSI_PROTOTYPES
432 va_start (args, format);
433 #else
434 Tcl_Obj *objp;
435 char *format;
436
437 va_start (args);
438 dsp = va_arg (args, Tcl_Obj *);
439 format = va_arg (args, char *);
440 #endif
441
442 vsprintf (buf, format, args);
443
444 Tcl_ListObjAppendElement (NULL, objp, Tcl_NewStringObj (buf, -1));
445 }
446 \f
447 /*
448 * This section contains the commands that control execution.
449 */
450
451 /* This implements the tcl command gdb_clear_file.
452 *
453 * Prepare to accept a new executable file. This is called when we
454 * want to clear away everything we know about the old file, without
455 * asking the user. The Tcl code will have already asked the user if
456 * necessary. After this is called, we should be able to run the
457 * `file' command without getting any questions.
458 *
459 * Arguments:
460 * None
461 * Tcl Result:
462 * None
463 */
464
465 static int
466 gdb_clear_file (clientData, interp, objc, objv)
467 ClientData clientData;
468 Tcl_Interp *interp;
469 int objc;
470 Tcl_Obj *CONST objv[];
471 {
472 if (objc != 1)
473 Tcl_SetStringObj (result_ptr->obj_ptr,
474 "Wrong number of args, none are allowed.", -1);
475
476 if (inferior_pid != 0 && target_has_execution)
477 {
478 if (attach_flag)
479 target_detach (NULL, 0);
480 else
481 target_kill ();
482 }
483
484 if (target_has_execution)
485 pop_target ();
486
487 symbol_file_command (NULL, 0);
488
489 /* gdb_loc refers to stop_pc, but nothing seems to clear it, so we
490 clear it here. FIXME: This seems like an abstraction violation
491 somewhere. */
492 stop_pc = 0;
493
494 return TCL_OK;
495 }
496
497 /* This implements the tcl command gdb_confirm_quit
498 * Ask the user to confirm an exit request.
499 *
500 * Arguments:
501 * None
502 * Tcl Result:
503 * A boolean, 1 if the user answered yes, 0 if no.
504 */
505
506 static int
507 gdb_confirm_quit (clientData, interp, objc, objv)
508 ClientData clientData;
509 Tcl_Interp *interp;
510 int objc;
511 Tcl_Obj *CONST objv[];
512 {
513 int ret;
514
515 if (objc != 1)
516 {
517 Tcl_SetStringObj (result_ptr->obj_ptr, "Wrong number of args, should be none.", -1);
518 return TCL_ERROR;
519 }
520
521 ret = quit_confirm ();
522 Tcl_SetBooleanObj (result_ptr->obj_ptr, ret);
523 return TCL_OK;
524 }
525
526 /* This implements the tcl command gdb_force_quit
527 * Quit without asking for confirmation.
528 *
529 * Arguments:
530 * None
531 * Tcl Result:
532 * None
533 */
534
535 static int
536 gdb_force_quit (clientData, interp, objc, objv)
537 ClientData clientData;
538 Tcl_Interp *interp;
539 int objc;
540 Tcl_Obj *CONST objv[];
541 {
542 if (objc != 1)
543 {
544 Tcl_SetStringObj (result_ptr->obj_ptr, "Wrong number of args, should be none.", -1);
545 return TCL_ERROR;
546 }
547
548 quit_force ((char *) NULL, 1);
549 return TCL_OK;
550 }
551
552 /* This implements the tcl command gdb_stop
553 * It stops the target in a continuable fashion.
554 *
555 * Arguments:
556 * None
557 * Tcl Result:
558 * None
559 */
560
561 static int
562 gdb_stop (clientData, interp, objc, objv)
563 ClientData clientData;
564 Tcl_Interp *interp;
565 int objc;
566 Tcl_Obj *CONST objv[];
567 {
568 if (target_stop)
569 {
570 target_stop ();
571 }
572 else
573 quit_flag = 1; /* hope something sees this */
574
575 return TCL_OK;
576 }
577
578 \f
579 /*
580 * This section contains Tcl commands that are wrappers for invoking
581 * the GDB command interpreter.
582 */
583
584
585 /* This implements the tcl command `gdb_eval'.
586 * It uses the gdb evaluator to return the value of
587 * an expression in the current language
588 *
589 * Tcl Arguments:
590 * expression - the expression to evaluate.
591 * Tcl Result:
592 * The result of the evaluation.
593 */
594
595 static int
596 gdb_eval (clientData, interp, objc, objv)
597 ClientData clientData;
598 Tcl_Interp *interp;
599 int objc;
600 Tcl_Obj *CONST objv[];
601 {
602 struct expression *expr;
603 struct cleanup *old_chain=NULL;
604 value_ptr val;
605
606 if (objc != 2)
607 {
608 Tcl_SetStringObj (result_ptr->obj_ptr,
609 "wrong # args, should be \"gdb_eval expression\"", -1);
610 return TCL_ERROR;
611 }
612
613 expr = parse_expression (Tcl_GetStringFromObj (objv[1], NULL));
614
615 old_chain = make_cleanup (free_current_contents, &expr);
616
617 val = evaluate_expression (expr);
618
619 /*
620 * Print the result of the expression evaluation. This will go to
621 * eventually go to gdbtk_fputs, and from there be collected into
622 * the Tcl result.
623 */
624
625 val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val),
626 gdb_stdout, 0, 0, 0, 0);
627
628 do_cleanups (old_chain);
629
630 return TCL_OK;
631 }
632
633 /* This implements the tcl command "gdb_cmd".
634 *
635 * It sends its argument to the GDB command scanner for execution.
636 * This command will never cause the update, idle and busy hooks to be called
637 * within the GUI.
638 *
639 * Tcl Arguments:
640 * command - The GDB command to execute
641 * Tcl Result:
642 * The output from the gdb command (except for the "load" & "while"
643 * which dump their output to the console.
644 */
645
646 static int
647 gdb_cmd (clientData, interp, objc, objv)
648 ClientData clientData;
649 Tcl_Interp *interp;
650 int objc;
651 Tcl_Obj *CONST objv[];
652 {
653
654 if (objc < 2)
655 {
656 Tcl_SetStringObj (result_ptr->obj_ptr, "wrong # args", -1);
657 return TCL_ERROR;
658 }
659
660 if (running_now || load_in_progress)
661 return TCL_OK;
662
663 No_Update = 1;
664
665 /* for the load instruction (and possibly others later) we
666 set turn off the GDBTK_TO_RESULT flag bit so gdbtk_fputs()
667 will not buffer all the data until the command is finished. */
668
669 if ((strncmp ("load ", Tcl_GetStringFromObj (objv[1], NULL), 5) == 0)
670 || (strncmp ("while ", Tcl_GetStringFromObj (objv[1], NULL), 6) == 0))
671 {
672 result_ptr->flags &= ~GDBTK_TO_RESULT;
673 load_in_progress = 1;
674 gdbtk_start_timer ();
675 }
676
677 execute_command (Tcl_GetStringFromObj (objv[1], NULL), 1);
678
679 if (load_in_progress)
680 {
681 gdbtk_stop_timer ();
682 load_in_progress = 0;
683 result_ptr->flags |= GDBTK_TO_RESULT;
684 }
685
686 bpstat_do_actions (&stop_bpstat);
687
688 return TCL_OK;
689 }
690
691 /*
692 * This implements the tcl command "gdb_immediate"
693 *
694 * It does exactly the same thing as gdb_cmd, except NONE of its outut
695 * is buffered. This will also ALWAYS cause the busy, update, and idle hooks to
696 * be called, contrasted with gdb_cmd, which NEVER calls them.
697 * It turns off the GDBTK_TO_RESULT flag, which diverts the result
698 * to the console window.
699 *
700 * Tcl Arguments:
701 * command - The GDB command to execute
702 * Tcl Result:
703 * None.
704 */
705
706 static int
707 gdb_immediate_command (clientData, interp, objc, objv)
708 ClientData clientData;
709 Tcl_Interp *interp;
710 int objc;
711 Tcl_Obj *CONST objv[];
712 {
713
714 if (objc != 2)
715 {
716 Tcl_SetStringObj (result_ptr->obj_ptr, "wrong # args", -1);
717 return TCL_ERROR;
718 }
719
720 if (running_now || load_in_progress)
721 return TCL_OK;
722
723 No_Update = 0;
724
725 result_ptr->flags &= ~GDBTK_TO_RESULT;
726
727 execute_command (Tcl_GetStringFromObj (objv[1], NULL), 1);
728
729 bpstat_do_actions (&stop_bpstat);
730
731 result_ptr->flags |= GDBTK_TO_RESULT;
732
733 return TCL_OK;
734 }
735
736 /* This implements the tcl command "gdb_prompt"
737 *
738 * It returns the gdb interpreter's prompt.
739 *
740 * Tcl Arguments:
741 * None.
742 * Tcl Result:
743 * The prompt.
744 */
745
746 static int
747 gdb_prompt_command (clientData, interp, objc, objv)
748 ClientData clientData;
749 Tcl_Interp *interp;
750 int objc;
751 Tcl_Obj *CONST objv[];
752 {
753 Tcl_SetStringObj (result_ptr->obj_ptr, get_prompt (), -1);
754 return TCL_OK;
755 }
756
757 \f
758 /*
759 * This section contains general informational commands.
760 */
761
762 /* This implements the tcl command "gdb_target_has_execution"
763 *
764 * Tells whether the target is executing.
765 *
766 * Tcl Arguments:
767 * None
768 * Tcl Result:
769 * A boolean indicating whether the target is executing.
770 */
771
772 static int
773 gdb_target_has_execution_command (clientData, interp, objc, objv)
774 ClientData clientData;
775 Tcl_Interp *interp;
776 int objc;
777 Tcl_Obj *CONST objv[];
778 {
779 int result = 0;
780
781 if (target_has_execution && inferior_pid != 0)
782 result = 1;
783
784 Tcl_SetBooleanObj (result_ptr->obj_ptr, result);
785 return TCL_OK;
786 }
787
788 /* This implements the tcl command "gdb_load_info"
789 *
790 * It returns information about the file about to be downloaded.
791 *
792 * Tcl Arguments:
793 * filename: The file to open & get the info on.
794 * Tcl Result:
795 * A list consisting of the name and size of each section.
796 */
797
798 static int
799 gdb_load_info (clientData, interp, objc, objv)
800 ClientData clientData;
801 Tcl_Interp *interp;
802 int objc;
803 Tcl_Obj *CONST objv[];
804 {
805 bfd *loadfile_bfd;
806 struct cleanup *old_cleanups;
807 asection *s;
808 Tcl_Obj *ob[2];
809
810 char *filename = Tcl_GetStringFromObj (objv[1], NULL);
811
812 loadfile_bfd = bfd_openr (filename, gnutarget);
813 if (loadfile_bfd == NULL)
814 {
815 Tcl_SetStringObj (result_ptr->obj_ptr, "Open failed", -1);
816 return TCL_ERROR;
817 }
818 old_cleanups = make_cleanup (bfd_close, loadfile_bfd);
819
820 if (!bfd_check_format (loadfile_bfd, bfd_object))
821 {
822 Tcl_SetStringObj (result_ptr->obj_ptr, "Bad Object File", -1);
823 return TCL_ERROR;
824 }
825
826 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
827
828 for (s = loadfile_bfd->sections; s; s = s->next)
829 {
830 if (s->flags & SEC_LOAD)
831 {
832 bfd_size_type size = bfd_get_section_size_before_reloc (s);
833 if (size > 0)
834 {
835 ob[0] = Tcl_NewStringObj ((char *) bfd_get_section_name (loadfile_bfd, s), -1);
836 ob[1] = Tcl_NewLongObj ((long) size);
837 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewListObj (2, ob));
838 }
839 }
840 }
841
842 do_cleanups (old_cleanups);
843 return TCL_OK;
844 }
845
846
847 /* gdb_get_locals -
848 * This and gdb_get_locals just call gdb_get_vars_command with the right
849 * value of clientData. We can't use the client data in the definition
850 * of the command, because the call wrapper uses this instead...
851 */
852
853 static int
854 gdb_get_locals_command (clientData, interp, objc, objv)
855 ClientData clientData;
856 Tcl_Interp *interp;
857 int objc;
858 Tcl_Obj *CONST objv[];
859 {
860
861 return gdb_get_vars_command((ClientData) 0, interp, objc, objv);
862
863 }
864
865 static int
866 gdb_get_args_command (clientData, interp, objc, objv)
867 ClientData clientData;
868 Tcl_Interp *interp;
869 int objc;
870 Tcl_Obj *CONST objv[];
871 {
872
873 return gdb_get_vars_command((ClientData) 1, interp, objc, objv);
874
875 }
876
877 /* This implements the tcl commands "gdb_get_locals" and "gdb_get_args"
878 *
879 * This function sets the Tcl interpreter's result to a list of variable names
880 * depending on clientData. If clientData is one, the result is a list of
881 * arguments; zero returns a list of locals -- all relative to the block
882 * specified as an argument to the command. Valid commands include
883 * anything decode_line_1 can handle (like "main.c:2", "*0x02020202",
884 * and "main").
885 *
886 * Tcl Arguments:
887 * block - the address within which to specify the locals or args.
888 * Tcl Result:
889 * A list of the locals or args
890 */
891
892 static int
893 gdb_get_vars_command (clientData, interp, objc, objv)
894 ClientData clientData;
895 Tcl_Interp *interp;
896 int objc;
897 Tcl_Obj *CONST objv[];
898 {
899 struct symtabs_and_lines sals;
900 struct symbol *sym;
901 struct block *block;
902 char **canonical, *args;
903 int i, nsyms, arguments;
904
905 if (objc != 2)
906 {
907 Tcl_AppendStringsToObj (result_ptr->obj_ptr,
908 "wrong # of args: should be \"",
909 Tcl_GetStringFromObj (objv[0], NULL),
910 " function:line|function|line|*addr\"", NULL);
911 return TCL_ERROR;
912 }
913
914 arguments = (int) clientData;
915 args = Tcl_GetStringFromObj (objv[1], NULL);
916 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
917 if (sals.nelts == 0)
918 {
919 Tcl_SetStringObj (result_ptr->obj_ptr,
920 "error decoding line", -1);
921 return TCL_ERROR;
922 }
923
924 /* Initialize the result pointer to an empty list. */
925
926 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
927
928 /* Resolve all line numbers to PC's */
929 for (i = 0; i < sals.nelts; i++)
930 resolve_sal_pc (&sals.sals[i]);
931
932 block = block_for_pc (sals.sals[0].pc);
933 while (block != 0)
934 {
935 nsyms = BLOCK_NSYMS (block);
936 for (i = 0; i < nsyms; i++)
937 {
938 sym = BLOCK_SYM (block, i);
939 switch (SYMBOL_CLASS (sym)) {
940 default:
941 case LOC_UNDEF: /* catches errors */
942 case LOC_CONST: /* constant */
943 case LOC_TYPEDEF: /* local typedef */
944 case LOC_LABEL: /* local label */
945 case LOC_BLOCK: /* local function */
946 case LOC_CONST_BYTES: /* loc. byte seq. */
947 case LOC_UNRESOLVED: /* unresolved static */
948 case LOC_OPTIMIZED_OUT: /* optimized out */
949 break;
950 case LOC_ARG: /* argument */
951 case LOC_REF_ARG: /* reference arg */
952 case LOC_REGPARM: /* register arg */
953 case LOC_REGPARM_ADDR: /* indirect register arg */
954 case LOC_LOCAL_ARG: /* stack arg */
955 case LOC_BASEREG_ARG: /* basereg arg */
956 if (arguments)
957 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
958 Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
959 break;
960 case LOC_LOCAL: /* stack local */
961 case LOC_BASEREG: /* basereg local */
962 case LOC_STATIC: /* static */
963 case LOC_REGISTER: /* register */
964 if (!arguments)
965 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
966 Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
967 break;
968 }
969 }
970 if (BLOCK_FUNCTION (block))
971 break;
972 else
973 block = BLOCK_SUPERBLOCK (block);
974 }
975
976 return TCL_OK;
977 }
978
979 /* This implements the tcl command "gdb_get_line"
980 *
981 * It returns the linenumber for a given linespec. It will take any spec
982 * that can be passed to decode_line_1
983 *
984 * Tcl Arguments:
985 * linespec - the line specification
986 * Tcl Result:
987 * The line number for that spec.
988 */
989 static int
990 gdb_get_line_command (clientData, interp, objc, objv)
991 ClientData clientData;
992 Tcl_Interp *interp;
993 int objc;
994 Tcl_Obj *CONST objv[];
995 {
996 struct symtabs_and_lines sals;
997 char *args, **canonical;
998
999 if (objc != 2)
1000 {
1001 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "wrong # of args: should be \"",
1002 Tcl_GetStringFromObj (objv[0], NULL),
1003 " linespec\"", NULL);
1004 return TCL_ERROR;
1005 }
1006
1007 args = Tcl_GetStringFromObj (objv[1], NULL);
1008 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1009 if (sals.nelts == 1)
1010 {
1011 Tcl_SetIntObj (result_ptr->obj_ptr, sals.sals[0].line);
1012 return TCL_OK;
1013 }
1014
1015 Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1);
1016 return TCL_OK;
1017
1018 }
1019
1020 /* This implements the tcl command "gdb_get_file"
1021 *
1022 * It returns the file containing a given line spec.
1023 *
1024 * Tcl Arguments:
1025 * linespec - The linespec to look up
1026 * Tcl Result:
1027 * The file containing it.
1028 */
1029
1030 static int
1031 gdb_get_file_command (clientData, interp, objc, objv)
1032 ClientData clientData;
1033 Tcl_Interp *interp;
1034 int objc;
1035 Tcl_Obj *CONST objv[];
1036 {
1037 struct symtabs_and_lines sals;
1038 char *args, **canonical;
1039
1040 if (objc != 2)
1041 {
1042 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "wrong # of args: should be \"",
1043 Tcl_GetStringFromObj (objv[0], NULL),
1044 " linespec\"", NULL);
1045 return TCL_ERROR;
1046 }
1047
1048 args = Tcl_GetStringFromObj (objv[1], NULL);
1049 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1050 if (sals.nelts == 1)
1051 {
1052 Tcl_SetStringObj (result_ptr->obj_ptr, sals.sals[0].symtab->filename, -1);
1053 return TCL_OK;
1054 }
1055
1056 Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1);
1057 return TCL_OK;
1058 }
1059
1060 /* This implements the tcl command "gdb_get_function"
1061 *
1062 * It finds the function containing the given line spec.
1063 *
1064 * Tcl Arguments:
1065 * linespec - The line specification
1066 * Tcl Result:
1067 * The function that contains it, or "N/A" if it is not in a function.
1068 */
1069 static int
1070 gdb_get_function_command (clientData, interp, objc, objv)
1071 ClientData clientData;
1072 Tcl_Interp *interp;
1073 int objc;
1074 Tcl_Obj *CONST objv[];
1075 {
1076 char *function;
1077 struct symtabs_and_lines sals;
1078 char *args, **canonical;
1079
1080 if (objc != 2)
1081 {
1082 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "wrong # of args: should be \"",
1083 Tcl_GetStringFromObj (objv[0], NULL),
1084 " linespec\"", NULL);
1085 return TCL_ERROR;
1086 }
1087
1088 args = Tcl_GetStringFromObj (objv[1], NULL);
1089 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1090 if (sals.nelts == 1)
1091 {
1092 resolve_sal_pc (&sals.sals[0]);
1093 find_pc_partial_function (sals.sals[0].pc, &function, NULL, NULL);
1094 if (function != NULL)
1095 {
1096 Tcl_SetStringObj (result_ptr->obj_ptr, function, -1);
1097 return TCL_OK;
1098 }
1099 }
1100
1101 Tcl_SetStringObj (result_ptr->obj_ptr, "N/A", -1);
1102 return TCL_OK;
1103 }
1104
1105 /* This implements the tcl command "gdb_find_file"
1106 *
1107 * It searches the symbol tables to get the full pathname to a file.
1108 *
1109 * Tcl Arguments:
1110 * filename: the file name to search for.
1111 * Tcl Result:
1112 * The full path to the file, or an empty string if the file is not
1113 * found.
1114 */
1115
1116 static int
1117 gdb_find_file_command (clientData, interp, objc, objv)
1118 ClientData clientData;
1119 Tcl_Interp *interp;
1120 int objc;
1121 Tcl_Obj *CONST objv[];
1122 {
1123 char *filename = NULL;
1124 struct symtab *st;
1125
1126 if (objc != 2)
1127 {
1128 Tcl_WrongNumArgs(interp, 1, objv, "filename");
1129 return TCL_ERROR;
1130 }
1131
1132 st = full_lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
1133 if (st)
1134 filename = st->fullname;
1135
1136 if (filename == NULL)
1137 Tcl_SetStringObj (result_ptr->obj_ptr, "", 0);
1138 else
1139 Tcl_SetStringObj (result_ptr->obj_ptr, filename, -1);
1140
1141 return TCL_OK;
1142 }
1143
1144 /* This implements the tcl command "gdb_listfiles"
1145 *
1146 * This lists all the files in the current executible.
1147 *
1148 * Note that this currently pulls in all sorts of filenames
1149 * that aren't really part of the executable. It would be
1150 * best if we could check each file to see if it actually
1151 * contains executable lines of code, but we can't do that
1152 * with psymtabs.
1153 *
1154 * Arguments:
1155 * ?pathname? - If provided, only files which match pathname
1156 * (up to strlen(pathname)) are included. THIS DOES NOT
1157 * CURRENTLY WORK BECAUSE PARTIAL_SYMTABS DON'T SUPPLY
1158 * THE FULL PATHNAME!!!
1159 *
1160 * Tcl Result:
1161 * A list of all matching files.
1162 */
1163 static int
1164 gdb_listfiles (clientData, interp, objc, objv)
1165 ClientData clientData;
1166 Tcl_Interp *interp;
1167 int objc;
1168 Tcl_Obj *CONST objv[];
1169 {
1170 struct objfile *objfile;
1171 struct partial_symtab *psymtab;
1172 struct symtab *symtab;
1173 char *lastfile, *pathname=NULL, **files;
1174 int files_size;
1175 int i, numfiles = 0, len = 0;
1176
1177 files_size = 1000;
1178 files = (char **) xmalloc (sizeof (char *) * files_size);
1179
1180 if (objc > 2)
1181 {
1182 Tcl_WrongNumArgs (interp, 1, objv, "Usage: gdb_listfiles ?pathname?");
1183 return TCL_ERROR;
1184 }
1185 else if (objc == 2)
1186 pathname = Tcl_GetStringFromObj (objv[1], &len);
1187
1188 ALL_PSYMTABS (objfile, psymtab)
1189 {
1190 if (numfiles == files_size)
1191 {
1192 files_size = files_size * 2;
1193 files = (char **) xrealloc (files, sizeof (char *) * files_size);
1194 }
1195 if (psymtab->filename)
1196 {
1197 if (!len || !strncmp(pathname, psymtab->filename,len)
1198 || !strcmp(psymtab->filename, basename(psymtab->filename)))
1199 {
1200 files[numfiles++] = basename(psymtab->filename);
1201 }
1202 }
1203 }
1204
1205 ALL_SYMTABS (objfile, symtab)
1206 {
1207 if (numfiles == files_size)
1208 {
1209 files_size = files_size * 2;
1210 files = (char **) xrealloc (files, sizeof (char *) * files_size);
1211 }
1212 if (symtab->filename && symtab->linetable && symtab->linetable->nitems)
1213 {
1214 if (!len || !strncmp(pathname, symtab->filename,len)
1215 || !strcmp(symtab->filename, basename(symtab->filename)))
1216 {
1217 files[numfiles++] = basename(symtab->filename);
1218 }
1219 }
1220 }
1221
1222 qsort (files, numfiles, sizeof(char *), comp_files);
1223
1224 lastfile = "";
1225
1226 /* Discard the old result pointer, in case it has accumulated anything
1227 and set it to a new list object */
1228
1229 Tcl_SetListObj(result_ptr->obj_ptr, 0, NULL);
1230
1231 for (i = 0; i < numfiles; i++)
1232 {
1233 if (strcmp(files[i],lastfile))
1234 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewStringObj(files[i], -1));
1235 lastfile = files[i];
1236 }
1237
1238 free (files);
1239 return TCL_OK;
1240 }
1241
1242 static int
1243 comp_files (file1, file2)
1244 const void *file1, *file2;
1245 {
1246 return strcmp(* (char **) file1, * (char **) file2);
1247 }
1248
1249
1250 /* This implements the tcl command "gdb_search"
1251 *
1252 *
1253 * Tcl Arguments:
1254 * option - One of "functions", "variables" or "types"
1255 * regexp - The regular expression to look for.
1256 * Then, optionally:
1257 * -files fileList
1258 * -static 1/0
1259 * Tcl Result:
1260 *
1261 */
1262
1263 static int
1264 gdb_search (clientData, interp, objc, objv)
1265 ClientData clientData;
1266 Tcl_Interp *interp;
1267 int objc;
1268 Tcl_Obj *CONST objv[];
1269 {
1270 struct symbol_search *ss = NULL;
1271 struct symbol_search *p;
1272 struct cleanup *old_chain = NULL;
1273 Tcl_Obj *CONST *switch_objv;
1274 int index, switch_objc, i;
1275 namespace_enum space = 0;
1276 char *regexp;
1277 int static_only, nfiles;
1278 Tcl_Obj **file_list;
1279 char **files;
1280 static char *search_options[] = { "functions", "variables", "types", (char *) NULL };
1281 static char *switches[] = { "-files", "-static", (char *) NULL };
1282 enum search_opts { SEARCH_FUNCTIONS, SEARCH_VARIABLES, SEARCH_TYPES };
1283 enum switches_opts { SWITCH_FILES, SWITCH_STATIC_ONLY };
1284
1285 if (objc < 3)
1286 {
1287 Tcl_WrongNumArgs (interp, 1, objv, "option regexp ?arg ...?");
1288 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1289 return TCL_ERROR;
1290 }
1291
1292 if (Tcl_GetIndexFromObj (interp, objv[1], search_options, "option", 0,
1293 &index) != TCL_OK)
1294 {
1295 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1296 return TCL_ERROR;
1297 }
1298
1299 /* Unfortunately, we cannot teach search_symbols to search on
1300 multiple regexps, so we have to do a two-tier search for
1301 any searches which choose to narrow the playing field. */
1302 switch ((enum search_opts) index)
1303 {
1304 case SEARCH_FUNCTIONS:
1305 space = FUNCTIONS_NAMESPACE; break;
1306 case SEARCH_VARIABLES:
1307 space = VARIABLES_NAMESPACE; break;
1308 case SEARCH_TYPES:
1309 space = TYPES_NAMESPACE; break;
1310 }
1311
1312 regexp = Tcl_GetStringFromObj (objv[2], NULL);
1313 /* Process any switches that refine the search */
1314 switch_objc = objc - 3;
1315 switch_objv = objv + 3;
1316
1317 static_only = 0;
1318 nfiles = 0;
1319 files = (char **) NULL;
1320 while (switch_objc > 0)
1321 {
1322 if (Tcl_GetIndexFromObj (interp, switch_objv[0], switches,
1323 "option", 0, &index) != TCL_OK)
1324 {
1325 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1326 return TCL_ERROR;
1327 }
1328
1329 switch ((enum switches_opts) index)
1330 {
1331 case SWITCH_FILES:
1332 {
1333 int result;
1334 if (switch_objc < 2)
1335 {
1336 Tcl_WrongNumArgs (interp, 2, objv, "[-files fileList -static 1|0]");
1337 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1338 return TCL_ERROR;
1339 }
1340 result = Tcl_ListObjGetElements (interp, switch_objv[1], &nfiles, &file_list);
1341 if (result != TCL_OK)
1342 return result;
1343
1344 files = (char **) xmalloc (nfiles * sizeof (char *));
1345 for (i = 0; i < nfiles; i++)
1346 files[i] = Tcl_GetStringFromObj (file_list[i], NULL);
1347 switch_objc--;
1348 switch_objv++;
1349 }
1350 break;
1351 case SWITCH_STATIC_ONLY:
1352 if (switch_objc < 2)
1353 {
1354 Tcl_WrongNumArgs (interp, 2, objv, "[-files fileList] [-static 1|0]");
1355 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1356 return TCL_ERROR;
1357 }
1358 if ( Tcl_GetBooleanFromObj (interp, switch_objv[1], &static_only) !=
1359 TCL_OK) {
1360 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1361 return TCL_ERROR;
1362 }
1363 switch_objc--;
1364 switch_objv++;
1365 }
1366 switch_objc--;
1367 switch_objv++;
1368 }
1369
1370 search_symbols (regexp, space, nfiles, files, &ss);
1371 if (ss != NULL)
1372 old_chain = make_cleanup (free_search_symbols, ss);
1373
1374 Tcl_SetListObj(result_ptr->obj_ptr, 0, NULL);
1375
1376 for (p = ss; p != NULL; p = p->next)
1377 {
1378 Tcl_Obj *elem;
1379
1380 if (static_only && p->block != STATIC_BLOCK)
1381 continue;
1382
1383 elem = Tcl_NewListObj (0, NULL);
1384
1385 if (p->msymbol == NULL)
1386 Tcl_ListObjAppendElement (interp, elem,
1387 Tcl_NewStringObj (SYMBOL_SOURCE_NAME (p->symbol), -1));
1388 else
1389 Tcl_ListObjAppendElement (interp, elem,
1390 Tcl_NewStringObj (SYMBOL_SOURCE_NAME (p->msymbol), -1));
1391
1392 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, elem);
1393 }
1394
1395 if (ss != NULL)
1396 do_cleanups (old_chain);
1397
1398 return TCL_OK;
1399 }
1400
1401 /* This implements the tcl command gdb_listfuncs
1402 *
1403 * It lists all the functions defined in a given file
1404 *
1405 * Arguments:
1406 * file - the file to look in
1407 * Tcl Result:
1408 * A list of two element lists, the first element is
1409 * the symbol name, and the second is a boolean indicating
1410 * whether the symbol is demangled (1 for yes).
1411 */
1412
1413 static int
1414 gdb_listfuncs (clientData, interp, objc, objv)
1415 ClientData clientData;
1416 Tcl_Interp *interp;
1417 int objc;
1418 Tcl_Obj *CONST objv[];
1419 {
1420 struct symtab *symtab;
1421 struct blockvector *bv;
1422 struct block *b;
1423 struct symbol *sym;
1424 int i,j;
1425 Tcl_Obj *funcVals[2];
1426
1427 if (objc != 2)
1428 {
1429 Tcl_SetStringObj (result_ptr->obj_ptr, "wrong # args", -1);
1430 }
1431
1432 symtab = full_lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
1433 if (!symtab)
1434 {
1435 Tcl_SetStringObj (result_ptr->obj_ptr, "No such file", -1);
1436 return TCL_ERROR;
1437 }
1438
1439 if (mangled == NULL)
1440 {
1441 mangled = Tcl_NewBooleanObj(1);
1442 not_mangled = Tcl_NewBooleanObj(0);
1443 Tcl_IncrRefCount(mangled);
1444 Tcl_IncrRefCount(not_mangled);
1445 }
1446
1447 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
1448
1449 bv = BLOCKVECTOR (symtab);
1450 for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
1451 {
1452 b = BLOCKVECTOR_BLOCK (bv, i);
1453 /* Skip the sort if this block is always sorted. */
1454 if (!BLOCK_SHOULD_SORT (b))
1455 sort_block_syms (b);
1456 for (j = 0; j < BLOCK_NSYMS (b); j++)
1457 {
1458 sym = BLOCK_SYM (b, j);
1459 if (SYMBOL_CLASS (sym) == LOC_BLOCK)
1460 {
1461
1462 char *name = cplus_demangle (SYMBOL_NAME(sym), 0);
1463 if (name)
1464 {
1465 /* strip out "global constructors" and "global destructors" */
1466 /* because we aren't interested in them. */
1467 if (strncmp (name, "global ", 7))
1468 {
1469 funcVals[0] = Tcl_NewStringObj(name, -1);
1470 funcVals[1] = mangled;
1471 }
1472 else
1473 continue;
1474
1475 }
1476 else
1477 {
1478 funcVals[0] = Tcl_NewStringObj(SYMBOL_NAME(sym), -1);
1479 funcVals[1] = not_mangled;
1480 }
1481 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
1482 Tcl_NewListObj (2, funcVals));
1483 }
1484 }
1485 }
1486 return TCL_OK;
1487 }
1488
1489 \f
1490 /*
1491 * This section contains all the commands that act on the registers:
1492 */
1493
1494 /* This is a sort of mapcar function for operations on registers */
1495
1496 static int
1497 map_arg_registers (objc, objv, func, argp)
1498 int objc;
1499 Tcl_Obj *CONST objv[];
1500 void (*func) PARAMS ((int regnum, void *argp));
1501 void *argp;
1502 {
1503 int regnum;
1504
1505 /* Note that the test for a valid register must include checking the
1506 reg_names array because NUM_REGS may be allocated for the union of the
1507 register sets within a family of related processors. In this case, the
1508 trailing entries of reg_names will change depending upon the particular
1509 processor being debugged. */
1510
1511 if (objc == 0) /* No args, just do all the regs */
1512 {
1513 for (regnum = 0;
1514 regnum < NUM_REGS
1515 && reg_names[regnum] != NULL
1516 && *reg_names[regnum] != '\000';
1517 regnum++)
1518 func (regnum, argp);
1519
1520 return TCL_OK;
1521 }
1522
1523 /* Else, list of register #s, just do listed regs */
1524 for (; objc > 0; objc--, objv++)
1525 {
1526 if (Tcl_GetIntFromObj (NULL, *objv, &regnum) != TCL_OK)
1527 {
1528 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1529 return TCL_ERROR;
1530 }
1531
1532 if (regnum >= 0
1533 && regnum < NUM_REGS
1534 && reg_names[regnum] != NULL
1535 && *reg_names[regnum] != '\000')
1536 func (regnum, argp);
1537 else
1538 {
1539 Tcl_SetStringObj (result_ptr->obj_ptr, "bad register number", -1);
1540 return TCL_ERROR;
1541 }
1542 }
1543
1544 return TCL_OK;
1545 }
1546
1547 /* This implements the TCL command `gdb_regnames', which returns a list of
1548 all of the register names. */
1549
1550 static int
1551 gdb_regnames (clientData, interp, objc, objv)
1552 ClientData clientData;
1553 Tcl_Interp *interp;
1554 int objc;
1555 Tcl_Obj *CONST objv[];
1556 {
1557 objc--;
1558 objv++;
1559
1560 return map_arg_registers (objc, objv, get_register_name, NULL);
1561 }
1562
1563 static void
1564 get_register_name (regnum, argp)
1565 int regnum;
1566 void *argp; /* Ignored */
1567 {
1568 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
1569 Tcl_NewStringObj (reg_names[regnum], -1));
1570 }
1571
1572 /* This implements the tcl command gdb_fetch_registers
1573 * Pass it a list of register names, and it will
1574 * return their values as a list.
1575 *
1576 * Tcl Arguments:
1577 * format: The format string for printing the values
1578 * args: the registers to look for
1579 * Tcl Result:
1580 * A list of their values.
1581 */
1582
1583 static int
1584 gdb_fetch_registers (clientData, interp, objc, objv)
1585 ClientData clientData;
1586 Tcl_Interp *interp;
1587 int objc;
1588 Tcl_Obj *CONST objv[];
1589 {
1590 int format, result;
1591
1592 if (objc < 2)
1593 {
1594 Tcl_SetStringObj (result_ptr->obj_ptr,
1595 "wrong # args, should be gdb_fetch_registers format ?register1 register2 ...?", -1);
1596 }
1597 objc -= 2;
1598 objv++;
1599 format = *(Tcl_GetStringFromObj(objv[0], NULL));
1600 objv++;
1601
1602
1603 result_ptr->flags |= GDBTK_MAKES_LIST; /* Output the results as a list */
1604 result = map_arg_registers (objc, objv, get_register, (void *) format);
1605 result_ptr->flags &= ~GDBTK_MAKES_LIST;
1606
1607 return result;
1608 }
1609
1610 static void
1611 get_register (regnum, fp)
1612 int regnum;
1613 void *fp;
1614 {
1615 char raw_buffer[MAX_REGISTER_RAW_SIZE];
1616 char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
1617 int format = (int)fp;
1618
1619 if (format == 'N')
1620 format = 0;
1621
1622 if (read_relative_register_raw_bytes (regnum, raw_buffer))
1623 {
1624 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
1625 Tcl_NewStringObj ("Optimized out", -1));
1626 return;
1627 }
1628
1629 /* Convert raw data to virtual format if necessary. */
1630
1631 if (REGISTER_CONVERTIBLE (regnum))
1632 {
1633 REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
1634 raw_buffer, virtual_buffer);
1635 }
1636 else
1637 memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
1638
1639 if (format == 'r')
1640 {
1641 int j;
1642 printf_filtered ("0x");
1643 for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++)
1644 {
1645 register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
1646 : REGISTER_RAW_SIZE (regnum) - 1 - j;
1647 printf_filtered ("%02x", (unsigned char)raw_buffer[idx]);
1648 }
1649 }
1650 else
1651 val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
1652 gdb_stdout, format, 1, 0, Val_pretty_default);
1653
1654 }
1655
1656 /* This implements the tcl command get_pc_reg
1657 * It returns the value of the PC register
1658 *
1659 * Tcl Arguments:
1660 * None
1661 * Tcl Result:
1662 * The value of the pc register.
1663 */
1664
1665 static int
1666 get_pc_register (clientData, interp, objc, objv)
1667 ClientData clientData;
1668 Tcl_Interp *interp;
1669 int objc;
1670 Tcl_Obj *CONST objv[];
1671 {
1672 char buff[64];
1673
1674 sprintf (buff, "0x%llx",(long long) read_register (PC_REGNUM));
1675 Tcl_SetStringObj(result_ptr->obj_ptr, buff, -1);
1676 return TCL_OK;
1677 }
1678
1679 /* This implements the tcl command "gdb_changed_register_list"
1680 * It takes a list of registers, and returns a list of
1681 * the registers on that list that have changed since the last
1682 * time the proc was called.
1683 *
1684 * Tcl Arguments:
1685 * A list of registers.
1686 * Tcl Result:
1687 * A list of changed registers.
1688 */
1689
1690 static int
1691 gdb_changed_register_list (clientData, interp, objc, objv)
1692 ClientData clientData;
1693 Tcl_Interp *interp;
1694 int objc;
1695 Tcl_Obj *CONST objv[];
1696 {
1697 objc--;
1698 objv++;
1699
1700 return map_arg_registers (objc, objv, register_changed_p, NULL);
1701 }
1702
1703 static void
1704 register_changed_p (regnum, argp)
1705 int regnum;
1706 void *argp; /* Ignored */
1707 {
1708 char raw_buffer[MAX_REGISTER_RAW_SIZE];
1709
1710 if (read_relative_register_raw_bytes (regnum, raw_buffer))
1711 return;
1712
1713 if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
1714 REGISTER_RAW_SIZE (regnum)) == 0)
1715 return;
1716
1717 /* Found a changed register. Save new value and return its number. */
1718
1719 memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
1720 REGISTER_RAW_SIZE (regnum));
1721
1722 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj(regnum));
1723 }
1724 \f
1725 /*
1726 * This section contains the commands that deal with tracepoints:
1727 */
1728
1729 /* return a list of all tracepoint numbers in interpreter */
1730 static int
1731 gdb_get_tracepoint_list (clientData, interp, objc, objv)
1732 ClientData clientData;
1733 Tcl_Interp *interp;
1734 int objc;
1735 Tcl_Obj *CONST objv[];
1736 {
1737 struct tracepoint *tp;
1738
1739 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
1740
1741 ALL_TRACEPOINTS (tp)
1742 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (tp->number));
1743
1744 return TCL_OK;
1745 }
1746
1747 /* returns -1 if not found, tracepoint # if found */
1748 int
1749 tracepoint_exists (char * args)
1750 {
1751 struct tracepoint *tp;
1752 char **canonical;
1753 struct symtabs_and_lines sals;
1754 char *file = NULL;
1755 int result = -1;
1756
1757 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1758 if (sals.nelts == 1)
1759 {
1760 resolve_sal_pc (&sals.sals[0]);
1761 file = xmalloc (strlen (sals.sals[0].symtab->dirname)
1762 + strlen (sals.sals[0].symtab->filename) + 1);
1763 if (file != NULL)
1764 {
1765 strcpy (file, sals.sals[0].symtab->dirname);
1766 strcat (file, sals.sals[0].symtab->filename);
1767
1768 ALL_TRACEPOINTS (tp)
1769 {
1770 if (tp->address == sals.sals[0].pc)
1771 result = tp->number;
1772 #if 0
1773 /* Why is this here? This messes up assembly traces */
1774 else if (tp->source_file != NULL
1775 && strcmp (tp->source_file, file) == 0
1776 && sals.sals[0].line == tp->line_number)
1777 result = tp->number;
1778 #endif
1779 }
1780 }
1781 }
1782 if (file != NULL)
1783 free (file);
1784 return result;
1785 }
1786
1787 static int
1788 gdb_tracepoint_exists_command (clientData, interp, objc, objv)
1789 ClientData clientData;
1790 Tcl_Interp *interp;
1791 int objc;
1792 Tcl_Obj *CONST objv[];
1793 {
1794 char * args;
1795
1796 if (objc != 2)
1797 {
1798 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "wrong # of args: should be \"",
1799 Tcl_GetStringFromObj (objv[0], NULL),
1800 " function:line|function|line|*addr\"", NULL);
1801 return TCL_ERROR;
1802 }
1803
1804 args = Tcl_GetStringFromObj (objv[1], NULL);
1805
1806 Tcl_SetIntObj (result_ptr->obj_ptr, tracepoint_exists (args));
1807 return TCL_OK;
1808 }
1809
1810 static int
1811 gdb_get_tracepoint_info (clientData, interp, objc, objv)
1812 ClientData clientData;
1813 Tcl_Interp *interp;
1814 int objc;
1815 Tcl_Obj *CONST objv[];
1816 {
1817 struct symtab_and_line sal;
1818 int tpnum;
1819 struct tracepoint *tp;
1820 struct action_line *al;
1821 Tcl_Obj *action_list;
1822 char *filename, *funcname;
1823 char tmp[19];
1824
1825 if (objc != 2)
1826 {
1827 Tcl_SetStringObj (result_ptr->obj_ptr, "wrong # args", -1);
1828 return TCL_ERROR;
1829 }
1830
1831 if (Tcl_GetIntFromObj (NULL, objv[1], &tpnum) != TCL_OK)
1832 {
1833 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
1834 return TCL_ERROR;
1835 }
1836
1837 ALL_TRACEPOINTS (tp)
1838 if (tp->number == tpnum)
1839 break;
1840
1841 if (tp == NULL)
1842 {
1843 Tcl_SetStringObj (result_ptr->obj_ptr, "Tracepoint #%d does not exist", -1);
1844 return TCL_ERROR;
1845 }
1846
1847 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
1848 sal = find_pc_line (tp->address, 0);
1849 filename = symtab_to_filename (sal.symtab);
1850 if (filename == NULL)
1851 filename = "N/A";
1852 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
1853 Tcl_NewStringObj (filename, -1));
1854 find_pc_partial_function (tp->address, &funcname, NULL, NULL);
1855 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewStringObj (funcname, -1));
1856 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (sal.line));
1857 sprintf (tmp, "0x%lx", tp->address);
1858 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewStringObj (tmp, -1));
1859 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (tp->enabled));
1860 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (tp->pass_count));
1861 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (tp->step_count));
1862 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (tp->thread));
1863 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewIntObj (tp->hit_count));
1864
1865 /* Append a list of actions */
1866 action_list = Tcl_NewObj ();
1867 for (al = tp->actions; al != NULL; al = al->next)
1868 {
1869 Tcl_ListObjAppendElement (interp, action_list,
1870 Tcl_NewStringObj (al->action, -1));
1871 }
1872 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, action_list);
1873
1874 return TCL_OK;
1875 }
1876
1877
1878 static int
1879 gdb_trace_status (clientData, interp, objc, objv)
1880 ClientData clientData;
1881 Tcl_Interp *interp;
1882 int objc;
1883 Tcl_Obj *CONST objv[];
1884 {
1885 int result = 0;
1886
1887 if (trace_running_p)
1888 result = 1;
1889
1890 Tcl_SetIntObj (result_ptr->obj_ptr, result);
1891 return TCL_OK;
1892 }
1893
1894
1895
1896 static int
1897 gdb_get_trace_frame_num (clientData, interp, objc, objv)
1898 ClientData clientData;
1899 Tcl_Interp *interp;
1900 int objc;
1901 Tcl_Obj *CONST objv[];
1902 {
1903 if (objc != 1)
1904 {
1905 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "wrong # of args: should be \"",
1906 Tcl_GetStringFromObj (objv[0], NULL),
1907 " linespec\"", NULL);
1908 return TCL_ERROR;
1909 }
1910
1911 Tcl_SetIntObj (result_ptr->obj_ptr, get_traceframe_number ());
1912 return TCL_OK;
1913
1914 }
1915
1916 /* This implements the tcl command gdb_actions
1917 * It sets actions for a given tracepoint.
1918 *
1919 * Tcl Arguments:
1920 * number: the tracepoint in question
1921 * actions: the actions to add to this tracepoint
1922 * Tcl Result:
1923 * None.
1924 */
1925
1926 static int
1927 gdb_actions_command (clientData, interp, objc, objv)
1928 ClientData clientData;
1929 Tcl_Interp *interp;
1930 int objc;
1931 Tcl_Obj *CONST objv[];
1932 {
1933 struct tracepoint *tp;
1934 Tcl_Obj **actions;
1935 int nactions, i, len;
1936 char *number, *args, *action;
1937 long step_count;
1938 struct action_line *next = NULL, *temp;
1939 enum actionline_type linetype;
1940
1941 if (objc != 3)
1942 {
1943 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "wrong # args: should be: \"",
1944 Tcl_GetStringFromObj (objv[0], NULL),
1945 " number actions\"", NULL);
1946 return TCL_ERROR;
1947 }
1948
1949 args = number = Tcl_GetStringFromObj (objv[1], NULL);
1950 tp = get_tracepoint_by_number (&args);
1951 if (tp == NULL)
1952 {
1953 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "Tracepoint \"", number, "\" does not exist", NULL);
1954 return TCL_ERROR;
1955 }
1956
1957 /* Free any existing actions */
1958 if (tp->actions != NULL)
1959 free_actions (tp);
1960
1961 step_count = 0;
1962
1963 Tcl_ListObjGetElements (interp, objv[2], &nactions, &actions);
1964
1965 /* Add the actions to the tracepoint */
1966 for (i = 0; i < nactions; i++)
1967 {
1968 temp = xmalloc (sizeof (struct action_line));
1969 temp->next = NULL;
1970 action = Tcl_GetStringFromObj (actions[i], &len);
1971 temp->action = savestring (action, len);
1972
1973 linetype = validate_actionline (&(temp->action), tp);
1974
1975 if (linetype == BADLINE)
1976 {
1977 free (temp);
1978 continue;
1979 }
1980
1981 if (next == NULL)
1982 {
1983 tp->actions = temp;
1984 next = temp;
1985 }
1986 else
1987 {
1988 next->next = temp;
1989 next = temp;
1990 }
1991 }
1992
1993 return TCL_OK;
1994 }
1995 \f
1996 /*
1997 * This section has commands that handle source disassembly.
1998 */
1999
2000 /* This implements the tcl command gdb_disassemble
2001 *
2002 * Arguments:
2003 * source_with_assm - must be "source" or "nosource"
2004 * low_address - the address from which to start disassembly
2005 * ?hi_address? - the address to which to disassemble, defaults
2006 * to the end of the function containing low_address.
2007 * Tcl Result:
2008 * The disassembled code is passed to fputs_unfiltered, so it
2009 * either goes to the console if result_ptr->obj_ptr is NULL or to
2010 * the Tcl result.
2011 */
2012
2013 static int
2014 gdb_disassemble (clientData, interp, objc, objv)
2015 ClientData clientData;
2016 Tcl_Interp *interp;
2017 int objc;
2018 Tcl_Obj *CONST objv[];
2019 {
2020 CORE_ADDR pc, low, high;
2021 int mixed_source_and_assembly;
2022 static disassemble_info di;
2023 static int di_initialized;
2024 char *arg_ptr;
2025
2026 if (objc != 3 && objc != 4)
2027 error ("wrong # args");
2028
2029 if (! di_initialized)
2030 {
2031 INIT_DISASSEMBLE_INFO_NO_ARCH (di, gdb_stdout,
2032 (fprintf_ftype) fprintf_unfiltered);
2033 di.flavour = bfd_target_unknown_flavour;
2034 di.memory_error_func = dis_asm_memory_error;
2035 di.print_address_func = dis_asm_print_address;
2036 di_initialized = 1;
2037 }
2038
2039 di.mach = tm_print_insn_info.mach;
2040 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
2041 di.endian = BFD_ENDIAN_BIG;
2042 else
2043 di.endian = BFD_ENDIAN_LITTLE;
2044
2045 arg_ptr = Tcl_GetStringFromObj (objv[1], NULL);
2046 if (*arg_ptr == 's' && strcmp (arg_ptr, "source") == 0)
2047 mixed_source_and_assembly = 1;
2048 else if (*arg_ptr == 'n' && strcmp (arg_ptr, "nosource") == 0)
2049 mixed_source_and_assembly = 0;
2050 else
2051 error ("First arg must be 'source' or 'nosource'");
2052
2053 low = parse_and_eval_address (Tcl_GetStringFromObj (objv[2], NULL));
2054
2055 if (objc == 3)
2056 {
2057 if (find_pc_partial_function (low, NULL, &low, &high) == 0)
2058 error ("No function contains specified address");
2059 }
2060 else
2061 high = parse_and_eval_address (Tcl_GetStringFromObj (objv[3], NULL));
2062
2063 /* If disassemble_from_exec == -1, then we use the following heuristic to
2064 determine whether or not to do disassembly from target memory or from the
2065 exec file:
2066
2067 If we're debugging a local process, read target memory, instead of the
2068 exec file. This makes disassembly of functions in shared libs work
2069 correctly.
2070
2071 Else, we're debugging a remote process, and should disassemble from the
2072 exec file for speed. However, this is no good if the target modifies its
2073 code (for relocation, or whatever).
2074 */
2075
2076 if (disassemble_from_exec == -1)
2077 {
2078 if (strcmp (target_shortname, "child") == 0
2079 || strcmp (target_shortname, "procfs") == 0
2080 || strcmp (target_shortname, "vxprocess") == 0)
2081 disassemble_from_exec = 0; /* It's a child process, read inferior mem */
2082 else
2083 disassemble_from_exec = 1; /* It's remote, read the exec file */
2084 }
2085
2086 if (disassemble_from_exec)
2087 di.read_memory_func = gdbtk_dis_asm_read_memory;
2088 else
2089 di.read_memory_func = dis_asm_read_memory;
2090
2091 /* If just doing straight assembly, all we need to do is disassemble
2092 everything between low and high. If doing mixed source/assembly, we've
2093 got a totally different path to follow. */
2094
2095 if (mixed_source_and_assembly)
2096 { /* Come here for mixed source/assembly */
2097 /* The idea here is to present a source-O-centric view of a function to
2098 the user. This means that things are presented in source order, with
2099 (possibly) out of order assembly immediately following. */
2100 struct symtab *symtab;
2101 struct linetable_entry *le;
2102 int nlines;
2103 int newlines;
2104 struct my_line_entry *mle;
2105 struct symtab_and_line sal;
2106 int i;
2107 int out_of_order;
2108 int next_line;
2109
2110 symtab = find_pc_symtab (low); /* Assume symtab is valid for whole PC range */
2111
2112 if (!symtab)
2113 goto assembly_only;
2114
2115 /* First, convert the linetable to a bunch of my_line_entry's. */
2116
2117 le = symtab->linetable->item;
2118 nlines = symtab->linetable->nitems;
2119
2120 if (nlines <= 0)
2121 goto assembly_only;
2122
2123 mle = (struct my_line_entry *) alloca (nlines * sizeof (struct my_line_entry));
2124
2125 out_of_order = 0;
2126
2127 /* Copy linetable entries for this function into our data structure, creating
2128 end_pc's and setting out_of_order as appropriate. */
2129
2130 /* First, skip all the preceding functions. */
2131
2132 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
2133
2134 /* Now, copy all entries before the end of this function. */
2135
2136 newlines = 0;
2137 for (; i < nlines - 1 && le[i].pc < high; i++)
2138 {
2139 if (le[i].line == le[i + 1].line
2140 && le[i].pc == le[i + 1].pc)
2141 continue; /* Ignore duplicates */
2142
2143 mle[newlines].line = le[i].line;
2144 if (le[i].line > le[i + 1].line)
2145 out_of_order = 1;
2146 mle[newlines].start_pc = le[i].pc;
2147 mle[newlines].end_pc = le[i + 1].pc;
2148 newlines++;
2149 }
2150
2151 /* If we're on the last line, and it's part of the function, then we need to
2152 get the end pc in a special way. */
2153
2154 if (i == nlines - 1
2155 && le[i].pc < high)
2156 {
2157 mle[newlines].line = le[i].line;
2158 mle[newlines].start_pc = le[i].pc;
2159 sal = find_pc_line (le[i].pc, 0);
2160 mle[newlines].end_pc = sal.end;
2161 newlines++;
2162 }
2163
2164 /* Now, sort mle by line #s (and, then by addresses within lines). */
2165
2166 if (out_of_order)
2167 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
2168
2169 /* Now, for each line entry, emit the specified lines (unless they have been
2170 emitted before), followed by the assembly code for that line. */
2171
2172 next_line = 0; /* Force out first line */
2173 for (i = 0; i < newlines; i++)
2174 {
2175 /* Print out everything from next_line to the current line. */
2176
2177 if (mle[i].line >= next_line)
2178 {
2179 if (next_line != 0)
2180 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
2181 else
2182 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
2183
2184 next_line = mle[i].line + 1;
2185 }
2186
2187 for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
2188 {
2189 QUIT;
2190 fputs_unfiltered (" ", gdb_stdout);
2191 print_address (pc, gdb_stdout);
2192 fputs_unfiltered (":\t ", gdb_stdout);
2193 pc += (*tm_print_insn) (pc, &di);
2194 fputs_unfiltered ("\n", gdb_stdout);
2195 }
2196 }
2197 }
2198 else
2199 {
2200 assembly_only:
2201 for (pc = low; pc < high; )
2202 {
2203 QUIT;
2204 fputs_unfiltered (" ", gdb_stdout);
2205 print_address (pc, gdb_stdout);
2206 fputs_unfiltered (":\t ", gdb_stdout);
2207 pc += (*tm_print_insn) (pc, &di);
2208 fputs_unfiltered ("\n", gdb_stdout);
2209 }
2210 }
2211
2212 gdb_flush (gdb_stdout);
2213
2214 return TCL_OK;
2215 }
2216
2217 /* This is the memory_read_func for gdb_disassemble when we are
2218 disassembling from the exec file. */
2219
2220 static int
2221 gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
2222 bfd_vma memaddr;
2223 bfd_byte *myaddr;
2224 int len;
2225 disassemble_info *info;
2226 {
2227 extern struct target_ops exec_ops;
2228 int res;
2229
2230 errno = 0;
2231 res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
2232
2233 if (res == len)
2234 return 0;
2235 else
2236 if (errno == 0)
2237 return EIO;
2238 else
2239 return errno;
2240 }
2241
2242 /* This will be passed to qsort to sort the results of the disassembly */
2243
2244 static int
2245 compare_lines (mle1p, mle2p)
2246 const PTR mle1p;
2247 const PTR mle2p;
2248 {
2249 struct my_line_entry *mle1, *mle2;
2250 int val;
2251
2252 mle1 = (struct my_line_entry *) mle1p;
2253 mle2 = (struct my_line_entry *) mle2p;
2254
2255 val = mle1->line - mle2->line;
2256
2257 if (val != 0)
2258 return val;
2259
2260 return mle1->start_pc - mle2->start_pc;
2261 }
2262
2263 /* This implements the TCL command `gdb_loc',
2264 *
2265 * Arguments:
2266 * ?symbol? The symbol or address to locate - defaults to pc
2267 * Tcl Return:
2268 * a list consisting of the following:
2269 * basename, function name, filename, line number, address, current pc
2270 */
2271
2272 static int
2273 gdb_loc (clientData, interp, objc, objv)
2274 ClientData clientData;
2275 Tcl_Interp *interp;
2276 int objc;
2277 Tcl_Obj *CONST objv[];
2278 {
2279 char *filename;
2280 struct symtab_and_line sal;
2281 char *funcname, *fname;
2282 CORE_ADDR pc;
2283
2284 if (!have_full_symbols () && !have_partial_symbols ())
2285 {
2286 Tcl_SetStringObj (result_ptr->obj_ptr, "No symbol table is loaded", -1);
2287 return TCL_ERROR;
2288 }
2289
2290 if (objc == 1)
2291 {
2292 if (selected_frame && (selected_frame->pc != stop_pc))
2293 {
2294 /* Note - this next line is not correct on all architectures. */
2295 /* For a graphical debugger we really want to highlight the */
2296 /* assembly line that called the next function on the stack. */
2297 /* Many architectures have the next instruction saved as the */
2298 /* pc on the stack, so what happens is the next instruction is hughlighted. */
2299 /* FIXME */
2300 pc = selected_frame->pc;
2301 sal = find_pc_line (selected_frame->pc,
2302 selected_frame->next != NULL
2303 && !selected_frame->next->signal_handler_caller
2304 && !frame_in_dummy (selected_frame->next));
2305 }
2306 else
2307 {
2308 pc = stop_pc;
2309 sal = find_pc_line (stop_pc, 0);
2310 }
2311 }
2312 else if (objc == 2)
2313 {
2314 struct symtabs_and_lines sals;
2315 int nelts;
2316
2317 sals = decode_line_spec (Tcl_GetStringFromObj (objv[1], NULL), 1);
2318
2319 nelts = sals.nelts;
2320 sal = sals.sals[0];
2321 free (sals.sals);
2322
2323 if (sals.nelts != 1)
2324 {
2325 Tcl_SetStringObj (result_ptr->obj_ptr, "Ambiguous line spec", -1);
2326 return TCL_ERROR;
2327 }
2328 pc = sal.pc;
2329 }
2330 else
2331 {
2332 Tcl_SetStringObj (result_ptr->obj_ptr, "wrong # args", -1);
2333 return TCL_ERROR;
2334 }
2335
2336 if (sal.symtab)
2337 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2338 Tcl_NewStringObj (sal.symtab->filename, -1));
2339 else
2340 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewStringObj ("", 0));
2341
2342 find_pc_partial_function (pc, &funcname, NULL, NULL);
2343 fname = cplus_demangle (funcname, 0);
2344 if (fname)
2345 {
2346 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2347 Tcl_NewStringObj (fname, -1));
2348 free (fname);
2349 }
2350 else
2351 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2352 Tcl_NewStringObj (funcname, -1));
2353
2354 filename = symtab_to_filename (sal.symtab);
2355 if (filename == NULL)
2356 filename = "";
2357
2358 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2359 Tcl_NewStringObj (filename, -1));
2360 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj(sal.line)); /* line number */
2361 sprintf_append_element_to_obj (result_ptr->obj_ptr, "0x%s", paddr_nz(pc)); /* PC in current frame */
2362 sprintf_append_element_to_obj (result_ptr->obj_ptr, "0x%s", paddr_nz(stop_pc)); /* Real PC */
2363 return TCL_OK;
2364 }
2365
2366 /* This implements the Tcl command 'gdb_get_mem', which
2367 * dumps a block of memory
2368 * Arguments:
2369 * gdb_get_mem addr form size num aschar
2370 *
2371 * addr: address of data to dump
2372 * form: a char indicating format
2373 * size: size of each element; 1,2,4, or 8 bytes
2374 * num: the number of bytes to read
2375 * acshar: an optional ascii character to use in ASCII dump
2376 *
2377 * Return:
2378 * a list of elements followed by an optional ASCII dump
2379 */
2380
2381 static int
2382 gdb_get_mem (clientData, interp, objc, objv)
2383 ClientData clientData;
2384 Tcl_Interp *interp;
2385 int objc;
2386 Tcl_Obj *CONST objv[];
2387 {
2388 int size, asize, i, j, bc;
2389 CORE_ADDR addr;
2390 int nbytes, rnum, bpr;
2391 long tmp;
2392 char format, c, buff[128], aschar, *mbuf, *mptr, *cptr, *bptr;
2393 struct type *val_type;
2394
2395 if (objc < 6 || objc > 7)
2396 {
2397 Tcl_SetStringObj (result_ptr->obj_ptr,
2398 "addr format size bytes bytes_per_row ?ascii_char?", -1);
2399 return TCL_ERROR;
2400 }
2401
2402 if (Tcl_GetIntFromObj (interp, objv[3], &size) != TCL_OK)
2403 {
2404 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
2405 return TCL_ERROR;
2406 }
2407 else if (size <= 0)
2408 {
2409 Tcl_SetStringObj (result_ptr->obj_ptr, "Invalid size, must be > 0", -1);
2410 return TCL_ERROR;
2411 }
2412
2413 if (Tcl_GetIntFromObj (interp, objv[4], &nbytes) != TCL_OK)
2414 {
2415 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
2416 return TCL_ERROR;
2417 }
2418 else if (size <= 0)
2419 {
2420 Tcl_SetStringObj (result_ptr->obj_ptr, "Invalid number of bytes, must be > 0",
2421 -1);
2422 return TCL_ERROR;
2423 }
2424
2425 if (Tcl_GetIntFromObj (interp, objv[5], &bpr) != TCL_OK)
2426 {
2427 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
2428 return TCL_ERROR;
2429 }
2430 else if (size <= 0)
2431 {
2432 Tcl_SetStringObj (result_ptr->obj_ptr, "Invalid bytes per row, must be > 0", -1);
2433 return TCL_ERROR;
2434 }
2435
2436 if (Tcl_GetLongFromObj (interp, objv[1], &tmp) != TCL_OK)
2437 return TCL_OK;
2438
2439 addr = (CORE_ADDR) tmp;
2440
2441 format = *(Tcl_GetStringFromObj (objv[2], NULL));
2442 mbuf = (char *)malloc (nbytes+32);
2443 if (!mbuf)
2444 {
2445 Tcl_SetStringObj (result_ptr->obj_ptr, "Out of memory.", -1);
2446 return TCL_ERROR;
2447 }
2448
2449 memset (mbuf, 0, nbytes+32);
2450 mptr = cptr = mbuf;
2451
2452 rnum = target_read_memory_partial (addr, mbuf, nbytes, NULL);
2453
2454 if (objc == 7)
2455 aschar = *(Tcl_GetStringFromObj(objv[6], NULL));
2456 else
2457 aschar = 0;
2458
2459 switch (size) {
2460 case 1:
2461 val_type = builtin_type_char;
2462 asize = 'b';
2463 break;
2464 case 2:
2465 val_type = builtin_type_short;
2466 asize = 'h';
2467 break;
2468 case 4:
2469 val_type = builtin_type_int;
2470 asize = 'w';
2471 break;
2472 case 8:
2473 val_type = builtin_type_long_long;
2474 asize = 'g';
2475 break;
2476 default:
2477 val_type = builtin_type_char;
2478 asize = 'b';
2479 }
2480
2481 bc = 0; /* count of bytes in a row */
2482 buff[0] = '"'; /* buffer for ascii dump */
2483 bptr = &buff[1]; /* pointer for ascii dump */
2484
2485 result_ptr->flags |= GDBTK_MAKES_LIST; /* Build up the result as a list... */
2486
2487 for (i=0; i < nbytes; i+= size)
2488 {
2489 if ( i >= rnum)
2490 {
2491 fputs_unfiltered ("N/A ", gdb_stdout);
2492 if (aschar)
2493 for ( j = 0; j < size; j++)
2494 *bptr++ = 'X';
2495 }
2496 else
2497 {
2498 print_scalar_formatted (mptr, val_type, format, asize, gdb_stdout);
2499
2500 if (aschar)
2501 {
2502 for ( j = 0; j < size; j++)
2503 {
2504 c = *cptr++;
2505 if (c < 32 || c > 126)
2506 c = aschar;
2507 if (c == '"')
2508 *bptr++ = '\\';
2509 *bptr++ = c;
2510 }
2511 }
2512 }
2513
2514 mptr += size;
2515 bc += size;
2516
2517 if (aschar && (bc >= bpr))
2518 {
2519 /* end of row. print it and reset variables */
2520 bc = 0;
2521 *bptr++ = '"';
2522 *bptr++ = ' ';
2523 *bptr = 0;
2524 fputs_unfiltered (buff, gdb_stdout);
2525 bptr = &buff[1];
2526 }
2527 }
2528
2529 result_ptr->flags &= ~GDBTK_MAKES_LIST;
2530
2531 free (mbuf);
2532 return TCL_OK;
2533 }
2534
2535 \f
2536
2537 /* This implements the tcl command "gdb_loadfile"
2538 * It loads a c source file into a text widget.
2539 *
2540 * Tcl Arguments:
2541 * widget: the name of the text widget to fill
2542 * filename: the name of the file to load
2543 * linenumbers: A boolean indicating whether or not to display line numbers.
2544 * Tcl Result:
2545 *
2546 */
2547
2548 /* In this routine, we will build up a "line table", i.e. a
2549 * table of bits showing which lines in the source file are executible.
2550 * LTABLE_SIZE is the number of bytes to allocate for the line table.
2551 *
2552 * Its size limits the maximum number of lines
2553 * in a file to 8 * LTABLE_SIZE. This memory is freed after
2554 * the file is loaded, so it is OK to make this very large.
2555 * Additional memory will be allocated if needed. */
2556 #define LTABLE_SIZE 20000
2557 static int
2558 gdb_loadfile (clientData, interp, objc, objv)
2559 ClientData clientData;
2560 Tcl_Interp *interp;
2561 int objc;
2562 Tcl_Obj *CONST objv[];
2563 {
2564 char *file, *widget;
2565 int linenumbers, ln, lnum, ltable_size;
2566 FILE *fp;
2567 char *ltable;
2568 struct symtab *symtab;
2569 struct linetable_entry *le;
2570 long mtime = 0;
2571 struct stat st;
2572 Tcl_DString text_cmd_1, text_cmd_2, *cur_cmd;
2573 char line[1024], line_num_buf[16];
2574 int prefix_len_1, prefix_len_2, cur_prefix_len, widget_len;
2575
2576
2577 if (objc != 4)
2578 {
2579 Tcl_WrongNumArgs(interp, 1, objv, "widget filename linenumbers");
2580 return TCL_ERROR;
2581 }
2582
2583 widget = Tcl_GetStringFromObj (objv[1], NULL);
2584 if ( Tk_NameToWindow (interp, widget, Tk_MainWindow (interp)) == NULL)
2585 {
2586 return TCL_ERROR;
2587 }
2588
2589 file = Tcl_GetStringFromObj (objv[2], NULL);
2590 Tcl_GetBooleanFromObj (interp, objv[3], &linenumbers);
2591
2592 symtab = full_lookup_symtab (file);
2593 if (!symtab)
2594 {
2595 Tcl_SetStringObj ( result_ptr->obj_ptr, "File not found in symtab", -1);
2596 fclose (fp);
2597 return TCL_ERROR;
2598 }
2599
2600 file = symtab_to_filename ( symtab );
2601 if ((fp = fopen ( file, "r" )) == NULL)
2602 {
2603 Tcl_SetStringObj ( result_ptr->obj_ptr, "Can't open file for reading", -1);
2604 return TCL_ERROR;
2605 }
2606
2607 if (stat (file, &st) < 0)
2608 {
2609 catch_errors (perror_with_name_wrapper, "gdbtk: get time stamp", "",
2610 RETURN_MASK_ALL);
2611 return TCL_ERROR;
2612 }
2613
2614 if (symtab && symtab->objfile && symtab->objfile->obfd)
2615 mtime = bfd_get_mtime(symtab->objfile->obfd);
2616 else if (exec_bfd)
2617 mtime = bfd_get_mtime(exec_bfd);
2618
2619 if (mtime && mtime < st.st_mtime)
2620 gdbtk_ignorable_warning("Source file is more recent than executable.\n");
2621
2622
2623 /* Source linenumbers don't appear to be in order, and a sort is */
2624 /* too slow so the fastest solution is just to allocate a huge */
2625 /* array and set the array entry for each linenumber */
2626
2627 ltable_size = LTABLE_SIZE;
2628 ltable = (char *)malloc (LTABLE_SIZE);
2629 if (ltable == NULL)
2630 {
2631 Tcl_SetStringObj ( result_ptr->obj_ptr, "Out of memory.", -1);
2632 fclose (fp);
2633 return TCL_ERROR;
2634 }
2635
2636 memset (ltable, 0, LTABLE_SIZE);
2637
2638 if (symtab->linetable && symtab->linetable->nitems)
2639 {
2640 le = symtab->linetable->item;
2641 for (ln = symtab->linetable->nitems ;ln > 0; ln--, le++)
2642 {
2643 lnum = le->line >> 3;
2644 if (lnum >= ltable_size)
2645 {
2646 char *new_ltable;
2647 new_ltable = (char *)realloc (ltable, ltable_size*2);
2648 memset (new_ltable + ltable_size, 0, ltable_size);
2649 ltable_size *= 2;
2650 if (new_ltable == NULL)
2651 {
2652 Tcl_SetStringObj ( result_ptr->obj_ptr, "Out of memory.", -1);
2653 free (ltable);
2654 fclose (fp);
2655 return TCL_ERROR;
2656 }
2657 ltable = new_ltable;
2658 }
2659 ltable[lnum] |= 1 << (le->line % 8);
2660 }
2661 }
2662
2663 Tcl_DStringInit(&text_cmd_1);
2664 Tcl_DStringInit(&text_cmd_2);
2665
2666 ln = 1;
2667
2668 widget_len = strlen (widget);
2669 line[0] = '\t';
2670
2671 Tcl_DStringAppend (&text_cmd_1, widget, widget_len);
2672 Tcl_DStringAppend (&text_cmd_2, widget, widget_len);
2673
2674 if (linenumbers)
2675 {
2676 Tcl_DStringAppend (&text_cmd_1, " insert end {-\t", -1);
2677 prefix_len_1 = Tcl_DStringLength(&text_cmd_1);
2678
2679 Tcl_DStringAppend (&text_cmd_2, " insert end { \t", -1);
2680 prefix_len_2 = Tcl_DStringLength(&text_cmd_2);
2681
2682 while (fgets (line + 1, 980, fp))
2683 {
2684 sprintf (line_num_buf, "%d", ln);
2685 if (ltable[ln >> 3] & (1 << (ln % 8)))
2686 {
2687 cur_cmd = &text_cmd_1;
2688 cur_prefix_len = prefix_len_1;
2689 Tcl_DStringAppend (cur_cmd, line_num_buf, -1);
2690 Tcl_DStringAppend (cur_cmd, "} break_tag", 11);
2691 }
2692 else
2693 {
2694 cur_cmd = &text_cmd_2;
2695 cur_prefix_len = prefix_len_2;
2696 Tcl_DStringAppend (cur_cmd, line_num_buf, -1);
2697 Tcl_DStringAppend (cur_cmd, "} \"\"", 4);
2698 }
2699
2700 Tcl_DStringAppendElement (cur_cmd, line);
2701 Tcl_DStringAppend (cur_cmd, " source_tag", 11);
2702
2703 Tcl_Eval(interp, Tcl_DStringValue(cur_cmd));
2704 Tcl_DStringSetLength(cur_cmd, cur_prefix_len);
2705 ln++;
2706 }
2707 }
2708 else
2709 {
2710 Tcl_DStringAppend (&text_cmd_1, " insert end {- } break_tag", -1);
2711 prefix_len_1 = Tcl_DStringLength(&text_cmd_1);
2712 Tcl_DStringAppend (&text_cmd_2, " insert end { } \"\"", -1);
2713 prefix_len_2 = Tcl_DStringLength(&text_cmd_2);
2714
2715 while (fgets (line + 1, 980, fp))
2716 {
2717 if (ltable[ln >> 3] & (1 << (ln % 8)))
2718 {
2719 cur_cmd = &text_cmd_1;
2720 cur_prefix_len = prefix_len_1;
2721 }
2722 else
2723 {
2724 cur_cmd = &text_cmd_2;
2725 cur_prefix_len = prefix_len_2;
2726 }
2727
2728 Tcl_DStringAppendElement (cur_cmd, line);
2729 Tcl_DStringAppend (cur_cmd, " source_tag", 11);
2730
2731 Tcl_Eval(interp, Tcl_DStringValue(cur_cmd));
2732 Tcl_DStringSetLength(cur_cmd, cur_prefix_len);
2733
2734 ln++;
2735 }
2736 }
2737
2738 Tcl_DStringFree (&text_cmd_1);
2739 Tcl_DStringFree (&text_cmd_2);
2740 free (ltable);
2741 fclose (fp);
2742 return TCL_OK;
2743 }
2744 \f
2745 /*
2746 * This section contains commands for manipulation of breakpoints.
2747 */
2748
2749
2750 /* set a breakpoint by source file and line number */
2751 /* flags are as follows: */
2752 /* least significant 2 bits are disposition, rest is */
2753 /* type (normally 0).
2754
2755 enum bptype {
2756 bp_breakpoint, Normal breakpoint
2757 bp_hardware_breakpoint, Hardware assisted breakpoint
2758 }
2759
2760 Disposition of breakpoint. Ie: what to do after hitting it.
2761 enum bpdisp {
2762 del, Delete it
2763 del_at_next_stop, Delete at next stop, whether hit or not
2764 disable, Disable it
2765 donttouch Leave it alone
2766 };
2767 */
2768
2769 /* This implements the tcl command "gdb_set_bp"
2770 * It sets breakpoints, and runs the Tcl command
2771 * gdbtk_tcl_breakpoint create
2772 * to register the new breakpoint with the GUI.
2773 *
2774 * Tcl Arguments:
2775 * filename: the file in which to set the breakpoint
2776 * line: the line number for the breakpoint
2777 * type: the type of the breakpoint
2778 * Tcl Result:
2779 * The return value of the call to gdbtk_tcl_breakpoint.
2780 */
2781
2782 static int
2783 gdb_set_bp (clientData, interp, objc, objv)
2784 ClientData clientData;
2785 Tcl_Interp *interp;
2786 int objc;
2787 Tcl_Obj *CONST objv[];
2788
2789 {
2790 struct symtab_and_line sal;
2791 int line, flags, ret;
2792 struct breakpoint *b;
2793 char buf[64];
2794 Tcl_DString cmd;
2795
2796 if (objc != 4)
2797 {
2798 Tcl_WrongNumArgs(interp, 1, objv, "filename line type");
2799 return TCL_ERROR;
2800 }
2801
2802 sal.symtab = full_lookup_symtab (Tcl_GetStringFromObj( objv[1], NULL));
2803 if (sal.symtab == NULL)
2804 return TCL_ERROR;
2805
2806 if (Tcl_GetIntFromObj( interp, objv[2], &line) == TCL_ERROR)
2807 {
2808 result_ptr->flags = GDBTK_IN_TCL_RESULT;
2809 return TCL_ERROR;
2810 }
2811
2812 if (Tcl_GetIntFromObj( interp, objv[3], &flags) == TCL_ERROR)
2813 {
2814 result_ptr->flags = GDBTK_IN_TCL_RESULT;
2815 return TCL_ERROR;
2816 }
2817
2818 sal.line = line;
2819 if (!find_line_pc (sal.symtab, sal.line, &sal.pc))
2820 return TCL_ERROR;
2821
2822 sal.section = find_pc_overlay (sal.pc);
2823 b = set_raw_breakpoint (sal);
2824 set_breakpoint_count (breakpoint_count + 1);
2825 b->number = breakpoint_count;
2826 b->type = flags >> 2;
2827 b->disposition = flags & 3;
2828
2829 /* FIXME: this won't work for duplicate basenames! */
2830 sprintf (buf, "%s:%d", basename (Tcl_GetStringFromObj ( objv[1], NULL)), line);
2831 b->addr_string = strsave (buf);
2832
2833 /* now send notification command back to GUI */
2834
2835 Tcl_DStringInit (&cmd);
2836
2837 Tcl_DStringAppend (&cmd, "gdbtk_tcl_breakpoint create ", -1);
2838 sprintf (buf, "%d", b->number);
2839 Tcl_DStringAppendElement(&cmd, buf);
2840 sprintf (buf, "0x%lx", (long)sal.pc);
2841 Tcl_DStringAppendElement (&cmd, buf);
2842 Tcl_DStringAppendElement (&cmd, Tcl_GetStringFromObj (objv[2], NULL));
2843 Tcl_DStringAppendElement (&cmd, Tcl_GetStringFromObj (objv[1], NULL));
2844
2845 ret = Tcl_Eval (interp, Tcl_DStringValue (&cmd));
2846 Tcl_DStringFree (&cmd);
2847 return ret;
2848 }
2849
2850 /* This implements the tcl command gdb_get_breakpoint_info
2851 *
2852 *
2853 * Tcl Arguments:
2854 * breakpoint_number
2855 * Tcl Result:
2856 * A list with {file, function, line_number, address, type, enabled?,
2857 * disposition, ignore_count, {list_of_commands}, thread, hit_count}
2858 */
2859
2860 static int
2861 gdb_get_breakpoint_info (clientData, interp, objc, objv)
2862 ClientData clientData;
2863 Tcl_Interp *interp;
2864 int objc;
2865 Tcl_Obj *CONST objv[];
2866 {
2867 struct symtab_and_line sal;
2868 static char *bptypes[] = {"breakpoint", "hardware breakpoint", "until",
2869 "finish", "watchpoint", "hardware watchpoint",
2870 "read watchpoint", "access watchpoint",
2871 "longjmp", "longjmp resume", "step resume",
2872 "through sigtramp", "watchpoint scope",
2873 "call dummy" };
2874 static char *bpdisp[] = {"delete", "delstop", "disable", "donttouch"};
2875 struct command_line *cmd;
2876 int bpnum;
2877 struct breakpoint *b;
2878 extern struct breakpoint *breakpoint_chain;
2879 char *funcname, *fname, *filename;
2880 Tcl_Obj *new_obj;
2881
2882 if (objc != 2)
2883 {
2884 Tcl_SetStringObj (result_ptr->obj_ptr, "wrong number of args, should be \"breakpoint\"", -1);
2885 return TCL_ERROR;
2886 }
2887
2888 if ( Tcl_GetIntFromObj(NULL, objv[1], &bpnum) != TCL_OK)
2889 {
2890 result_ptr->flags = GDBTK_IN_TCL_RESULT;
2891 return TCL_ERROR;
2892 }
2893
2894 for (b = breakpoint_chain; b; b = b->next)
2895 if (b->number == bpnum)
2896 break;
2897
2898 if (!b || b->type != bp_breakpoint)
2899 {
2900 Tcl_SetStringObj (result_ptr->obj_ptr, "Breakpoint #%d does not exist", -1);
2901 return TCL_ERROR;
2902 }
2903
2904 sal = find_pc_line (b->address, 0);
2905
2906 filename = symtab_to_filename (sal.symtab);
2907 if (filename == NULL)
2908 filename = "";
2909
2910 Tcl_SetListObj (result_ptr->obj_ptr ,0 ,NULL);
2911 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2912 Tcl_NewStringObj (filename, -1));
2913
2914 find_pc_partial_function (b->address, &funcname, NULL, NULL);
2915 fname = cplus_demangle (funcname, 0);
2916 if (fname)
2917 {
2918 new_obj = Tcl_NewStringObj (fname, -1);
2919 free (fname);
2920 }
2921 else
2922 new_obj = Tcl_NewStringObj (funcname, -1);
2923
2924 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj);
2925
2926 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (b->line_number));
2927 sprintf_append_element_to_obj (result_ptr->obj_ptr, "0x%lx", b->address);
2928 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2929 Tcl_NewStringObj (bptypes[b->type], -1));
2930 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewBooleanObj(b->enable == enabled));
2931 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2932 Tcl_NewStringObj (bpdisp[b->disposition], -1));
2933 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (b->ignore_count));
2934
2935 new_obj = Tcl_NewObj();
2936 for (cmd = b->commands; cmd; cmd = cmd->next)
2937 Tcl_ListObjAppendElement (NULL, new_obj,
2938 Tcl_NewStringObj (cmd->line, -1));
2939 Tcl_ListObjAppendElement(NULL, result_ptr->obj_ptr, new_obj);
2940
2941 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
2942 Tcl_NewStringObj (b->cond_string, -1));
2943
2944 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (b->thread));
2945 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (b->hit_count));
2946
2947 return TCL_OK;
2948 }
2949
2950
2951 /* This implements the tcl command gdb_get_breakpoint_list
2952 * It builds up a list of the current breakpoints.
2953 *
2954 * Tcl Arguments:
2955 * None.
2956 * Tcl Result:
2957 * A list of breakpoint numbers.
2958 */
2959
2960 static int
2961 gdb_get_breakpoint_list (clientData, interp, objc, objv)
2962 ClientData clientData;
2963 Tcl_Interp *interp;
2964 int objc;
2965 Tcl_Obj *CONST objv[];
2966 {
2967 struct breakpoint *b;
2968 extern struct breakpoint *breakpoint_chain;
2969 Tcl_Obj *new_obj;
2970
2971 if (objc != 1)
2972 error ("wrong number of args, none are allowed");
2973
2974 for (b = breakpoint_chain; b; b = b->next)
2975 if (b->type == bp_breakpoint)
2976 {
2977 new_obj = Tcl_NewIntObj (b->number);
2978 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj);
2979 }
2980
2981 return TCL_OK;
2982 }
2983 \f
2984 /* The functions in this section deal with stacks and backtraces. */
2985
2986 /* This implements the tcl command gdb_stack.
2987 * It builds up a list of stack frames.
2988 *
2989 * Tcl Arguments:
2990 * start - starting stack frame
2991 * count - number of frames to inspect
2992 * Tcl Result:
2993 * A list of function names
2994 */
2995
2996 static int
2997 gdb_stack (clientData, interp, objc, objv) ClientData clientData;
2998 Tcl_Interp *interp;
2999 int objc;
3000 Tcl_Obj *CONST objv[];
3001 {
3002 int start, count;
3003
3004 if (objc < 3)
3005 {
3006 Tcl_WrongNumArgs (interp, 1, objv, "start count");
3007 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
3008 return TCL_ERROR;
3009 }
3010
3011 if (Tcl_GetIntFromObj (NULL, objv[1], &start))
3012 {
3013 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
3014 return TCL_ERROR;
3015 }
3016 if (Tcl_GetIntFromObj (NULL, objv[2], &count))
3017 {
3018 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
3019 return TCL_ERROR;
3020 }
3021
3022 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
3023
3024 if (target_has_stack)
3025 {
3026 struct frame_info *top;
3027 struct frame_info *fi;
3028
3029 /* Find the outermost frame */
3030 fi = get_current_frame ();
3031 while (fi != NULL)
3032 {
3033 top = fi;
3034 fi = get_prev_frame (fi);
3035 }
3036
3037 /* top now points to the top (outermost frame) of the
3038 stack, so point it to the requested start */
3039 start = -start;
3040 top = find_relative_frame (top, &start);
3041
3042 /* If start != 0, then we have asked to start outputting
3043 frames beyond the innermost stack frame */
3044 if (start == 0)
3045 {
3046 fi = top;
3047 while (fi && count--)
3048 {
3049 get_frame_name (interp, result_ptr->obj_ptr, fi);
3050 fi = get_next_frame (fi);
3051 }
3052 }
3053 }
3054
3055 return TCL_OK;
3056 }
3057
3058 /* A helper function for get_stack which adds information about
3059 * the stack frame FI to the caller's LIST.
3060 *
3061 * This is stolen from print_frame_info in stack.c.
3062 */
3063 static void
3064 get_frame_name (interp, list, fi)
3065 Tcl_Interp *interp;
3066 Tcl_Obj *list;
3067 struct frame_info *fi;
3068 {
3069 struct symtab_and_line sal;
3070 struct symbol *func = NULL;
3071 register char *funname = 0;
3072 enum language funlang = language_unknown;
3073 Tcl_Obj *objv[1];
3074
3075 if (frame_in_dummy (fi))
3076 {
3077 objv[0] = Tcl_NewStringObj ("<function called from gdb>\n", -1);
3078 Tcl_ListObjAppendElement (interp, list, objv[0]);
3079 return;
3080 }
3081 if (fi->signal_handler_caller)
3082 {
3083 objv[0] = Tcl_NewStringObj ("<signal handler called>\n", -1);
3084 Tcl_ListObjAppendElement (interp, list, objv[0]);
3085 return;
3086 }
3087
3088 sal =
3089 find_pc_line (fi->pc,
3090 fi->next != NULL
3091 && !fi->next->signal_handler_caller
3092 && !frame_in_dummy (fi->next));
3093
3094 func = find_pc_function (fi->pc);
3095 if (func)
3096 {
3097 struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
3098 if (msymbol != NULL
3099 && (SYMBOL_VALUE_ADDRESS (msymbol)
3100 > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
3101 {
3102 func = 0;
3103 funname = SYMBOL_NAME (msymbol);
3104 funlang = SYMBOL_LANGUAGE (msymbol);
3105 }
3106 else
3107 {
3108 funname = SYMBOL_NAME (func);
3109 funlang = SYMBOL_LANGUAGE (func);
3110 }
3111 }
3112 else
3113 {
3114 struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
3115 if (msymbol != NULL)
3116 {
3117 funname = SYMBOL_NAME (msymbol);
3118 funlang = SYMBOL_LANGUAGE (msymbol);
3119 }
3120 }
3121
3122 if (sal.symtab)
3123 {
3124 objv[0] = Tcl_NewStringObj (funname, -1);
3125 Tcl_ListObjAppendElement (interp, list, objv[0]);
3126 }
3127 else
3128 {
3129 #if 0
3130 /* we have no convenient way to deal with this yet... */
3131 if (fi->pc != sal.pc || !sal.symtab)
3132 {
3133 print_address_numeric (fi->pc, 1, gdb_stdout);
3134 printf_filtered (" in ");
3135 }
3136 printf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang,
3137 DMGL_ANSI);
3138 #endif
3139 objv[0] = Tcl_NewStringObj (funname != NULL ? funname : "??", -1);
3140 #ifdef PC_LOAD_SEGMENT
3141 /* If we couldn't print out function name but if can figure out what
3142 load segment this pc value is from, at least print out some info
3143 about its load segment. */
3144 if (!funname)
3145 {
3146 Tcl_AppendStringsToObj (objv[0], " from ", PC_LOAD_SEGMENT (fi->pc),
3147 (char *) NULL);
3148 }
3149 #endif
3150 #ifdef PC_SOLIB
3151 if (!funname)
3152 {
3153 char *lib = PC_SOLIB (fi->pc);
3154 if (lib)
3155 {
3156 Tcl_AppendStringsToObj (objv[0], " from ", lib, (char *) NULL);
3157 }
3158 }
3159 #endif
3160 Tcl_ListObjAppendElement (interp, list, objv[0]);
3161 }
3162 }
3163
3164 \f
3165 /*
3166 * This section contains a bunch of miscellaneous utility commands
3167 */
3168
3169 /* This implements the tcl command gdb_path_conv
3170 *
3171 * On Windows, it canonicalizes the pathname,
3172 * On Unix, it is a no op.
3173 *
3174 * Arguments:
3175 * path
3176 * Tcl Result:
3177 * The canonicalized path.
3178 */
3179
3180 static int
3181 gdb_path_conv (clientData, interp, objc, objv)
3182 ClientData clientData;
3183 Tcl_Interp *interp;
3184 int objc;
3185 Tcl_Obj *CONST objv[];
3186 {
3187 if (objc != 2)
3188 error ("wrong # args");
3189
3190 #ifdef WINNT
3191 {
3192 char pathname[256], *ptr;
3193
3194 cygwin32_conv_to_full_win32_path (Tcl_GetStringFromObj(objv[1], NULL), pathname);
3195 for (ptr = pathname; *ptr; ptr++)
3196 {
3197 if (*ptr == '\\')
3198 *ptr = '/';
3199 }
3200 Tcl_SetStringObj (result_ptr->obj_ptr, pathname, -1);
3201 }
3202 #else
3203 Tcl_SetStringObj (result_ptr->obj_ptr, Tcl_GetStringFromObj (objv[1], NULL), -1);
3204 #endif
3205
3206 return TCL_OK;
3207 }
3208 \f
3209 /*
3210 * This section has utility routines that are not Tcl commands.
3211 */
3212
3213 static int
3214 perror_with_name_wrapper (args)
3215 char * args;
3216 {
3217 perror_with_name (args);
3218 return 1;
3219 }
3220
3221 /* The lookup_symtab() in symtab.c doesn't work correctly */
3222 /* It will not work will full pathnames and if multiple */
3223 /* source files have the same basename, it will return */
3224 /* the first one instead of the correct one. This version */
3225 /* also always makes sure symtab->fullname is set. */
3226
3227 static struct symtab *
3228 full_lookup_symtab(file)
3229 char *file;
3230 {
3231 struct symtab *st;
3232 struct objfile *objfile;
3233 char *bfile, *fullname;
3234 struct partial_symtab *pt;
3235
3236 if (!file)
3237 return NULL;
3238
3239 /* first try a direct lookup */
3240 st = lookup_symtab (file);
3241 if (st)
3242 {
3243 if (!st->fullname)
3244 symtab_to_filename(st);
3245 return st;
3246 }
3247
3248 /* if the direct approach failed, try */
3249 /* looking up the basename and checking */
3250 /* all matches with the fullname */
3251 bfile = basename (file);
3252 ALL_SYMTABS (objfile, st)
3253 {
3254 if (!strcmp (bfile, basename(st->filename)))
3255 {
3256 if (!st->fullname)
3257 fullname = symtab_to_filename (st);
3258 else
3259 fullname = st->fullname;
3260
3261 if (!strcmp (file, fullname))
3262 return st;
3263 }
3264 }
3265
3266 /* still no luck? look at psymtabs */
3267 ALL_PSYMTABS (objfile, pt)
3268 {
3269 if (!strcmp (bfile, basename(pt->filename)))
3270 {
3271 st = PSYMTAB_TO_SYMTAB (pt);
3272 if (st)
3273 {
3274 fullname = symtab_to_filename (st);
3275 if (!strcmp (file, fullname))
3276 return st;
3277 }
3278 }
3279 }
3280 return NULL;
3281 }
This page took 0.134495 seconds and 5 git commands to generate.