Added patch headers.
[linux-flexiantxendom0-3.2.10.git] / kdb / modules / kdbm_debugtypes.c
1 /* this one has some additional address validation - untested */
2 /*
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
8  */
9
10 /*
11  *
12  * Most of this code is borrowed and adapted from the lkcd command "lcrash"
13  * and its supporting libarary.
14  *
15  * This module provides kdb commands for casting memory structures.
16  * It loads symbolic debugging info (provided from lcrash -o), and provides
17  *  "print" "px", "pd"
18  * (this information originally comes from the lcrash "kerntypes" file)
19  *
20  * A key here is tacking a file of debug info onto this module, for
21  * load with it at insmod time.
22  *
23  * Careful of porting the klib KL_XXX functions (they call thru a jump table
24  * that we don't use here)
25  *
26  * Usage:
27  *  in order for the insmod kdbm_debugtypes.ko to succeed in loading types
28  *  you must first use  lcrash -t kerntypes.xxxx -o debug_info
29  *  and echo debug_info > /proc/kdb/debug_info_name
30  */
31
32 #define VMALLOC_START_IA64 0xa000000200000000
33 #include <linux/kernel.h>
34 #include <linux/module.h>
35 #include <linux/kdb.h>
36 #include <linux/kdbprivate.h>
37 #include <linux/fs.h>
38 #include <asm/processor.h>
39 #include <asm/uaccess.h>
40 #include <asm/fcntl.h>
41 #include <linux/vmalloc.h>
42 #include <linux/ctype.h>
43 #include <linux/file.h>
44 #include <linux/err.h>
45 #include "lcrash/klib.h"
46 #include "lcrash/kl_stringtab.h"
47 #include "lcrash/kl_btnode.h"
48 #include "lcrash/lc_eval.h"
49
50 MODULE_AUTHOR("SGI");
51 MODULE_DESCRIPTION("Load symbolic debugging information");
52 MODULE_LICENSE("GPL");
53
54 #undef next_node /* collision with nodemask.h */
55 static char     *stringstorage, **stringp_array;
56 static void     *filestorage;
57 static long     num_strings, num_kltypes, num_dsyms, stringstorage_size;
58 extern int      have_debug_file;
59 extern dbg_sym_t *types_tree_head;
60 extern dbg_sym_t *typedefs_tree_head;
61 extern kltype_t  *kltype_array;
62 extern dbg_sym_t *dsym_types_array;
63 extern dbg_sym_t *type_tree;
64 extern dbg_sym_t *typedef_tree;
65
66 /*
67  * use a pointer's value as an index in the stringp_array (num_strings) and
68  * translate it to string address
69  *
70  * Return 0 for success, 1 for failure
71  */
72 static int
73 index_to_char_ptr(char **ptrp)
74 {
75         long    i;
76
77         i = (long)*ptrp;
78         /* we use a value of -1 to mean this was a null pointer */
79         if (i == -1) {
80                 *ptrp = NULL;
81                 return 0;
82         }
83         if (i > num_strings-1) {
84                 printk("Could not translate character string index %#lx\n", i);
85                 return 1;
86         }
87         *ptrp = *(stringp_array+i);
88         return 0;
89 }
90
91 /*
92  * use a pointer's value as an index in the kltype_array (num_kltypes) and
93  * translate it to the kltype_t address
94  *
95  * return 0 for success, 1 for failure
96  */
97 static int
98 index_to_kltype_ptr(kltype_t **ptrp)
99 {
100         long    i;
101
102         i = (long)*ptrp;
103         /* we use a value of -1 to mean this was a null pointer */
104         if (i == -1) {
105                 *ptrp = NULL;
106                 return 0;
107         }
108         if (i > num_kltypes-1) {
109                 printk("Could not translate kl_type string index %#lx\n", i);
110                 return 1;
111         }
112         *ptrp = kltype_array+i;
113         return 0;
114 }
115
116 /*
117  * look up a pointer in the dsym_types_array (num_dsyms) and
118  * translate it to the index in the array
119  *
120  * return 0 for success, 1 for failure
121  */
122 static int
123 index_to_dbg_ptr(dbg_sym_t **ptrp)
124 {
125         long    i;
126
127         i = (long)*ptrp;
128         /* we use a value of -1 to mean this was a null pointer */
129         if (i == -1) {
130                 *ptrp = NULL;
131                 return 0;
132         }
133         if (i > num_dsyms-1) {
134                 printk("Could not translate dbg_sym_t index %#lx\n", i);
135                 return 1;
136         }
137         *ptrp = dsym_types_array+i;
138         return 0;
139 }
140
141
142 /*
143  * Work on the image of the file built by lcrash.
144  * Unpack the strings, and resolve the pointers in the arrays of kltype_t's
145  * and dbg_sym_t's to pointers.
146  *
147  * see lcrash's lib/libklib/kl_debug.c, which generates this file
148  *
149  * Return the pointers to the heads of the two binary trees by means of
150  * pointer arguments.
151  *
152  * Return 0 for sucess, 1 for any error.
153  */
154 static int
155 trans_file_image(void *file_storage, long file_size,  dbg_sym_t **type_treepp,
156                 dbg_sym_t **typedef_treepp)
157 {
158         int             len;
159         long            i, section_size, *lp, element_size;
160         long            head_types_tree, head_typedefs_tree;
161         char            *ptr, *stringsection, *kltypesection, *dbgsection;
162         void            *kltypestorage, *dbgstorage;
163         kltype_t        *klp;
164         dbg_sym_t       *dbgp;
165
166         /* 1) the strings */
167         lp = (long *)file_storage;
168         stringsection = (char *)lp;
169         section_size = *lp++;
170         num_strings = *lp++;
171         lp++; /* element size does not apply the strings section */
172
173         stringstorage_size = section_size - (3*sizeof(long));
174         stringstorage = (char *)lp;
175
176         stringp_array = (char **)vmalloc(num_strings * sizeof(char *));
177         if (! stringp_array) {
178                 printk("vmalloc of %ld string pointers failed\n", num_strings);
179                 return 1;
180         }
181         ptr = stringstorage;
182         for (i=0; i<num_strings; i++) {
183                 *(stringp_array+i) = ptr;
184                 len = strlen(ptr) + 1;
185                 ptr += len;
186         }
187
188         /* 2) the kltypes */
189         kltypesection = (char *)(stringsection + section_size);
190         lp = (long *)kltypesection;
191         section_size = *lp++;
192         num_kltypes = *lp++;
193         element_size = *lp++;
194         /* sanity check: */
195         if (element_size != sizeof(kltype_t)) {
196                 printk("size of kltype_t:%ld does not match\n", element_size);
197                 goto bad;
198         }
199         kltypestorage = (void *)lp;
200         kltype_array = (kltype_t *)kltypestorage;
201
202         /* 3) the dbg_sym_t's */
203         dbgsection = (char *)kltypesection + section_size;
204         lp = (long *)dbgsection;
205         section_size = *lp++;
206         /* sanity check: */
207         if ((dbgsection + section_size) != ((char *)file_storage+file_size)) {
208                 printk("dbg_sym_ts do not end at end of file\n");
209                 goto bad;
210         }
211         num_dsyms = *lp++;
212         element_size = *lp++;
213         /* sanity check: */
214         if (element_size != sizeof(dbg_sym_t)) {
215                 printk("kdb: size of dbg_sym_t does not match lkcd\'s\n");
216                 goto bad;
217         }
218
219         /* two special words ahead of the structures themselves */
220         head_types_tree = *lp++;
221         head_typedefs_tree = *lp++;
222
223         dbgstorage = (void *)lp;
224         dsym_types_array = (dbg_sym_t *)dbgstorage;
225
226         /* return the heads of the two binary trees */
227         *type_treepp = dsym_types_array+head_types_tree;
228         *typedef_treepp = dsym_types_array+head_typedefs_tree;
229
230         /* translate the indices in our our array of kltype_t's to pointers */
231         /*  (see write_kltype() for the fields that can be translated) */
232         klp = kltype_array;
233         for (i=0; i<num_kltypes; i++, klp++) {
234                 if (index_to_char_ptr(&klp->kl_name))
235                         goto bad;
236                 if (index_to_char_ptr(&klp->kl_typestr))
237                         goto bad;
238                 if (index_to_kltype_ptr(&klp->kl_member))
239                         goto bad;
240                 if (index_to_kltype_ptr(&klp->kl_next))
241                         goto bad;
242                 if (index_to_kltype_ptr(&klp->kl_realtype))
243                         goto bad;
244                 if (index_to_kltype_ptr(&klp->kl_indextype))
245                         goto bad;
246                 if (index_to_kltype_ptr(&klp->kl_elementtype))
247                         goto bad;
248                 if (index_to_dbg_ptr((dbg_sym_t **)&klp->kl_ptr))
249                         goto bad;
250         }
251
252         /* translate the indices in our our array of dbg_sym_t's to pointers */
253         /*  (see write_dbgtype() for the fields that can be translated) */
254         dbgp = dsym_types_array;
255         for (i=0; i<num_dsyms; i++, dbgp++) {
256                 if (index_to_char_ptr(&dbgp->sym_bt.bt_key))
257                         goto bad;
258                 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_left))
259                         goto bad;
260                 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_right))
261                         goto bad;
262                 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_parent))
263                         goto bad;
264                 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_next))
265                         goto bad;
266                 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_link))
267                         goto bad;
268                 if (index_to_kltype_ptr(&dbgp->sym_kltype))
269                         goto bad;
270         }
271
272         vfree(stringp_array);
273         return 0;
274 bad:
275         printk("trans_file_image() returning an error\n");
276         vfree(stringp_array);
277         return 1;
278 }
279
280 /* there is /proc interface to this string */
281 extern char kdb_debug_info_filename[];
282 /*
283  * This is the module initialization function.
284  */
285 static int __init
286 kdbm_debuginfo_init(void)
287 {
288         int             len;
289         long            ret, file_size;
290         ssize_t         sizeread;
291         mm_segment_t    fs;
292         struct file     *file;
293         loff_t          inode_size, pos;
294
295         len = strlen(kdb_debug_info_filename);
296         if (!len) {
297                 printk("kdb: no file name in /proc/kdb/debug_info_name\n");
298                 return -ENODEV;
299         }
300
301         fs = get_fs();     /* save previous value of address limits */
302         set_fs (get_ds()); /* use kernel limit */
303
304         file = filp_open(kdb_debug_info_filename, O_RDONLY, 0);
305         if (IS_ERR(file)) {
306                 set_fs(fs);
307                 printk (
308                   "kdb: open of %s (from /proc/kdb/debug_info_name) failed\n",
309                         kdb_debug_info_filename);
310                 return -ENODEV;
311         }
312         if (!file->f_op || (!file->f_op->read && !file->f_op->llseek)) {
313                 printk ("file has no operation for read or seek\n");
314                 set_fs(fs);
315                 return -ENODEV;
316         }
317         inode_size = file->f_dentry->d_inode->i_size;
318
319         /*
320          * File has a header word on it that contains the size of the
321          * file.  We don't need it, but can use it as a sanity check.
322          */
323         pos = 0;
324         sizeread = file->f_op->read(file, (char *)&file_size,
325                                         sizeof(file_size), &pos);
326         if (sizeread != sizeof(file_size)) {
327                 printk("could not read %d bytes from %s\n",
328                         (int)sizeof(file_size), kdb_debug_info_filename);
329                 ret = filp_close(file, NULL);
330                 set_fs(fs);
331                 return -ENODEV;
332         }
333         if (inode_size != file_size) {
334                 printk("file says %ld, inode says %lld\n",
335                                 file_size, inode_size);
336                 ret = filp_close(file, NULL);
337                 set_fs(fs);
338                 return -ENODEV;
339         }
340
341         /* space for the rest of the file: */
342         file_size -= sizeof(long);
343         filestorage = (void *)vmalloc(file_size);
344
345         pos = sizeof(file_size); /* position after the header word */
346         sizeread = file->f_op->read(file, (char *)filestorage,
347                                         file_size, &pos);
348         if (sizeread != file_size) {
349                 printk("could not read %ld bytes from %s\n",
350                         file_size, kdb_debug_info_filename);
351                 ret = filp_close(file, NULL);
352                 set_fs(fs);
353                 vfree (filestorage);
354                 return -ENODEV;
355         }
356
357         ret = filp_close(file, NULL);
358         set_fs(fs); /* restore address limits before returning to user space */
359
360         if (trans_file_image(filestorage, file_size, &types_tree_head,
361                                                      &typedefs_tree_head)){
362                 vfree (filestorage);
363                 return -ENODEV;
364         }
365         printk("kdbm_debuginfo loaded %s\n", kdb_debug_info_filename);
366         /* set the lcrash code's binary tree head nodes */
367         type_tree = types_tree_head;
368         typedef_tree = typedefs_tree_head;
369
370         have_debug_file = 1;
371
372         return 0;
373 }
374
375 /*
376  * This is the module exit function.
377  */
378 static void __exit
379 kdbm_debuginfo_exit(void)
380 {
381         printk("kdbm_debuginfo unloaded %s\n", kdb_debug_info_filename);
382         vfree (filestorage);
383         have_debug_file = 0;
384         return;
385 }
386
387 module_init(kdbm_debuginfo_init);
388 module_exit(kdbm_debuginfo_exit);