Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys o Fix a bug in ksyms that changed the real meaning of st...



details:   https://anonhg.NetBSD.org/src/rev/aa02ade3a63f
branches:  trunk
changeset: 555430:aa02ade3a63f
user:      cube <cube%NetBSD.org@localhost>
date:      Mon Nov 17 10:16:18 2003 +0000

description:
o Fix a bug in ksyms that changed the real meaning of st_name entries for
  symbols, and made it impossible for the kernel to use that value, and
  correctly find symbols from LKMs.
o Allow LKM users to use DDB to debug the entry function of a LKM by
  loading the symbol table with the temporary name /lkmtemp/ before calling
  it, and then renaming it once we know the module name.

Approved by ragge@.

diffstat:

 sys/ddb/db_sym.c      |  14 ++++++------
 sys/kern/kern_ksyms.c |  59 ++++++++++++++++++++++++++++++++++++++------------
 sys/kern/kern_lkm.c   |  30 +++++++++++++------------
 sys/sys/ksyms.h       |   7 ++++-
 4 files changed, 73 insertions(+), 37 deletions(-)

diffs (truncated from 318 to 300 lines):

diff -r a2a8bf6fe864 -r aa02ade3a63f sys/ddb/db_sym.c
--- a/sys/ddb/db_sym.c  Mon Nov 17 10:07:58 2003 +0000
+++ b/sys/ddb/db_sym.c  Mon Nov 17 10:16:18 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: db_sym.c,v 1.44 2003/10/25 08:54:01 christos Exp $     */
+/*     $NetBSD: db_sym.c,v 1.45 2003/11/17 10:16:18 cube Exp $ */
 
 /*
  * Mach Operating System
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_sym.c,v 1.44 2003/10/25 08:54:01 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_sym.c,v 1.45 2003/11/17 10:16:18 cube Exp $");
 
 #include "opt_ddbparam.h"
 
@@ -109,12 +109,12 @@
        }
 #endif
        db_symsplit(name, &mod, &sym);
-       if (ksyms_getval(mod, sym, &uval, KSYMS_EXTERN) == 0) {
+       if (ksyms_getval_from_kernel(mod, sym, &uval, KSYMS_EXTERN) == 0) {
                val = (long) uval;
                *valuep = (db_expr_t)val;
                return TRUE;
        }
-       if (ksyms_getval(mod, sym, &uval, KSYMS_ANY) == 0) {
+       if (ksyms_getval_from_kernel(mod, sym, &uval, KSYMS_ANY) == 0) {
                val = (long) uval;
                *valuep = (db_expr_t)val;
                return TRUE;
@@ -229,7 +229,7 @@
 #endif
 
        if (ksyms_getname(&mod, &sym, (vaddr_t)val, strategy) == 0) {
-               (void)ksyms_getval(mod, sym, &naddr, KSYMS_ANY);
+               (void)ksyms_getval_from_kernel(mod, sym, &naddr, KSYMS_ANY);
                diff = val - (db_addr_t)naddr;
                ret = (db_sym_t)naddr;
        } else
@@ -337,7 +337,7 @@
 #endif
        if (ksyms_getname(&mod, &name, (vaddr_t)off,
            strategy|KSYMS_CLOSEST) == 0) {
-               (void)ksyms_getval(mod, name, &val, KSYMS_ANY);
+               (void)ksyms_getval_from_kernel(mod, name, &val, KSYMS_ANY);
                if (((off - val) < db_maxoff) && val) {
                        sprintf(buf, "%s:%s", mod, name);
                        if (off - val) {
@@ -407,7 +407,7 @@
 #endif
        if (ksyms_getname(&mod, &name, (vaddr_t)off,
            strategy|KSYMS_CLOSEST) == 0) {
-               (void)ksyms_getval(mod, name, &uval, KSYMS_ANY);
+               (void)ksyms_getval_from_kernel(mod, name, &uval, KSYMS_ANY);
                val = (long) uval;
                if (((off - val) < db_maxoff) && val) {
                        (*pr)("%s:%s", mod, name);
diff -r a2a8bf6fe864 -r aa02ade3a63f sys/kern/kern_ksyms.c
--- a/sys/kern/kern_ksyms.c     Mon Nov 17 10:07:58 2003 +0000
+++ b/sys/kern/kern_ksyms.c     Mon Nov 17 10:16:18 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_ksyms.c,v 1.16 2003/11/06 18:22:01 ragge Exp $    */
+/*     $NetBSD: kern_ksyms.c,v 1.17 2003/11/17 10:16:18 cube Exp $     */
 /*
  * Copyright (c) 2001, 2003 Anders Magnusson (ragge%ludd.luth.se@localhost).
  * All rights reserved.
@@ -46,7 +46,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.16 2003/11/06 18:22:01 ragge Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.17 2003/11/17 10:16:18 cube Exp $");
 
 #ifdef _KERNEL
 #include "opt_ddb.h"
@@ -121,6 +121,7 @@
        const char *sd_name;    /* Name of this table */
        Elf_Sym *sd_symstart;   /* Address of symbol table */
        caddr_t sd_strstart;    /* Adderss of corresponding string table */
+       int sd_usroffset;       /* Real address for userspace */
        int sd_symsize;         /* Size in bytes of symbol table */
        int sd_strsize;         /* Size of string table */
        int *sd_symnmoff;       /* Used when calculating the name offset */
@@ -268,11 +269,12 @@
  * Finds a certain symbol name in a certain symbol table.
  */
 static Elf_Sym *
-findsym(char *name, struct symtab *table)
+findsym(char *name, struct symtab *table, int userreq)
 {
        Elf_Sym *start = table->sd_symstart;
        int i, sz = table->sd_symsize/sizeof(Elf_Sym);
        char *np;
+       caddr_t realstart = table->sd_strstart - (userreq ? 0 : table->sd_usroffset);
 
 #ifdef USE_PTREE
        if (table == &kernel_symtab && (i = ptree_find(name)) != 0)
@@ -280,7 +282,7 @@
 #endif
 
        for (i = 0; i < sz; i++) {
-               np = table->sd_strstart + start[i].st_name;
+               np = realstart + start[i].st_name;
                if (name[0] == np[0] && name[1] == np[1] &&
                    strcmp(name, np) == 0)
                        return &start[i];
@@ -495,7 +497,7 @@
  * Returns 0 if success or ENOENT if no such entry.
  */
 int
-ksyms_getval(const char *mod, char *sym, unsigned long *val, int type)
+ksyms_getval(const char *mod, char *sym, unsigned long *val, int type, int userreq)
 {
        struct symtab *st;
        Elf_Sym *es;
@@ -511,7 +513,7 @@
        CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
                if (mod && strcmp(st->sd_name, mod))
                        continue;
-               if ((es = findsym(sym, st)) == NULL)
+               if ((es = findsym(sym, st, userreq)) == NULL)
                        continue;
 
                /* Skip if bad binding */
@@ -563,7 +565,7 @@
                                laddr = les->st_value;
                                es = les;
                                lmod = st->sd_name;
-                               stable = st->sd_strstart;
+                               stable = st->sd_strstart - st->sd_usroffset;
                        }
                }
        }
@@ -593,10 +595,11 @@
                        for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++)
                                st->sd_symstart[i].st_name =
                                    strsz + st->sd_symnmoff[i];
+                       st->sd_usroffset = strsz;
                }
                 symsz += st->sd_symsize;
                 strsz += st->sd_strsize;
-        }                               
+        }
 }
 #endif
 
@@ -693,7 +696,7 @@
                        continue;
                        
                /* Check if the symbol exists */
-               if (ksyms_getval(NULL, strstart + sym[i].st_name,
+               if (ksyms_getval_from_kernel(NULL, strstart + sym[i].st_name,
                    &rval, KSYMS_EXTERN) == 0) {
                        /* Check (and complain) about differing values */
                        if (sym[i].st_value != rval) {
@@ -776,6 +779,31 @@
        return 0;
 }
 
+int
+ksyms_rensymtab(const char *old, const char *new)
+{
+       struct symtab *st, *oldst = NULL;
+       char *newstr;
+
+       CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
+               if (strcmp(old, st->sd_name) == 0)
+                       oldst = st;
+               if (strcmp(new, st->sd_name) == 0)
+                       return (EEXIST);
+       }
+       if (oldst == NULL)
+               return (ENOENT);
+
+       newstr = malloc(strlen(new)+1, M_DEVBUF, M_WAITOK);
+       if (!newstr)
+               return (ENOMEM);
+       strcpy(newstr, new);
+       free((char *)oldst->sd_name, M_DEVBUF);
+       oldst->sd_name = newstr;
+
+       return (0);
+}
+
 #ifdef DDB
 
 /*
@@ -801,7 +829,8 @@
                        Elf_Sym *les = st->sd_symstart + i;
                        char c;
 
-                       if (strstr(sb + les->st_name, sym) == NULL)
+                       if (strstr(sb + les->st_name - st->sd_usroffset, sym)
+                           == NULL)
                                continue;
 
                        if (mode == 'F') {
@@ -822,9 +851,11 @@
                                        c = ' ';
                                        break;
                                }
-                               db_printf("%s%c ", sb + les->st_name, c);
+                               db_printf("%s%c ", sb + les->st_name -
+                                   st->sd_usroffset, c);
                        } else
-                               db_printf("%s ", sb + les->st_name);
+                               db_printf("%s ", sb + les->st_name -
+                                   st->sd_usroffset);
                }
        }
        return ENOENT;
@@ -1033,7 +1064,7 @@
                 */
                if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL)))
                        break;
-               if ((error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN)))
+               if ((error = ksyms_getval_from_userland(NULL, str, &val, KSYMS_EXTERN)))
                        break;
                error = copyout(&val, kg->kg_value, sizeof(long));
                break;
@@ -1046,7 +1077,7 @@
                if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL)))
                        break;
                CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) {
-                       if ((sym = findsym(str, st)) == NULL)
+                       if ((sym = findsym(str, st, 1)) == NULL) /* from userland */
                                continue;
 
                        /* Skip if bad binding */
diff -r a2a8bf6fe864 -r aa02ade3a63f sys/kern/kern_lkm.c
--- a/sys/kern/kern_lkm.c       Mon Nov 17 10:07:58 2003 +0000
+++ b/sys/kern/kern_lkm.c       Mon Nov 17 10:16:18 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_lkm.c,v 1.69 2003/11/01 07:07:31 christos Exp $   */
+/*     $NetBSD: kern_lkm.c,v 1.70 2003/11/17 10:16:18 cube Exp $       */
 
 /*
  * Copyright (c) 1994 Christopher G. Demetriou
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lkm.c,v 1.69 2003/11/01 07:07:31 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lkm.c,v 1.70 2003/11/17 10:16:18 cube Exp $");
 
 #include "opt_ddb.h"
 #include "opt_malloclog.h"
@@ -413,11 +413,25 @@
                        memset((caddr_t)curp->area + curp->offset, 0,
                               curp->size - curp->offset);
 
+               if (curp->syms && curp->sym_offset >= curp->sym_size) {
+                       error = ksyms_addsymtab("/lkmtemp/",
+                           (char *)curp->syms, curp->sym_symsize,
+                           (char *)curp->syms + curp->sym_symsize,
+                           curp->sym_size - curp->sym_symsize);
+                       if (error)
+                               break;
+#ifdef DEBUG
+                       if (lkmdebug & LKMDB_INFO)
+                               printf( "DDB symbols added!\n" );
+#endif
+               }
+
                curp->entry = (int (*) __P((struct lkm_table *, int, int)))
                                (*((long *) (data)));
 
                /* call entry(load)... (assigns "private" portion) */
                error = (*(curp->entry))(curp, LKM_E_LOAD, LKM_VERSION);
+               (void)ksyms_rensymtab("/lkmtemp/", curp->private.lkm_any->lkm_name);
                if (error) {
                        /*
                         * Module may refuse loading or may have a
@@ -439,18 +453,6 @@
                if (lkmdebug & LKMDB_INFO)
                        printf("LKM: LMREADY\n");
 #endif /* DEBUG */
-               if (curp->syms && curp->sym_offset >= curp->sym_size) {
-                       error = ksyms_addsymtab(curp->private.lkm_any->lkm_name,
-                           (char *)curp->syms, curp->sym_symsize,
-                           (char *)curp->syms + curp->sym_symsize,
-                           curp->sym_size - curp->sym_symsize);
-                       if (error)
-                               break;
-#ifdef DEBUG
-                       if (lkmdebug & LKMDB_INFO)
-                               printf( "DDB symbols added!\n" );
-#endif
-               }
                lkm_state = LKMS_IDLE;
                break;
 
diff -r a2a8bf6fe864 -r aa02ade3a63f sys/sys/ksyms.h
--- a/sys/sys/ksyms.h   Mon Nov 17 10:07:58 2003 +0000
+++ b/sys/sys/ksyms.h   Mon Nov 17 10:16:18 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ksyms.h,v 1.7 2003/07/08 06:32:15 itojun Exp $ */



Home | Main Index | Thread Index | Old Index