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