OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [gdbtk/] [generic/] [gdbtk-stack.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Tcl/Tk command definitions for Insight - Stack.
2
   Copyright 2001 Free Software Foundation, Inc.
3
 
4
   This file is part of GDB.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
20
 
21
#include "defs.h"
22
#include "frame.h"
23
#include "value.h"
24
#include "target.h"
25
#include "breakpoint.h"
26
#include "linespec.h"
27
 
28
#include <tcl.h>
29
#include "gdbtk.h"
30
#include "gdbtk-cmds.h"
31
#include "gdbtk-wrapper.h"
32
 
33
static int gdb_block_vars (ClientData clientData,
34
                           Tcl_Interp * interp, int objc,
35
                           Tcl_Obj * CONST objv[]);
36
static int gdb_get_args_command (ClientData, Tcl_Interp *, int,
37
                                 Tcl_Obj * CONST objv[]);
38
static int gdb_get_blocks (ClientData clientData,
39
                           Tcl_Interp * interp, int objc,
40
                           Tcl_Obj * CONST objv[]);
41
static int gdb_get_locals_command (ClientData, Tcl_Interp *, int,
42
                                   Tcl_Obj * CONST objv[]);
43
static int gdb_get_vars_command (ClientData, Tcl_Interp *, int,
44
                                 Tcl_Obj * CONST objv[]);
45
static int gdb_selected_block (ClientData clientData,
46
                               Tcl_Interp * interp, int argc,
47
                               Tcl_Obj * CONST objv[]);
48
static int gdb_selected_frame (ClientData clientData,
49
                               Tcl_Interp * interp, int argc,
50
                               Tcl_Obj * CONST objv[]);
51
static int gdb_stack (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
52
static void get_frame_name (Tcl_Interp *interp, Tcl_Obj *list,
53
                            struct frame_info *fi);
54
 
55
int
56
Gdbtk_Stack_Init (Tcl_Interp *interp)
57
{
58
  Tcl_CreateObjCommand (interp, "gdb_block_variables", gdbtk_call_wrapper,
59
                        gdb_block_vars, NULL);
60
  Tcl_CreateObjCommand (interp, "gdb_get_blocks", gdbtk_call_wrapper,
61
                        gdb_get_blocks, NULL);
62
  Tcl_CreateObjCommand (interp, "gdb_get_args", gdbtk_call_wrapper,
63
                        gdb_get_args_command, NULL);
64
  Tcl_CreateObjCommand (interp, "gdb_get_locals", gdbtk_call_wrapper,
65
                        gdb_get_locals_command, NULL);
66
  Tcl_CreateObjCommand (interp, "gdb_selected_block", gdbtk_call_wrapper,
67
                        gdb_selected_block, NULL);
68
  Tcl_CreateObjCommand (interp, "gdb_selected_frame", gdbtk_call_wrapper,
69
                        gdb_selected_frame, NULL);
70
  Tcl_CreateObjCommand (interp, "gdb_stack", gdbtk_call_wrapper, gdb_stack, NULL);
71
 
72
  Tcl_LinkVar (interp, "gdb_selected_frame_level",
73
               (char *) &selected_frame_level,
74
               TCL_LINK_INT | TCL_LINK_READ_ONLY);
75
 
76
  return TCL_OK;
77
}
78
 
79
/* This implements the tcl command gdb_block_vars.
80
 *
81
 * Returns all variables valid in the specified block.
82
 *
83
 * Arguments:
84
 *    The start and end addresses which identify the block.
85
 * Tcl Result:
86
 *    All variables defined in the given block.
87
 */
88
static int
89
gdb_block_vars (clientData, interp, objc, objv)
90
     ClientData clientData;
91
     Tcl_Interp *interp;
92
     int objc;
93
     Tcl_Obj *CONST objv[];
94
{
95
  struct block *block;
96
  int nsyms, i;
97
  struct symbol *sym;
98
  CORE_ADDR start, end;
99
 
100
  if (objc < 3)
101
    {
102
      Tcl_WrongNumArgs (interp, 1, objv, "startAddr endAddr");
103
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
104
      return TCL_ERROR;
105
    }
106
 
107
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
108
  if (selected_frame == NULL)
109
    return TCL_OK;
110
 
111
  start = parse_and_eval_address (Tcl_GetStringFromObj (objv[1], NULL));
112
  end   = parse_and_eval_address (Tcl_GetStringFromObj (objv[2], NULL));
113
 
114
  block = get_frame_block (selected_frame);
115
 
116
  while (block != 0)
117
    {
118
      if (BLOCK_START (block) == start && BLOCK_END (block) == end)
119
        {
120
          nsyms = BLOCK_NSYMS (block);
121
          for (i = 0; i < nsyms; i++)
122
            {
123
              sym = BLOCK_SYM (block, i);
124
              switch (SYMBOL_CLASS (sym))
125
                {
126
                case LOC_ARG:             /* argument              */
127
                case LOC_REF_ARG:         /* reference arg         */
128
                case LOC_REGPARM:         /* register arg          */
129
                case LOC_REGPARM_ADDR:    /* indirect register arg */
130
                case LOC_LOCAL_ARG:       /* stack arg             */
131
                case LOC_BASEREG_ARG:     /* basereg arg           */
132
                case LOC_LOCAL:           /* stack local           */
133
                case LOC_BASEREG:         /* basereg local         */
134
                case LOC_STATIC:          /* static                */
135
                case LOC_REGISTER:        /* register              */
136
                  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
137
                                            Tcl_NewStringObj (SYMBOL_NAME (sym),
138
                                                              -1));
139
                  break;
140
 
141
                default:
142
                  break;
143
                }
144
            }
145
 
146
          return TCL_OK;
147
        }
148
      else if (BLOCK_FUNCTION (block))
149
        break;
150
      else
151
        block = BLOCK_SUPERBLOCK (block);
152
    }
153
 
154
  return TCL_OK;
155
}
156
 
157
/* This implements the tcl command gdb_get_blocks
158
 *
159
 * Returns the start and end addresses for all blocks in
160
 * the selected frame.
161
 *
162
 * Arguments:
163
 *    None
164
 * Tcl Result:
165
 *    A list of all valid blocks in the selected_frame.
166
 */
167
static int
168
gdb_get_blocks (clientData, interp, objc, objv)
169
     ClientData clientData;
170
     Tcl_Interp *interp;
171
     int objc;
172
     Tcl_Obj *CONST objv[];
173
{
174
  struct block *block;
175
  int nsyms, i, junk;
176
  struct symbol *sym;
177
  CORE_ADDR pc;
178
 
179
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
180
 
181
  if (selected_frame != NULL)
182
    {
183
      block = get_frame_block (selected_frame);
184
      pc = get_frame_pc (selected_frame);
185
      while (block != 0)
186
        {
187
          nsyms = BLOCK_NSYMS (block);
188
          junk = 0;
189
          for (i = 0; i < nsyms; i++)
190
            {
191
              sym = BLOCK_SYM (block, i);
192
              switch (SYMBOL_CLASS (sym))
193
                {
194
                default:
195
                case LOC_UNDEF:           /* catches errors        */
196
                case LOC_CONST:           /* constant              */
197
                case LOC_TYPEDEF:         /* local typedef         */
198
                case LOC_LABEL:           /* local label           */
199
                case LOC_BLOCK:           /* local function        */
200
                case LOC_CONST_BYTES:     /* loc. byte seq.        */
201
                case LOC_UNRESOLVED:      /* unresolved static     */
202
                case LOC_OPTIMIZED_OUT:   /* optimized out         */
203
                  junk = 1;
204
                  break;
205
 
206
                case LOC_ARG:             /* argument              */
207
                case LOC_REF_ARG:         /* reference arg         */
208
                case LOC_REGPARM:         /* register arg          */
209
                case LOC_REGPARM_ADDR:    /* indirect register arg */
210
                case LOC_LOCAL_ARG:       /* stack arg             */
211
                case LOC_BASEREG_ARG:     /* basereg arg           */
212
 
213
                case LOC_LOCAL:           /* stack local           */
214
                case LOC_BASEREG:         /* basereg local         */
215
                case LOC_STATIC:          /* static                */
216
                case LOC_REGISTER:        /* register              */
217
                  junk = 0;
218
                  break;
219
                }
220
            }
221
 
222
          /* If we found a block with locals in it, add it to the list.
223
             Note that the ranges of start and end address for blocks
224
             are exclusive, so double-check against the PC */
225
 
226
          if (!junk && pc < BLOCK_END (block))
227
            {
228
              char *addr;
229
 
230
              Tcl_Obj *elt = Tcl_NewListObj (0, NULL);
231
              xasprintf (&addr, "0x%s", paddr_nz (BLOCK_START (block)));
232
              Tcl_ListObjAppendElement (interp, elt,
233
                                        Tcl_NewStringObj (addr, -1));
234
              free(addr);
235
              xasprintf (&addr, "0x%s", paddr_nz (BLOCK_END (block)));
236
              Tcl_ListObjAppendElement (interp, elt,
237
                                        Tcl_NewStringObj (addr, -1));
238
              Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, elt);
239
              free(addr);
240
            }
241
 
242
          if (BLOCK_FUNCTION (block))
243
            break;
244
          else
245
            block = BLOCK_SUPERBLOCK (block);
246
        }
247
    }
248
 
249
  return TCL_OK;
250
}
251
 
252
/* gdb_get_args -
253
 * This and gdb_get_locals just call gdb_get_vars_command with the right
254
 * value of clientData.  We can't use the client data in the definition
255
 * of the command, because the call wrapper uses this instead...
256
 */
257
static int
258
gdb_get_args_command (clientData, interp, objc, objv)
259
     ClientData clientData;
260
     Tcl_Interp *interp;
261
     int objc;
262
     Tcl_Obj *CONST objv[];
263
{
264
  return gdb_get_vars_command ((ClientData) 1, interp, objc, objv);
265
}
266
 
267
 
268
static int
269
gdb_get_locals_command (clientData, interp, objc, objv)
270
     ClientData clientData;
271
     Tcl_Interp *interp;
272
     int objc;
273
     Tcl_Obj *CONST objv[];
274
{
275
  return gdb_get_vars_command ((ClientData) 0, interp, objc, objv);
276
}
277
 
278
/* This implements the tcl commands "gdb_get_locals" and "gdb_get_args"
279
 
280
 * This function sets the Tcl interpreter's result to a list of variable names
281
 * depending on clientData. If clientData is one, the result is a list of
282
 * arguments; zero returns a list of locals -- all relative to the block
283
 * specified as an argument to the command. Valid commands include
284
 * anything decode_line_1 can handle (like "main.c:2", "*0x02020202",
285
 * and "main").
286
 *
287
 * Tcl Arguments:
288
 *   linespec - the linespec defining the scope of the lookup. Empty string
289
 *              to use the current block in the innermost frame.
290
 * Tcl Result:
291
 *   A list of the locals or args
292
 */
293
static int
294
gdb_get_vars_command (clientData, interp, objc, objv)
295
     ClientData clientData;
296
     Tcl_Interp *interp;
297
     int objc;
298
     Tcl_Obj *CONST objv[];
299
{
300
  struct symtabs_and_lines sals;
301
  struct symbol *sym;
302
  struct block *block;
303
  char **canonical, *args;
304
  int i, nsyms, arguments;
305
 
306
  if (objc > 2)
307
    {
308
      Tcl_WrongNumArgs (interp, 1, objv,
309
                        "[function:line|function|line|*addr]");
310
      return TCL_ERROR;
311
    }
312
 
313
  arguments = (int) clientData;
314
 
315
  /* Initialize the result pointer to an empty list. */
316
 
317
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
318
 
319
  if (objc == 2)
320
    {
321
      args = Tcl_GetStringFromObj (objv[1], NULL);
322
      sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
323
      if (sals.nelts == 0)
324
        {
325
          Tcl_SetStringObj (result_ptr->obj_ptr,
326
                            "error decoding line", -1);
327
          return TCL_ERROR;
328
        }
329
 
330
      /* Resolve all line numbers to PC's */
331
      for (i = 0; i < sals.nelts; i++)
332
        resolve_sal_pc (&sals.sals[i]);
333
 
334
      block = block_for_pc (sals.sals[0].pc);
335
    }
336
  else
337
    {
338
      /* Specified currently selected frame */
339
      if (selected_frame == NULL)
340
        return TCL_OK;
341
 
342
      block = get_frame_block (selected_frame);
343
    }
344
 
345
  while (block != 0)
346
    {
347
      nsyms = BLOCK_NSYMS (block);
348
      for (i = 0; i < nsyms; i++)
349
        {
350
          sym = BLOCK_SYM (block, i);
351
          switch (SYMBOL_CLASS (sym))
352
            {
353
            default:
354
            case LOC_UNDEF:     /* catches errors        */
355
            case LOC_CONST:     /* constant              */
356
            case LOC_TYPEDEF:   /* local typedef         */
357
            case LOC_LABEL:     /* local label           */
358
            case LOC_BLOCK:     /* local function        */
359
            case LOC_CONST_BYTES:       /* loc. byte seq.        */
360
            case LOC_UNRESOLVED:        /* unresolved static     */
361
            case LOC_OPTIMIZED_OUT:     /* optimized out         */
362
              break;
363
            case LOC_ARG:       /* argument              */
364
            case LOC_REF_ARG:   /* reference arg         */
365
            case LOC_REGPARM:   /* register arg          */
366
            case LOC_REGPARM_ADDR:      /* indirect register arg */
367
            case LOC_LOCAL_ARG: /* stack arg             */
368
            case LOC_BASEREG_ARG:       /* basereg arg           */
369
              if (arguments)
370
                Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
371
                                  Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
372
              break;
373
            case LOC_LOCAL:     /* stack local           */
374
            case LOC_BASEREG:   /* basereg local         */
375
            case LOC_STATIC:    /* static                */
376
            case LOC_REGISTER:  /* register              */
377
              if (!arguments)
378
                Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
379
                                  Tcl_NewStringObj (SYMBOL_NAME (sym), -1));
380
              break;
381
            }
382
        }
383
      if (BLOCK_FUNCTION (block))
384
        break;
385
      else
386
        block = BLOCK_SUPERBLOCK (block);
387
    }
388
 
389
  return TCL_OK;
390
}
391
 
392
/* This implements the tcl command gdb_selected_block
393
 *
394
 * Returns the start and end addresses of the innermost
395
 * block in the selected frame.
396
 *
397
 * Arguments:
398
 *    None
399
 * Tcl Result:
400
 *    The currently selected block's start and end addresses
401
 */
402
static int
403
gdb_selected_block (clientData, interp, objc, objv)
404
     ClientData clientData;
405
     Tcl_Interp *interp;
406
     int objc;
407
     Tcl_Obj *CONST objv[];
408
{
409
  char *start = NULL;
410
  char *end   = NULL;
411
 
412
  if (selected_frame == NULL)
413
    {
414
      xasprintf (&start, "%s", "");
415
      xasprintf (&end, "%s", "");
416
    }
417
  else
418
    {
419
      struct block *block;
420
      block = get_frame_block (selected_frame);
421
      xasprintf (&start, "0x%s", paddr_nz (BLOCK_START (block)));
422
      xasprintf (&end, "0x%s", paddr_nz (BLOCK_END (block)));
423
    }
424
 
425
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
426
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
427
                            Tcl_NewStringObj (start, -1));
428
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
429
                            Tcl_NewStringObj (end, -1));
430
 
431
  free(start);
432
  free(end);
433
  return TCL_OK;
434
}
435
 
436
/* This implements the tcl command gdb_selected_frame
437
 
438
 * Returns the address of the selected frame
439
 * frame.
440
 *
441
 * Arguments:
442
 *    None
443
 * Tcl Result:
444
 *    The currently selected frame's address
445
 */
446
static int
447
gdb_selected_frame (clientData, interp, objc, objv)
448
     ClientData clientData;
449
     Tcl_Interp *interp;
450
     int objc;
451
     Tcl_Obj *CONST objv[];
452
{
453
  char *frame;
454
 
455
  if (selected_frame == NULL)
456
    xasprintf (&frame, "%s","");
457
  else
458
    xasprintf (&frame, "0x%s", paddr_nz (FRAME_FP (selected_frame)));
459
 
460
  Tcl_SetStringObj (result_ptr->obj_ptr, frame, -1);
461
 
462
  free(frame);
463
  return TCL_OK;
464
}
465
 
466
/* This implements the tcl command gdb_stack.
467
 * It builds up a list of stack frames.
468
 *
469
 * Tcl Arguments:
470
 *    start  - starting stack frame
471
 *    count - number of frames to inspect
472
 * Tcl Result:
473
 *    A list of function names
474
 */
475
static int
476
gdb_stack (clientData, interp, objc, objv)
477
     ClientData clientData;
478
     Tcl_Interp *interp;
479
     int objc;
480
     Tcl_Obj *CONST objv[];
481
{
482
  int start, count;
483
 
484
  if (objc < 3)
485
    {
486
      Tcl_WrongNumArgs (interp, 1, objv, "start count");
487
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
488
      return TCL_ERROR;
489
    }
490
 
491
  if (Tcl_GetIntFromObj (NULL, objv[1], &start))
492
    {
493
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
494
      return TCL_ERROR;
495
    }
496
  if (Tcl_GetIntFromObj (NULL, objv[2], &count))
497
    {
498
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
499
      return TCL_ERROR;
500
    }
501
 
502
  if (target_has_stack)
503
    {
504
      gdb_result r;
505
      struct frame_info *top;
506
      struct frame_info *fi;
507
 
508
      /* Find the outermost frame */
509
      r  = GDB_get_current_frame (&fi);
510
      if (r != GDB_OK)
511
        return TCL_ERROR;
512
 
513
      while (fi != NULL)
514
        {
515
          top = fi;
516
          r = GDB_get_prev_frame (fi, &fi);
517
          if (r != GDB_OK)
518
            fi = NULL;
519
        }
520
 
521
      /* top now points to the top (outermost frame) of the
522
         stack, so point it to the requested start */
523
      start = -start;
524
      r = GDB_find_relative_frame (top, &start, &top);
525
 
526
      result_ptr->obj_ptr = Tcl_NewListObj (0, NULL);
527
      if (r != GDB_OK)
528
        return TCL_OK;
529
 
530
      /* If start != 0, then we have asked to start outputting
531
         frames beyond the innermost stack frame */
532
      if (start == 0)
533
        {
534
          fi = top;
535
          while (fi && count--)
536
            {
537
              get_frame_name (interp, result_ptr->obj_ptr, fi);
538
              r = GDB_get_next_frame (fi, &fi);
539
              if (r != GDB_OK)
540
                break;
541
            }
542
        }
543
    }
544
 
545
  return TCL_OK;
546
}
547
 
548
/* A helper function for get_stack which adds information about
549
 * the stack frame FI to the caller's LIST.
550
 *
551
 * This is stolen from print_frame_info in stack.c.
552
 */
553
static void
554
get_frame_name (Tcl_Interp *interp, Tcl_Obj *list, struct frame_info *fi)
555
{
556
  struct symtab_and_line sal;
557
  struct symbol *func = NULL;
558
  register char *funname = 0;
559
  enum language funlang = language_unknown;
560
  Tcl_Obj *objv[1];
561
 
562
  if (frame_in_dummy (fi))
563
    {
564
      objv[0] = Tcl_NewStringObj ("<function called from gdb>\n", -1);
565
      Tcl_ListObjAppendElement (interp, list, objv[0]);
566
      return;
567
    }
568
  if (fi->signal_handler_caller)
569
    {
570
      objv[0] = Tcl_NewStringObj ("<signal handler called>\n", -1);
571
      Tcl_ListObjAppendElement (interp, list, objv[0]);
572
      return;
573
    }
574
 
575
  sal =
576
    find_pc_line (fi->pc,
577
                  fi->next != NULL
578
                  && !fi->next->signal_handler_caller
579
                  && !frame_in_dummy (fi->next));
580
 
581
  func = find_pc_function (fi->pc);
582
  if (func)
583
    {
584
      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
585
      if (msymbol != NULL
586
          && (SYMBOL_VALUE_ADDRESS (msymbol)
587
              > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
588
        {
589
          func = 0;
590
          funname = GDBTK_SYMBOL_SOURCE_NAME (msymbol);
591
          funlang = SYMBOL_LANGUAGE (msymbol);
592
        }
593
      else
594
        {
595
          funname = GDBTK_SYMBOL_SOURCE_NAME (func);
596
          funlang = SYMBOL_LANGUAGE (func);
597
        }
598
    }
599
  else
600
    {
601
      struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
602
      if (msymbol != NULL)
603
        {
604
          funname = GDBTK_SYMBOL_SOURCE_NAME (msymbol);
605
          funlang = SYMBOL_LANGUAGE (msymbol);
606
        }
607
    }
608
 
609
  if (sal.symtab)
610
    {
611
      objv[0] = Tcl_NewStringObj (funname, -1);
612
      Tcl_ListObjAppendElement (interp, list, objv[0]);
613
    }
614
  else
615
    {
616
#if 0
617
      /* we have no convenient way to deal with this yet... */
618
      if (fi->pc != sal.pc || !sal.symtab)
619
        {
620
          print_address_numeric (fi->pc, 1, gdb_stdout);
621
          printf_filtered (" in ");
622
        }
623
      printf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang,
624
                              DMGL_ANSI);
625
#endif
626
      objv[0] = Tcl_NewStringObj (funname != NULL ? funname : "??", -1);
627
#ifdef PC_LOAD_SEGMENT
628
      /* If we couldn't print out function name but if can figure out what
629
         load segment this pc value is from, at least print out some info
630
         about its load segment. */
631
      if (!funname)
632
        {
633
          Tcl_AppendStringsToObj (objv[0], " from ", PC_LOAD_SEGMENT (fi->pc),
634
                                  (char *) NULL);
635
        }
636
#endif
637
#ifdef PC_SOLIB
638
      if (!funname)
639
        {
640
          char *lib = PC_SOLIB (fi->pc);
641
          if (lib)
642
            {
643
              Tcl_AppendStringsToObj (objv[0], " from ", lib, (char *) NULL);
644
            }
645
        }
646
#endif
647
      Tcl_ListObjAppendElement (interp, list, objv[0]);
648
    }
649
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.