1 /* Kernel Object Display generic routines and callbacks
2    Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
3 
4    Written by Fernando Nasser <fnasser@cygnus.com> for Cygnus Solutions.
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,
21    Boston, MA 02111-1307, USA.  */
22 
23 #include "defs.h"
24 #include "command.h"
25 #include "gdbcmd.h"
26 #include "target.h"
27 #include "gdb_string.h"
28 #include "kod.h"
29 
30 /* Prototypes for exported functions.  */
31 void _initialize_kod (void);
32 
33 /* Prototypes for local functions.  */
34 static void info_kod_command (char *, int);
35 static void load_kod_library (char *);
36 
37 /* Prototypes for callbacks.  These are passed into the KOD modules.  */
ggc_round_alloc_size(size_t requested_size)38 static void gdb_kod_display (char *);
39 static void gdb_kod_query (char *, char *, int *);
40 
41 /* These functions are imported from the KOD module.
42 
43    gdb_kod_open - initiates the KOD connection to the remote.  The
ggc_internal_alloc(size_t size,void (* f)(void *),size_t,size_t MEM_STAT_DECL)44    first argument is the display function the module should use to
45    communicate with the user.  The second argument is the query
46    function the display should use to communicate with the target.
47    This should call error() if there is an error.  Otherwise it should
48    return a malloc()d string of the form:
49 
50    NAME VERSION - DESCRIPTION
51 
52    Neither NAME nor VERSION should contain a hyphen.
53 
54 
55    gdb_kod_request - This is used when the user enters an "info
56    <module>" request.  The remaining arguments are passed as the first
57    argument.  The second argument is the standard `from_tty'
58    argument.
59 
60 
61    gdb_kod_close - This is called when the KOD connection to the
62    remote should be terminated.  */
63 
64 static char *(*gdb_kod_open) (kod_display_callback_ftype *display,
65 			      kod_query_callback_ftype *query);
ggc_free(void * p)66 static void (*gdb_kod_request) (char *, int);
67 static void (*gdb_kod_close) ();
68 
69 
70 /* Name of inferior's operating system.  */
71 char *operating_system;
ggc_grow(void)72 
73 /* We save a copy of the OS so that we can properly reset when
74    switching OS's.  */
75 static char *old_operating_system;
76 
ggc_trim(void)77 /* Print a line of data generated by the module.  */
78 
79 static void
80 gdb_kod_display (char *arg)
81 {
82   printf_filtered ("%s", arg);
83 }
84 
85 /* Queries the target on behalf of the module.  */
86 
87 static void
88 gdb_kod_query (char *arg, char *result, int *maxsiz)
89 {
90   LONGEST bufsiz = 0;
91 
92   /* Check if current target has remote_query capabilities.  If not,
93      it does not have kod either.  */
94   bufsiz = target_read_partial (&current_target, TARGET_OBJECT_KOD,
95 				NULL, NULL, 0, 0);
96   if (bufsiz < 0)
97     {
98       strcpy (result,
99               "ERR: Kernel Object Display not supported by current target\n");
100       return;
101     }
102 
103   /* Just get the maximum buffer size.  */
104 
105   /* Check if *we* were called just for getting the buffer size.  */
106   if (*maxsiz == 0)
107     {
108       *maxsiz = bufsiz;
109       strcpy (result, "OK");
110       return;
111     }
112 
113   /* Check if caller can handle a buffer this large, if not, adjust.  */
114   if (bufsiz > *maxsiz)
115     bufsiz = *maxsiz;
116 
117   /* See if buffer can hold the query (usually it can, as the query is
118      short).  */
119   if (strlen (arg) >= bufsiz)
120     error ("kod: query argument too long");
121 
122   /* Send actual request.  */
123   if (target_read_partial (&current_target, TARGET_OBJECT_KOD,
124 			   arg, result, 0, bufsiz) < 0)
125     strcpy (result, "ERR: remote query failed");
126 }
127 
128 /* Print name of kod command after selecting the appropriate kod
129    formatting library module.  As a side effect we create a new "info"
130    subcommand which is what the user actually uses to query the OS.  */
131 
132 static void
133 kod_set_os (char *arg, int from_tty, struct cmd_list_element *command)
134 {
135   char *p;
136 
137   /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
138      the set command passed as a parameter.  The clone operation will
139      include (BUG?) any ``set'' command callback, if present.
140      Commands like ``info set'' call all the ``show'' command
141      callbacks.  Unfortunately, for ``show'' commands cloned from
142      ``set'', this includes callbacks belonging to ``set'' commands.
143      Making this worse, this only occures if add_show_from_set() is
144      called after add_cmd_sfunc() (BUG?).  */
145 
146   if (cmd_type (command) != set_cmd)
147     return;
148 
149   /* If we had already had an open OS, close it.  */
150   if (gdb_kod_close)
151     (*gdb_kod_close) ();
152 
153   /* Also remove the old OS's command.  */
154   if (old_operating_system)
155     {
156       delete_cmd (old_operating_system, &infolist);
157       xfree (old_operating_system);
158     }
159 
160   if (! operating_system || ! *operating_system)
161     {
162       /* If user set operating system to empty, we want to forget we
163 	 had a module open.  Setting these variables is just nice for
164 	 debugging and clarity.  */
165       gdb_kod_open = NULL;
166       gdb_kod_request = NULL;
167       gdb_kod_close = NULL;
168     }
169   else
170     {
171       char *kodlib;
172 
173       old_operating_system = xstrdup (operating_system);
174 
175       load_kod_library (operating_system);
176 
177       kodlib = (*gdb_kod_open) (gdb_kod_display, gdb_kod_query);
178 
179       /* Add kod related info commands to gdb.  */
180       add_info (operating_system, info_kod_command,
181 		"Displays information about Kernel Objects.");
182 
183       p = strrchr (kodlib, '-');
184       if (p != NULL)
185 	p++;
186       else
187 	p = "Unknown KOD library";
188       printf_filtered ("%s - %s\n", operating_system, p);
189 
190       xfree (kodlib);
191     }
192 }
193 
194 /* Print information about currently known kernel objects of the
195    specified type or a list of all known kernel object types if
196    argument is empty.  */
197 
198 static void
199 info_kod_command (char *arg, int from_tty)
200 {
201   (*gdb_kod_request) (arg, from_tty);
202 }
203 
204 /* Print name of kod command after selecting the appropriate kod
205    formatting library module.  */
206 
207 static void
208 load_kod_library (char *lib)
209 {
210 #if 0
211   /* FIXME: Don't have the eCos code here.  */
212   if (! strcmp (lib, "ecos"))
213     {
214       gdb_kod_open = ecos_kod_open;
215       gdb_kod_request = ecos_kod_request;
216       gdb_kod_close = ecos_kod_close;
217     }
218   else
219 #endif /* 0 */
220    if (! strcmp (lib, "cisco"))
221     {
222       gdb_kod_open = cisco_kod_open;
223       gdb_kod_request = cisco_kod_request;
224       gdb_kod_close = cisco_kod_close;
225     }
226   else
227     error ("Unknown operating system: %s\n", operating_system);
228 }
229 
230 void
231 _initialize_kod (void)
232 {
233   struct cmd_list_element *c;
234 
235   c = add_set_cmd ("os", no_class, var_string,
236 		   (char *) &operating_system,
237 		   "Set operating system",
238 		   &setlist);
239   set_cmd_sfunc (c, kod_set_os);
240   add_show_from_set (c, &showlist);
241 }
242