summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_linker.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-12-01 19:24:28 +0000
committerrwatson <rwatson@FreeBSD.org>2007-12-01 19:24:28 +0000
commit0ab794a171ac6568b244e0f424efa9bcf4eb25a1 (patch)
tree49ec045f2a807b5eb7974c2cc2171f8195ac1b06 /sys/kern/kern_linker.c
parent8df55e4f8662732d62efb9b039f3d1863a0a2266 (diff)
downloadFreeBSD-src-0ab794a171ac6568b244e0f424efa9bcf4eb25a1.zip
FreeBSD-src-0ab794a171ac6568b244e0f424efa9bcf4eb25a1.tar.gz
The kernel linker includes a number of utility functions to look up symbol
information in support of DDB(4); these functions bypass normal linker locking as they may run in contexts where locking is unsafe (such as the kernel debugger). Add a new interface linker_ddb_search_symbol_name(), which looks up a symbol name and offset given an address, and also linker_search_symbol_name() which does the same but *does* follow the locking conventions of the linker. Unlike existing functions, these functions place the name in a caller-provided buffer, which is stable even after linker locks have been released. These functions will be used in upcoming revisions to stack(9) to support kernel stack trace generation in contexts as part of a live, rather than suspended, kernel.
Diffstat (limited to 'sys/kern/kern_linker.c')
-rw-r--r--sys/kern/kern_linker.c100
1 files changed, 87 insertions, 13 deletions
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 321436d..93166a1 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -791,18 +791,18 @@ linker_file_lookup_symbol_internal(linker_file_t file, const char *name,
return (0);
}
-#ifdef DDB
/*
- * DDB Helpers. DDB has to look across multiple files with their own symbol
- * tables and string tables.
+ * Both DDB and stack(9) rely on the kernel linker to provide forward and
+ * backward lookup of symbols. However, DDB and sometimes stack(9) need to
+ * do this in a lockfree manner. We provide a set of internal helper
+ * routines to perform these operations without locks, and then wrappers that
+ * optionally lock.
*
- * Note that we do not obey list locking protocols here. We really don't need
- * DDB to hang because somebody's got the lock held. We'll take the chance
- * that the files list is inconsistant instead.
+ * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB.
*/
-
-int
-linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
+#ifdef DDB
+static int
+linker_debug_lookup(const char *symstr, c_linker_sym_t *sym)
{
linker_file_t lf;
@@ -812,9 +812,10 @@ linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
}
return (ENOENT);
}
+#endif
-int
-linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
+static int
+linker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
{
linker_file_t lf;
c_linker_sym_t best, es;
@@ -844,8 +845,8 @@ linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
}
}
-int
-linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
+static int
+linker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
{
linker_file_t lf;
@@ -855,9 +856,82 @@ linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
}
return (ENOENT);
}
+
+static int
+linker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen,
+ long *offset)
+{
+ linker_symval_t symval;
+ c_linker_sym_t sym;
+ int error;
+
+ *offset = 0;
+ error = linker_debug_search_symbol(value, &sym, offset);
+ if (error)
+ return (error);
+ error = linker_debug_symbol_values(sym, &symval);
+ if (error)
+ return (error);
+ strlcpy(buf, symval.name, buflen);
+ return (0);
+}
+
+#ifdef DDB
+/*
+ * DDB Helpers. DDB has to look across multiple files with their own symbol
+ * tables and string tables.
+ *
+ * Note that we do not obey list locking protocols here. We really don't need
+ * DDB to hang because somebody's got the lock held. We'll take the chance
+ * that the files list is inconsistant instead.
+ */
+int
+linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym)
+{
+
+ return (linker_debug_lookup(symstr, sym));
+}
+
+int
+linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
+{
+
+ return (linker_debug_search_symbol(value, sym, diffp));
+}
+
+int
+linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
+{
+
+ return (linker_debug_symbol_values(sym, symval));
+}
+
+int
+linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
+ long *offset)
+{
+
+ return (linker_debug_search_symbol_name(value, buf, buflen, offset));
+}
#endif
/*
+ * stack(9) helper for non-debugging environemnts. Unlike DDB helpers, we do
+ * obey locking protocols, and offer a significantly less complex interface.
+ */
+int
+linker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
+ long *offset)
+{
+ int error;
+
+ KLD_LOCK();
+ error = linker_debug_search_symbol_name(value, buf, buflen, offset);
+ KLD_UNLOCK();
+ return (error);
+}
+
+/*
* Syscalls.
*/
int
OpenPOWER on IntegriCloud