xref: /openbsd-src/gnu/usr.bin/binutils/gdb/cp-abi.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
1*b725ae77Skettenis /* Generic code for supporting multiple C++ ABI's
2*b725ae77Skettenis    Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
3*b725ae77Skettenis 
4*b725ae77Skettenis    This file is part of GDB.
5*b725ae77Skettenis 
6*b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
7*b725ae77Skettenis    it under the terms of the GNU General Public License as published by
8*b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
9*b725ae77Skettenis    (at your option) any later version.
10*b725ae77Skettenis 
11*b725ae77Skettenis    This program is distributed in the hope that it will be useful,
12*b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*b725ae77Skettenis    GNU General Public License for more details.
15*b725ae77Skettenis 
16*b725ae77Skettenis    You should have received a copy of the GNU General Public License
17*b725ae77Skettenis    along with this program; if not, write to the Free Software
18*b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
19*b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
20*b725ae77Skettenis 
21*b725ae77Skettenis #include "defs.h"
22*b725ae77Skettenis #include "value.h"
23*b725ae77Skettenis #include "cp-abi.h"
24*b725ae77Skettenis #include "command.h"
25*b725ae77Skettenis #include "gdbcmd.h"
26*b725ae77Skettenis #include "ui-out.h"
27*b725ae77Skettenis 
28*b725ae77Skettenis #include "gdb_string.h"
29*b725ae77Skettenis 
30*b725ae77Skettenis static struct cp_abi_ops *find_cp_abi (const char *short_name);
31*b725ae77Skettenis 
32*b725ae77Skettenis static struct cp_abi_ops current_cp_abi = { "", NULL };
33*b725ae77Skettenis static struct cp_abi_ops auto_cp_abi = { "auto", NULL };
34*b725ae77Skettenis 
35*b725ae77Skettenis #define CP_ABI_MAX 8
36*b725ae77Skettenis static struct cp_abi_ops *cp_abis[CP_ABI_MAX];
37*b725ae77Skettenis static int num_cp_abis = 0;
38*b725ae77Skettenis 
39*b725ae77Skettenis enum ctor_kinds
is_constructor_name(const char * name)40*b725ae77Skettenis is_constructor_name (const char *name)
41*b725ae77Skettenis {
42*b725ae77Skettenis   if ((current_cp_abi.is_constructor_name) == NULL)
43*b725ae77Skettenis     error ("ABI doesn't define required function is_constructor_name");
44*b725ae77Skettenis   return (*current_cp_abi.is_constructor_name) (name);
45*b725ae77Skettenis }
46*b725ae77Skettenis 
47*b725ae77Skettenis enum dtor_kinds
is_destructor_name(const char * name)48*b725ae77Skettenis is_destructor_name (const char *name)
49*b725ae77Skettenis {
50*b725ae77Skettenis   if ((current_cp_abi.is_destructor_name) == NULL)
51*b725ae77Skettenis     error ("ABI doesn't define required function is_destructor_name");
52*b725ae77Skettenis   return (*current_cp_abi.is_destructor_name) (name);
53*b725ae77Skettenis }
54*b725ae77Skettenis 
55*b725ae77Skettenis int
is_vtable_name(const char * name)56*b725ae77Skettenis is_vtable_name (const char *name)
57*b725ae77Skettenis {
58*b725ae77Skettenis   if ((current_cp_abi.is_vtable_name) == NULL)
59*b725ae77Skettenis     error ("ABI doesn't define required function is_vtable_name");
60*b725ae77Skettenis   return (*current_cp_abi.is_vtable_name) (name);
61*b725ae77Skettenis }
62*b725ae77Skettenis 
63*b725ae77Skettenis int
is_operator_name(const char * name)64*b725ae77Skettenis is_operator_name (const char *name)
65*b725ae77Skettenis {
66*b725ae77Skettenis   if ((current_cp_abi.is_operator_name) == NULL)
67*b725ae77Skettenis     error ("ABI doesn't define required function is_operator_name");
68*b725ae77Skettenis   return (*current_cp_abi.is_operator_name) (name);
69*b725ae77Skettenis }
70*b725ae77Skettenis 
71*b725ae77Skettenis int
baseclass_offset(struct type * type,int index,char * valaddr,CORE_ADDR address)72*b725ae77Skettenis baseclass_offset (struct type *type, int index, char *valaddr,
73*b725ae77Skettenis 		  CORE_ADDR address)
74*b725ae77Skettenis {
75*b725ae77Skettenis   if (current_cp_abi.baseclass_offset == NULL)
76*b725ae77Skettenis     error ("ABI doesn't define required function baseclass_offset");
77*b725ae77Skettenis   return (*current_cp_abi.baseclass_offset) (type, index, valaddr, address);
78*b725ae77Skettenis }
79*b725ae77Skettenis 
80*b725ae77Skettenis struct value *
value_virtual_fn_field(struct value ** arg1p,struct fn_field * f,int j,struct type * type,int offset)81*b725ae77Skettenis value_virtual_fn_field (struct value **arg1p, struct fn_field *f, int j,
82*b725ae77Skettenis 			struct type *type, int offset)
83*b725ae77Skettenis {
84*b725ae77Skettenis   if ((current_cp_abi.virtual_fn_field) == NULL)
85*b725ae77Skettenis     return NULL;
86*b725ae77Skettenis   return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset);
87*b725ae77Skettenis }
88*b725ae77Skettenis 
89*b725ae77Skettenis struct type *
value_rtti_type(struct value * v,int * full,int * top,int * using_enc)90*b725ae77Skettenis value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
91*b725ae77Skettenis {
92*b725ae77Skettenis   if ((current_cp_abi.rtti_type) == NULL)
93*b725ae77Skettenis     return NULL;
94*b725ae77Skettenis   return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
95*b725ae77Skettenis }
96*b725ae77Skettenis 
97*b725ae77Skettenis /* Set the current C++ ABI to SHORT_NAME.  */
98*b725ae77Skettenis 
99*b725ae77Skettenis static int
switch_to_cp_abi(const char * short_name)100*b725ae77Skettenis switch_to_cp_abi (const char *short_name)
101*b725ae77Skettenis {
102*b725ae77Skettenis   struct cp_abi_ops *abi;
103*b725ae77Skettenis 
104*b725ae77Skettenis   abi = find_cp_abi (short_name);
105*b725ae77Skettenis   if (abi == NULL)
106*b725ae77Skettenis     return 0;
107*b725ae77Skettenis 
108*b725ae77Skettenis   current_cp_abi = *abi;
109*b725ae77Skettenis   return 1;
110*b725ae77Skettenis }
111*b725ae77Skettenis 
112*b725ae77Skettenis /* Add ABI to the list of supported C++ ABI's.  */
113*b725ae77Skettenis 
114*b725ae77Skettenis int
register_cp_abi(struct cp_abi_ops * abi)115*b725ae77Skettenis register_cp_abi (struct cp_abi_ops *abi)
116*b725ae77Skettenis {
117*b725ae77Skettenis   if (num_cp_abis == CP_ABI_MAX)
118*b725ae77Skettenis     internal_error (__FILE__, __LINE__,
119*b725ae77Skettenis 		    "Too many C++ ABIs, please increase CP_ABI_MAX in cp-abi.c");
120*b725ae77Skettenis 
121*b725ae77Skettenis   cp_abis[num_cp_abis++] = abi;
122*b725ae77Skettenis 
123*b725ae77Skettenis   return 1;
124*b725ae77Skettenis }
125*b725ae77Skettenis 
126*b725ae77Skettenis /* Set the ABI to use in "auto" mode to SHORT_NAME.  */
127*b725ae77Skettenis 
128*b725ae77Skettenis void
set_cp_abi_as_auto_default(const char * short_name)129*b725ae77Skettenis set_cp_abi_as_auto_default (const char *short_name)
130*b725ae77Skettenis {
131*b725ae77Skettenis   char *new_longname, *new_doc;
132*b725ae77Skettenis   struct cp_abi_ops *abi = find_cp_abi (short_name);
133*b725ae77Skettenis 
134*b725ae77Skettenis   if (abi == NULL)
135*b725ae77Skettenis     internal_error (__FILE__, __LINE__,
136*b725ae77Skettenis 		    "Cannot find C++ ABI \"%s\" to set it as auto default.",
137*b725ae77Skettenis 		    short_name);
138*b725ae77Skettenis 
139*b725ae77Skettenis   if (auto_cp_abi.longname != NULL)
140*b725ae77Skettenis     xfree ((char *) auto_cp_abi.longname);
141*b725ae77Skettenis   if (auto_cp_abi.doc != NULL)
142*b725ae77Skettenis     xfree ((char *) auto_cp_abi.doc);
143*b725ae77Skettenis 
144*b725ae77Skettenis   auto_cp_abi = *abi;
145*b725ae77Skettenis 
146*b725ae77Skettenis   auto_cp_abi.shortname = "auto";
147*b725ae77Skettenis   new_longname = xmalloc (strlen ("currently ") + 1 + strlen (abi->shortname)
148*b725ae77Skettenis 			  + 1 + 1);
149*b725ae77Skettenis   sprintf (new_longname, "currently \"%s\"", abi->shortname);
150*b725ae77Skettenis   auto_cp_abi.longname = new_longname;
151*b725ae77Skettenis 
152*b725ae77Skettenis   new_doc = xmalloc (strlen ("Automatically selected; currently ")
153*b725ae77Skettenis 		     + 1 + strlen (abi->shortname) + 1 + 1);
154*b725ae77Skettenis   sprintf (new_doc, "Automatically selected; currently \"%s\"", abi->shortname);
155*b725ae77Skettenis   auto_cp_abi.doc = new_doc;
156*b725ae77Skettenis 
157*b725ae77Skettenis   /* Since we copy the current ABI into current_cp_abi instead of
158*b725ae77Skettenis      using a pointer, if auto is currently the default, we need to
159*b725ae77Skettenis      reset it.  */
160*b725ae77Skettenis   if (strcmp (current_cp_abi.shortname, "auto") == 0)
161*b725ae77Skettenis     switch_to_cp_abi ("auto");
162*b725ae77Skettenis }
163*b725ae77Skettenis 
164*b725ae77Skettenis /* Return the ABI operations associated with SHORT_NAME.  */
165*b725ae77Skettenis 
166*b725ae77Skettenis static struct cp_abi_ops *
find_cp_abi(const char * short_name)167*b725ae77Skettenis find_cp_abi (const char *short_name)
168*b725ae77Skettenis {
169*b725ae77Skettenis   int i;
170*b725ae77Skettenis 
171*b725ae77Skettenis   for (i = 0; i < num_cp_abis; i++)
172*b725ae77Skettenis     if (strcmp (cp_abis[i]->shortname, short_name) == 0)
173*b725ae77Skettenis       return cp_abis[i];
174*b725ae77Skettenis 
175*b725ae77Skettenis   return NULL;
176*b725ae77Skettenis }
177*b725ae77Skettenis 
178*b725ae77Skettenis /* Display the list of registered C++ ABIs.  */
179*b725ae77Skettenis 
180*b725ae77Skettenis static void
list_cp_abis(int from_tty)181*b725ae77Skettenis list_cp_abis (int from_tty)
182*b725ae77Skettenis {
183*b725ae77Skettenis   struct cleanup *cleanup_chain;
184*b725ae77Skettenis   int i;
185*b725ae77Skettenis   ui_out_text (uiout, "The available C++ ABIs are:\n");
186*b725ae77Skettenis 
187*b725ae77Skettenis   cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "cp-abi-list");
188*b725ae77Skettenis   for (i = 0; i < num_cp_abis; i++)
189*b725ae77Skettenis     {
190*b725ae77Skettenis       char pad[14];
191*b725ae77Skettenis       int padcount;
192*b725ae77Skettenis 
193*b725ae77Skettenis       ui_out_text (uiout, "  ");
194*b725ae77Skettenis       ui_out_field_string (uiout, "cp-abi", cp_abis[i]->shortname);
195*b725ae77Skettenis 
196*b725ae77Skettenis       padcount = 16 - 2 - strlen (cp_abis[i]->shortname);
197*b725ae77Skettenis       pad[padcount] = 0;
198*b725ae77Skettenis       while (padcount > 0)
199*b725ae77Skettenis 	pad[--padcount] = ' ';
200*b725ae77Skettenis       ui_out_text (uiout, pad);
201*b725ae77Skettenis 
202*b725ae77Skettenis       ui_out_field_string (uiout, "doc", cp_abis[i]->doc);
203*b725ae77Skettenis       ui_out_text (uiout, "\n");
204*b725ae77Skettenis     }
205*b725ae77Skettenis   do_cleanups (cleanup_chain);
206*b725ae77Skettenis }
207*b725ae77Skettenis 
208*b725ae77Skettenis /* Set the current C++ ABI, or display the list of options if no
209*b725ae77Skettenis    argument is given.  */
210*b725ae77Skettenis 
211*b725ae77Skettenis static void
set_cp_abi_cmd(char * args,int from_tty)212*b725ae77Skettenis set_cp_abi_cmd (char *args, int from_tty)
213*b725ae77Skettenis {
214*b725ae77Skettenis   if (args == NULL)
215*b725ae77Skettenis     {
216*b725ae77Skettenis       list_cp_abis (from_tty);
217*b725ae77Skettenis       return;
218*b725ae77Skettenis     }
219*b725ae77Skettenis 
220*b725ae77Skettenis   if (!switch_to_cp_abi (args))
221*b725ae77Skettenis     error ("Could not find \"%s\" in ABI list", args);
222*b725ae77Skettenis }
223*b725ae77Skettenis 
224*b725ae77Skettenis /* Show the currently selected C++ ABI.  */
225*b725ae77Skettenis 
226*b725ae77Skettenis static void
show_cp_abi_cmd(char * args,int from_tty)227*b725ae77Skettenis show_cp_abi_cmd (char *args, int from_tty)
228*b725ae77Skettenis {
229*b725ae77Skettenis   ui_out_text (uiout, "The currently selected C++ ABI is \"");
230*b725ae77Skettenis 
231*b725ae77Skettenis   ui_out_field_string (uiout, "cp-abi", current_cp_abi.shortname);
232*b725ae77Skettenis   ui_out_text (uiout, "\" (");
233*b725ae77Skettenis   ui_out_field_string (uiout, "longname", current_cp_abi.longname);
234*b725ae77Skettenis   ui_out_text (uiout, ").\n");
235*b725ae77Skettenis }
236*b725ae77Skettenis 
237*b725ae77Skettenis extern initialize_file_ftype _initialize_cp_abi; /* -Wmissing-prototypes */
238*b725ae77Skettenis 
239*b725ae77Skettenis void
_initialize_cp_abi(void)240*b725ae77Skettenis _initialize_cp_abi (void)
241*b725ae77Skettenis {
242*b725ae77Skettenis   register_cp_abi (&auto_cp_abi);
243*b725ae77Skettenis   switch_to_cp_abi ("auto");
244*b725ae77Skettenis 
245*b725ae77Skettenis   add_cmd ("cp-abi", class_obscure, set_cp_abi_cmd,
246*b725ae77Skettenis 	   "Set the ABI used for inspecting C++ objects.\n"
247*b725ae77Skettenis 	   "\"set cp-abi\" with no arguments will list the available ABIs.",
248*b725ae77Skettenis 	   &setlist);
249*b725ae77Skettenis 
250*b725ae77Skettenis   add_cmd ("cp-abi", class_obscure, show_cp_abi_cmd,
251*b725ae77Skettenis 	   "Show the ABI used for inspecting C++ objects.", &showlist);
252*b725ae77Skettenis }
253