Adjust for symbol name changes.
[dragonfly.git] / contrib / gdb-6.2.1 / gdb / kod-cisco.c
1 /* Kernel Object Display facility for Cisco
2    Copyright 1999, 2000 Free Software Foundation, Inc.
3    
4    Written by Tom Tromey <tromey@cygnus.com>.
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, Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "gdb_string.h"
24 #include "kod.h"
25
26 #ifdef HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif
29
30 /* Define this to turn off communication with target.  */
31 /* #define FAKE_PACKET */
32
33 /* Size of buffer used for remote communication.  */
34 #define PBUFSIZ 400
35
36 /* Pointers to gdb callbacks.  */
37 static void (*gdb_kod_display) (char *);
38 static void (*gdb_kod_query) (char *, char *, int *);
39
40 \f
41
42 /* Initialize and return library name and version.
43    The gdb side of KOD, kod.c, passes us two functions: one for
44    displaying output (presumably to the user) and the other for
45    querying the target.  */
46 char *
47 cisco_kod_open (kod_display_callback_ftype *display_func,
48                 kod_query_callback_ftype *query_func)
49 {
50   char buffer[PBUFSIZ];
51   int bufsiz = PBUFSIZ;
52   int i, count;
53
54   gdb_kod_display = display_func;
55   gdb_kod_query = query_func;
56
57   /* Get the OS info, and check the version field.  This is the stub
58      version, which we use to see whether we will understand what
59      comes back.  This is lame, but the `qKoL' request doesn't
60      actually provide enough configurability.
61      
62      Right now the only defined version number is `0.0.0'.
63      This stub supports qKoI and the `a' (any) object requests qKaL
64      and qKaI.  Each `a' object is returned as a 4-byte integer ID.
65      An info request on an object returns a pair of 4-byte integers;
66      the first is the object pointer and the second is the thread ID.  */
67
68 #ifndef FAKE_PACKET
69   (*gdb_kod_query) ("oI;", buffer, &bufsiz);
70 #else
71   strcpy (buffer, "Cisco IOS/Classic/13.4 0.0.0");
72 #endif
73
74   count = 2;
75   for (i = 0; count && buffer[i] != '\0'; ++i)
76     {
77       if (buffer[i] == ' ')
78         --count;
79     }
80
81   if (buffer[i] == '\0')
82     error ("Remote returned malformed packet\n");
83   if (strcmp (&buffer[i], "0.0.0"))
84     error ("Remote returned unknown stub version: %s\n", &buffer[i]);
85
86   /* Return name, version, and description.  I hope we have enough
87      space.  */
88   return (xstrdup ("gdbkodcisco v0.0.0 - Cisco Kernel Object Display"));
89 }
90
91 /* Close the connection.  */
92 void
93 cisco_kod_close (void)
94 {
95 }
96
97 /* Print a "bad packet" message.  */
98 static void
99 bad_packet (void)
100 {
101   (*gdb_kod_display) ("Remote target returned malformed packet.\n");
102 }
103
104 /* Print information about currently known kernel objects.
105    We currently ignore the argument.  There is only one mode of
106    querying the Cisco kernel: we ask for a dump of everything, and
107    it returns it.  */
108 void
109 cisco_kod_request (char *arg, int from_tty)
110 {
111   char buffer[PBUFSIZ], command[PBUFSIZ];
112   int done = 0, i;
113   int fail = 0;
114
115   char **sync_ids = NULL;
116   int sync_len = 0;
117   int sync_next = 0;
118   char *prev_id = NULL;
119
120   if (! arg || strcmp (arg, "any"))
121     {
122       /* "Top-level" command.  This is really silly, but it also seems
123          to be how KOD is defined.  */
124       /* Even sillier is the fact that this first line must start
125          with the word "List".  See kod.tcl.  */
126       (*gdb_kod_display) ("List of Cisco Kernel Objects\n");
127       (*gdb_kod_display) ("Object\tDescription\n");
128       (*gdb_kod_display) ("any\tAny and all objects\n");
129       return;
130     }
131
132   while (! done)
133     {
134       int off = 0;              /* Where we are in the string.  */
135       long count;               /* Number of objects in this packet.  */
136       int bufsiz = PBUFSIZ;
137       char *s_end;
138
139       strcpy (command, "aL");
140       if (prev_id)
141         {
142           strcat (command, ",");
143           strcat (command, prev_id);
144         }
145       strcat (command, ";");
146
147 #ifndef FAKE_PACKET
148       /* We talk to the target by calling through the query function
149          passed to us when we were initialized.  */
150       (*gdb_kod_query) (command, buffer, &bufsiz);
151 #else
152       /* Fake up a multi-part packet.  */
153       if (! strncmp (&command[3], "a500005a", 8))
154         strcpy (buffer, "KAL,01,1,f500005f;f500005f;");
155       else
156         strcpy (buffer, "KAL,02,0,a500005a;a500005a;de02869f;");
157 #endif
158
159       /* Empty response is an error.  */
160       if (strlen (buffer) == 0)
161         {
162           (*gdb_kod_display) ("Remote target did not recognize kernel object query command.\n");
163           fail = 1;
164           break;
165         }
166
167       /* If we don't get a `K' response then the buffer holds the
168          target's error message.  */
169       if (buffer[0] != 'K')
170         {
171           (*gdb_kod_display) (buffer);
172           fail = 1;
173           break;
174         }
175
176       /* Make sure we get the response we expect.  */
177       if (strncmp (buffer, "KAL,", 4))
178         {
179           bad_packet ();
180           fail = 1;
181           break;
182         }
183       off += 4;
184
185       /* Parse out the count.  We expect to convert exactly two
186          characters followed by a comma.  */
187       count = strtol (&buffer[off], &s_end, 16);
188       if (s_end - &buffer[off] != 2 || buffer[off + 2] != ',')
189         {
190           bad_packet ();
191           fail = 1;
192           break;
193         }
194       off += 3;
195
196       /* Parse out the `done' flag.  */
197       if ((buffer[off] != '0' && buffer[off] != '1')
198           || buffer[off + 1] != ',')
199         {
200           bad_packet ();
201           fail = 1;
202           break;
203         }
204       done = buffer[off] == '1';
205       off += 2;
206
207       /* Id of the last item; we might this to construct the next
208          request.  */
209       prev_id = &buffer[off];
210       if (strlen (prev_id) < 8 || buffer[off + 8] != ';')
211         {
212           bad_packet ();
213           fail = 1;
214           break;
215         }
216       buffer[off + 8] = '\0';
217       off += 9;
218
219       sync_len += count;
220       sync_ids = (char **) xrealloc (sync_ids, sync_len * sizeof (char *));
221
222       for (i = 0; i < count; ++i)
223         {
224           if (strlen (&buffer[off]) < 8 || buffer[off + 8] != ';')
225             {
226               bad_packet ();
227               fail = 1;
228               break;
229             }
230           buffer[off + 8] = '\0';
231           sync_ids[sync_next++] = xstrdup (&buffer[off]);
232           off += 9;
233         }
234
235       if (buffer[off] != '\0')
236         {
237           bad_packet ();
238           fail = 1;
239           break;
240         }
241     }
242
243   /* We've collected all the sync object IDs.  Now query to get the
244      specific information, and arrange to print this info.  */
245   if (! fail)
246     {
247       (*gdb_kod_display) ("Object ID\tObject Pointer\tThread ID\n");
248
249       for (i = 0; i < sync_next; ++i)
250         {
251           int off = 0;
252           int bufsiz = PBUFSIZ;
253
254           /* For now assume a query can be accomplished in a single
255              transaction.  This is implied in the protocol document.
256              See comments above, and the KOD protocol document, to
257              understand the parsing of the return value.  */
258           strcpy (command, "aI,");
259           strcat (command, sync_ids[i]);
260           strcat (command, ";");
261
262 #ifndef FAKE_PACKET
263           (*gdb_kod_query) (command, buffer, &bufsiz);
264 #else
265           strcpy (buffer, "KAI,");
266           strcat (buffer, sync_ids[i]);
267           strcat (buffer, ",ffef00a0,cd00123d;");
268 #endif
269
270           if (strlen (buffer) == 0)
271             {
272               (*gdb_kod_display) ("Remote target did not recognize KOD command.\n");
273               break;
274             }
275
276           if (strncmp (buffer, "KAI,", 4))
277             {
278               bad_packet ();
279               break;
280             }
281           off += 4;
282
283           if (strncmp (&buffer[off], sync_ids[i], 8)
284               || buffer[off + 8] != ',')
285             {
286               bad_packet ();
287               break;
288             }
289           off += 9;
290
291           /* Extract thread id and sync object pointer.  */
292           if (strlen (&buffer[off]) != 2 * 8 + 2
293               || buffer[off + 8] != ','
294               || buffer[off + 17] != ';')
295             {
296               bad_packet ();
297               break;
298             }
299
300           buffer[off + 8] = '\0';
301           buffer[off + 17] = '\0';
302
303           /* Display the result.  */
304           (*gdb_kod_display) (sync_ids[i]);
305           (*gdb_kod_display) ("\t");
306           (*gdb_kod_display) (&buffer[off]);
307           (*gdb_kod_display) ("\t");
308           (*gdb_kod_display) (&buffer[off + 9]);
309           (*gdb_kod_display) ("\n");
310         }
311     }
312
313   /* Free memory.  */
314   for (i = 0; i < sync_next; ++i)
315     xfree (sync_ids[i]);
316   xfree (sync_ids);
317 }