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