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