1/* Definitions for frame address handler, for GDB, the GNU debugger.
2
3   Copyright 2003 Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.  */
21
22#include "defs.h"
23#include "frame-base.h"
24#include "frame.h"
25
26/* A default frame base implementations.  If it wasn't for the old
27   DEPRECATED_FRAME_LOCALS_ADDRESS and DEPRECATED_FRAME_ARGS_ADDRESS,
28   these could be combined into a single function.  All architectures
29   really need to override this.  */
30
31static CORE_ADDR
32default_frame_base_address (struct frame_info *next_frame, void **this_cache)
33{
34  struct frame_info *this_frame = get_prev_frame (next_frame);
35  return get_frame_base (this_frame); /* sigh! */
36}
37
38static CORE_ADDR
39default_frame_locals_address (struct frame_info *next_frame, void **this_cache)
40{
41  if (DEPRECATED_FRAME_LOCALS_ADDRESS_P ())
42    {
43      /* This is bad.  The computation of per-frame locals address
44	 should use a per-frame frame-base.  */
45      struct frame_info *this_frame = get_prev_frame (next_frame);
46      return DEPRECATED_FRAME_LOCALS_ADDRESS (this_frame);
47    }
48  return default_frame_base_address (next_frame, this_cache);
49}
50
51static CORE_ADDR
52default_frame_args_address (struct frame_info *next_frame, void **this_cache)
53{
54  if (DEPRECATED_FRAME_ARGS_ADDRESS_P ())
55    {
56      struct frame_info *this_frame = get_prev_frame (next_frame);
57      return DEPRECATED_FRAME_ARGS_ADDRESS (this_frame);
58    }
59  return default_frame_base_address (next_frame, this_cache);
60}
61
62const struct frame_base default_frame_base = {
63  NULL, /* No parent.  */
64  default_frame_base_address,
65  default_frame_locals_address,
66  default_frame_args_address
67};
68
69static struct gdbarch_data *frame_base_data;
70
71struct frame_base_table
72{
73  frame_base_sniffer_ftype **sniffer;
74  const struct frame_base *default_base;
75  int nr;
76};
77
78static void *
79frame_base_init (struct gdbarch *gdbarch)
80{
81  struct frame_base_table *table = XCALLOC (1, struct frame_base_table);
82  table->default_base = &default_frame_base;
83  return table;
84}
85
86static struct frame_base_table *
87frame_base_table (struct gdbarch *gdbarch)
88{
89  struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
90  if (table == NULL)
91    {
92      /* ULGH, called during architecture initialization.  Patch
93         things up.  */
94      table = frame_base_init (gdbarch);
95      set_gdbarch_data (gdbarch, frame_base_data, table);
96    }
97  return table;
98}
99
100/* Append a predicate to the end of the table.  */
101static void
102append_predicate (struct frame_base_table *table,
103		  frame_base_sniffer_ftype *sniffer)
104{
105  table->sniffer = xrealloc (table->sniffer,
106			     ((table->nr + 1)
107			      * sizeof (frame_base_sniffer_ftype *)));
108  table->sniffer[table->nr] = sniffer;
109  table->nr++;
110}
111
112void
113frame_base_append_sniffer (struct gdbarch *gdbarch,
114			   frame_base_sniffer_ftype *sniffer)
115{
116  struct frame_base_table *table = frame_base_table (gdbarch);
117  append_predicate (table, sniffer);
118}
119
120void
121frame_base_set_default (struct gdbarch *gdbarch,
122			const struct frame_base *default_base)
123{
124  struct frame_base_table *table = frame_base_table (gdbarch);
125  table->default_base = default_base;
126}
127
128const struct frame_base *
129frame_base_find_by_frame (struct frame_info *next_frame)
130{
131  struct gdbarch *gdbarch = get_frame_arch (next_frame);
132  struct frame_base_table *table = frame_base_table (gdbarch);
133  int i;
134  for (i = 0; i < table->nr; i++)
135    {
136      const struct frame_base *desc = NULL;
137      desc = table->sniffer[i] (next_frame);
138      if (desc != NULL)
139	return desc;
140    }
141  return table->default_base;
142}
143
144extern initialize_file_ftype _initialize_frame_base; /* -Wmissing-prototypes */
145
146void
147_initialize_frame_base (void)
148{
149  frame_base_data = register_gdbarch_data (frame_base_init);
150}
151