1 /* this one has some additional address validation - untested */
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
7 * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
12 * Most of this code is borrowed and adapted from the lkcd command "lcrash"
13 * and its supporting libarary.
15 * This module provides kdb commands for casting memory structures.
16 * It loads symbolic debugging info (provided from lcrash -o), and provides
18 * (this information originally comes from the lcrash "kerntypes" file)
20 * A key here is tacking a file of debug info onto this module, for
21 * load with it at insmod time.
23 * Careful of porting the klib KL_XXX functions (they call thru a jump table
24 * that we don't use here)
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
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>
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"
51 MODULE_DESCRIPTION("Load symbolic debugging information");
52 MODULE_LICENSE("GPL");
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;
67 * use a pointer's value as an index in the stringp_array (num_strings) and
68 * translate it to string address
70 * Return 0 for success, 1 for failure
73 index_to_char_ptr(char **ptrp)
78 /* we use a value of -1 to mean this was a null pointer */
83 if (i > num_strings-1) {
84 printk("Could not translate character string index %#lx\n", i);
87 *ptrp = *(stringp_array+i);
92 * use a pointer's value as an index in the kltype_array (num_kltypes) and
93 * translate it to the kltype_t address
95 * return 0 for success, 1 for failure
98 index_to_kltype_ptr(kltype_t **ptrp)
103 /* we use a value of -1 to mean this was a null pointer */
108 if (i > num_kltypes-1) {
109 printk("Could not translate kl_type string index %#lx\n", i);
112 *ptrp = kltype_array+i;
117 * look up a pointer in the dsym_types_array (num_dsyms) and
118 * translate it to the index in the array
120 * return 0 for success, 1 for failure
123 index_to_dbg_ptr(dbg_sym_t **ptrp)
128 /* we use a value of -1 to mean this was a null pointer */
133 if (i > num_dsyms-1) {
134 printk("Could not translate dbg_sym_t index %#lx\n", i);
137 *ptrp = dsym_types_array+i;
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.
147 * see lcrash's lib/libklib/kl_debug.c, which generates this file
149 * Return the pointers to the heads of the two binary trees by means of
152 * Return 0 for sucess, 1 for any error.
155 trans_file_image(void *file_storage, long file_size, dbg_sym_t **type_treepp,
156 dbg_sym_t **typedef_treepp)
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;
167 lp = (long *)file_storage;
168 stringsection = (char *)lp;
169 section_size = *lp++;
171 lp++; /* element size does not apply the strings section */
173 stringstorage_size = section_size - (3*sizeof(long));
174 stringstorage = (char *)lp;
176 stringp_array = (char **)vmalloc(num_strings * sizeof(char *));
177 if (! stringp_array) {
178 printk("vmalloc of %ld string pointers failed\n", num_strings);
182 for (i=0; i<num_strings; i++) {
183 *(stringp_array+i) = ptr;
184 len = strlen(ptr) + 1;
189 kltypesection = (char *)(stringsection + section_size);
190 lp = (long *)kltypesection;
191 section_size = *lp++;
193 element_size = *lp++;
195 if (element_size != sizeof(kltype_t)) {
196 printk("size of kltype_t:%ld does not match\n", element_size);
199 kltypestorage = (void *)lp;
200 kltype_array = (kltype_t *)kltypestorage;
202 /* 3) the dbg_sym_t's */
203 dbgsection = (char *)kltypesection + section_size;
204 lp = (long *)dbgsection;
205 section_size = *lp++;
207 if ((dbgsection + section_size) != ((char *)file_storage+file_size)) {
208 printk("dbg_sym_ts do not end at end of file\n");
212 element_size = *lp++;
214 if (element_size != sizeof(dbg_sym_t)) {
215 printk("kdb: size of dbg_sym_t does not match lkcd\'s\n");
219 /* two special words ahead of the structures themselves */
220 head_types_tree = *lp++;
221 head_typedefs_tree = *lp++;
223 dbgstorage = (void *)lp;
224 dsym_types_array = (dbg_sym_t *)dbgstorage;
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;
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) */
233 for (i=0; i<num_kltypes; i++, klp++) {
234 if (index_to_char_ptr(&klp->kl_name))
236 if (index_to_char_ptr(&klp->kl_typestr))
238 if (index_to_kltype_ptr(&klp->kl_member))
240 if (index_to_kltype_ptr(&klp->kl_next))
242 if (index_to_kltype_ptr(&klp->kl_realtype))
244 if (index_to_kltype_ptr(&klp->kl_indextype))
246 if (index_to_kltype_ptr(&klp->kl_elementtype))
248 if (index_to_dbg_ptr((dbg_sym_t **)&klp->kl_ptr))
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))
258 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_left))
260 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_right))
262 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_parent))
264 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_next))
266 if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_link))
268 if (index_to_kltype_ptr(&dbgp->sym_kltype))
272 vfree(stringp_array);
275 printk("trans_file_image() returning an error\n");
276 vfree(stringp_array);
280 /* there is /proc interface to this string */
281 extern char kdb_debug_info_filename[];
283 * This is the module initialization function.
286 kdbm_debuginfo_init(void)
293 loff_t inode_size, pos;
295 len = strlen(kdb_debug_info_filename);
297 printk("kdb: no file name in /proc/kdb/debug_info_name\n");
301 fs = get_fs(); /* save previous value of address limits */
302 set_fs (get_ds()); /* use kernel limit */
304 file = filp_open(kdb_debug_info_filename, O_RDONLY, 0);
308 "kdb: open of %s (from /proc/kdb/debug_info_name) failed\n",
309 kdb_debug_info_filename);
312 if (!file->f_op || (!file->f_op->read && !file->f_op->llseek)) {
313 printk ("file has no operation for read or seek\n");
317 inode_size = file->f_dentry->d_inode->i_size;
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.
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);
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);
341 /* space for the rest of the file: */
342 file_size -= sizeof(long);
343 filestorage = (void *)vmalloc(file_size);
345 pos = sizeof(file_size); /* position after the header word */
346 sizeread = file->f_op->read(file, (char *)filestorage,
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);
357 ret = filp_close(file, NULL);
358 set_fs(fs); /* restore address limits before returning to user space */
360 if (trans_file_image(filestorage, file_size, &types_tree_head,
361 &typedefs_tree_head)){
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;
376 * This is the module exit function.
379 kdbm_debuginfo_exit(void)
381 printk("kdbm_debuginfo unloaded %s\n", kdb_debug_info_filename);
387 module_init(kdbm_debuginfo_init);
388 module_exit(kdbm_debuginfo_exit);