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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [dummy-frame.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
2
 
3
   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
4
   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009,
5
   2010 Free Software Foundation, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
 
23
#include "defs.h"
24
#include "dummy-frame.h"
25
#include "regcache.h"
26
#include "frame.h"
27
#include "inferior.h"
28
#include "gdb_assert.h"
29
#include "frame-unwind.h"
30
#include "command.h"
31
#include "gdbcmd.h"
32
#include "gdb_string.h"
33
#include "observer.h"
34
 
35
/* Dummy frame.  This saves the processor state just prior to setting
36
   up the inferior function call.  Older targets save the registers
37
   on the target stack (but that really slows down function calls).  */
38
 
39
struct dummy_frame
40
{
41
  struct dummy_frame *next;
42
  /* This frame's ID.  Must match the value returned by
43
     gdbarch_dummy_id.  */
44
  struct frame_id id;
45
  /* The caller's state prior to the call.  */
46
  struct inferior_thread_state *caller_state;
47
};
48
 
49
static struct dummy_frame *dummy_frame_stack = NULL;
50
 
51
/* Function: deprecated_pc_in_call_dummy (pc)
52
 
53
   Return non-zero if the PC falls in a dummy frame created by gdb for
54
   an inferior call.  The code below which allows gdbarch_decr_pc_after_break
55
   is for infrun.c, which may give the function a PC without that
56
   subtracted out.
57
 
58
   FIXME: cagney/2002-11-23: This is silly.  Surely "infrun.c" can
59
   figure out what the real PC (as in the resume address) is BEFORE
60
   calling this function.
61
 
62
   NOTE: cagney/2004-08-02: I'm pretty sure that, with the introduction of
63
   infrun.c:adjust_pc_after_break (thanks), this function is now
64
   always called with a correctly adjusted PC!
65
 
66
   NOTE: cagney/2004-08-02: Code should not need to call this.  */
67
 
68
int
69
deprecated_pc_in_call_dummy (struct gdbarch *gdbarch, CORE_ADDR pc)
70
{
71
  struct dummy_frame *dummyframe;
72
  for (dummyframe = dummy_frame_stack;
73
       dummyframe != NULL;
74
       dummyframe = dummyframe->next)
75
    {
76
      if ((pc >= dummyframe->id.code_addr)
77
          && (pc <= dummyframe->id.code_addr
78
                    + gdbarch_decr_pc_after_break (gdbarch)))
79
        return 1;
80
    }
81
  return 0;
82
}
83
 
84
/* Push the caller's state, along with the dummy frame info, onto the
85
   dummy-frame stack.  */
86
 
87
void
88
dummy_frame_push (struct inferior_thread_state *caller_state,
89
                  const struct frame_id *dummy_id)
90
{
91
  struct dummy_frame *dummy_frame;
92
 
93
  dummy_frame = XZALLOC (struct dummy_frame);
94
  dummy_frame->caller_state = caller_state;
95
  dummy_frame->id = (*dummy_id);
96
  dummy_frame->next = dummy_frame_stack;
97
  dummy_frame_stack = dummy_frame;
98
}
99
 
100
/* Remove *DUMMY_PTR from the dummy frame stack.  */
101
 
102
static void
103
remove_dummy_frame (struct dummy_frame **dummy_ptr)
104
{
105
  struct dummy_frame *dummy = *dummy_ptr;
106
 
107
  *dummy_ptr = dummy->next;
108
  discard_inferior_thread_state (dummy->caller_state);
109
  xfree (dummy);
110
}
111
 
112
/* Pop *DUMMY_PTR, restoring program state to that before the
113
   frame was created.  */
114
 
115
static void
116
pop_dummy_frame (struct dummy_frame **dummy_ptr)
117
{
118
  struct dummy_frame *dummy;
119
 
120
  restore_inferior_thread_state ((*dummy_ptr)->caller_state);
121
 
122
  /* restore_inferior_status frees inf_state,
123
     all that remains is to pop *dummy_ptr */
124
  dummy = *dummy_ptr;
125
  *dummy_ptr = dummy->next;
126
  xfree (dummy);
127
 
128
  /* We've made right mess of GDB's local state, just discard
129
     everything.  */
130
  reinit_frame_cache ();
131
}
132
 
133
/* Look up DUMMY_ID.
134
   Return NULL if not found.  */
135
 
136
static struct dummy_frame **
137
lookup_dummy_frame (struct frame_id dummy_id)
138
{
139
  struct dummy_frame **dp;
140
 
141
  for (dp = &dummy_frame_stack; *dp != NULL; dp = &(*dp)->next)
142
    {
143
      if (frame_id_eq ((*dp)->id, dummy_id))
144
        return dp;
145
    }
146
 
147
  return NULL;
148
}
149
 
150
/* Pop the dummy frame DUMMY_ID, restoring program state to that before the
151
   frame was created.
152
   On return reinit_frame_cache has been called.
153
   If the frame isn't found, flag an internal error.
154
 
155
   NOTE: This can only pop the one frame, even if it is in the middle of the
156
   stack, because the other frames may be for different threads, and there's
157
   currently no way to tell which stack frame is for which thread.  */
158
 
159
void
160
dummy_frame_pop (struct frame_id dummy_id)
161
{
162
  struct dummy_frame **dp;
163
 
164
  dp = lookup_dummy_frame (dummy_id);
165
  gdb_assert (dp != NULL);
166
 
167
  pop_dummy_frame (dp);
168
}
169
 
170
/* There may be stale dummy frames, perhaps left over from when a longjump took
171
   us out of a function that was called by the debugger.  Clean them up at
172
   least once whenever we start a new inferior.  */
173
 
174
static void
175
cleanup_dummy_frames (struct target_ops *target, int from_tty)
176
{
177
  while (dummy_frame_stack != NULL)
178
    remove_dummy_frame (&dummy_frame_stack);
179
}
180
 
181
/* Return the dummy frame cache, it contains both the ID, and a
182
   pointer to the regcache.  */
183
struct dummy_frame_cache
184
{
185
  struct frame_id this_id;
186
  struct regcache *prev_regcache;
187
};
188
 
189
static int
190
dummy_frame_sniffer (const struct frame_unwind *self,
191
                     struct frame_info *this_frame,
192
                     void **this_prologue_cache)
193
{
194
  struct dummy_frame *dummyframe;
195
  struct frame_id this_id;
196
 
197
  /* When unwinding a normal frame, the stack structure is determined
198
     by analyzing the frame's function's code (be it using brute force
199
     prologue analysis, or the dwarf2 CFI).  In the case of a dummy
200
     frame, that simply isn't possible.  The PC is either the program
201
     entry point, or some random address on the stack.  Trying to use
202
     that PC to apply standard frame ID unwind techniques is just
203
     asking for trouble.  */
204
 
205
  /* Don't bother unless there is at least one dummy frame.  */
206
  if (dummy_frame_stack != NULL)
207
    {
208
      /* Use an architecture specific method to extract this frame's
209
         dummy ID, assuming it is a dummy frame.  */
210
      this_id = gdbarch_dummy_id (get_frame_arch (this_frame), this_frame);
211
 
212
      /* Use that ID to find the corresponding cache entry.  */
213
      for (dummyframe = dummy_frame_stack;
214
           dummyframe != NULL;
215
           dummyframe = dummyframe->next)
216
        {
217
          if (frame_id_eq (dummyframe->id, this_id))
218
            {
219
              struct dummy_frame_cache *cache;
220
              cache = FRAME_OBSTACK_ZALLOC (struct dummy_frame_cache);
221
              cache->prev_regcache = get_inferior_thread_state_regcache (dummyframe->caller_state);
222
              cache->this_id = this_id;
223
              (*this_prologue_cache) = cache;
224
              return 1;
225
            }
226
        }
227
    }
228
  return 0;
229
}
230
 
231
/* Given a call-dummy dummy-frame, return the registers.  Here the
232
   register value is taken from the local copy of the register buffer.  */
233
 
234
static struct value *
235
dummy_frame_prev_register (struct frame_info *this_frame,
236
                           void **this_prologue_cache,
237
                           int regnum)
238
{
239
  struct dummy_frame_cache *cache = (*this_prologue_cache);
240
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
241
  struct value *reg_val;
242
 
243
  /* The dummy-frame sniffer always fills in the cache.  */
244
  gdb_assert (cache != NULL);
245
 
246
  /* Describe the register's location.  Generic dummy frames always
247
     have the register value in an ``expression''.  */
248
  reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
249
 
250
  /* Use the regcache_cooked_read() method so that it, on the fly,
251
     constructs either a raw or pseudo register from the raw
252
     register cache.  */
253
  regcache_cooked_read (cache->prev_regcache, regnum,
254
                        value_contents_writeable (reg_val));
255
  return reg_val;
256
}
257
 
258
/* Assuming that THIS_FRAME is a dummy, return its ID.  That ID is
259
   determined by examining the NEXT frame's unwound registers using
260
   the method dummy_id().  As a side effect, THIS dummy frame's
261
   dummy cache is located and and saved in THIS_PROLOGUE_CACHE.  */
262
 
263
static void
264
dummy_frame_this_id (struct frame_info *this_frame,
265
                     void **this_prologue_cache,
266
                     struct frame_id *this_id)
267
{
268
  /* The dummy-frame sniffer always fills in the cache.  */
269
  struct dummy_frame_cache *cache = (*this_prologue_cache);
270
  gdb_assert (cache != NULL);
271
  (*this_id) = cache->this_id;
272
}
273
 
274
static const struct frame_unwind dummy_frame_unwinder =
275
{
276
  DUMMY_FRAME,
277
  dummy_frame_this_id,
278
  dummy_frame_prev_register,
279
  NULL,
280
  dummy_frame_sniffer,
281
};
282
 
283
const struct frame_unwind *const dummy_frame_unwind = {
284
  &dummy_frame_unwinder
285
};
286
 
287
static void
288
fprint_dummy_frames (struct ui_file *file)
289
{
290
  struct dummy_frame *s;
291
  for (s = dummy_frame_stack; s != NULL; s = s->next)
292
    {
293
      gdb_print_host_address (s, file);
294
      fprintf_unfiltered (file, ":");
295
      fprintf_unfiltered (file, " id=");
296
      fprint_frame_id (file, s->id);
297
      fprintf_unfiltered (file, "\n");
298
    }
299
}
300
 
301
static void
302
maintenance_print_dummy_frames (char *args, int from_tty)
303
{
304
  if (args == NULL)
305
    fprint_dummy_frames (gdb_stdout);
306
  else
307
    {
308
      struct cleanup *cleanups;
309
      struct ui_file *file = gdb_fopen (args, "w");
310
      if (file == NULL)
311
        perror_with_name (_("maintenance print dummy-frames"));
312
      cleanups = make_cleanup_ui_file_delete (file);
313
      fprint_dummy_frames (file);
314
      do_cleanups (cleanups);
315
    }
316
}
317
 
318
extern void _initialize_dummy_frame (void);
319
 
320
void
321
_initialize_dummy_frame (void)
322
{
323
  add_cmd ("dummy-frames", class_maintenance, maintenance_print_dummy_frames,
324
           _("Print the contents of the internal dummy-frame stack."),
325
           &maintenanceprintlist);
326
 
327
  observer_attach_inferior_created (cleanup_dummy_frames);
328
}

powered by: WebSVN 2.1.0

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