PERFORCE change 143149 for review
John Birrell
jb at FreeBSD.org
Mon Jun 9 02:52:11 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=143149
Change 143149 by jb at freebsd3 on 2008/06/09 02:51:12
Add the linker method for the DTrace kernel modules.
Affected files ...
.. //depot/projects/dtrace6/src/sys/kern/kern_linker.c#4 edit
.. //depot/projects/dtrace6/src/sys/kern/linker_if.m#2 edit
.. //depot/projects/dtrace6/src/sys/sys/linker.h#5 edit
Differences ...
==== //depot/projects/dtrace6/src/sys/kern/kern_linker.c#4 (text+ko) ====
@@ -68,7 +68,13 @@
linker_file_t linker_kernel_file;
-static struct mtx kld_mtx; /* kernel linker mutex */
+static struct mtx kld_mtx; /* kernel linker lock */
+
+/*
+ * Load counter used by clients to determine if a linker file has been
+ * re-loaded. This counter is incremented for each file load.
+ */
+static int loadcnt;
static linker_class_list_t classes;
static linker_file_list_t linker_files;
@@ -475,6 +481,22 @@
return (lf);
}
+int
+linker_file_foreach(linker_predicate_t *predicate, void *context)
+{
+ linker_file_t lf;
+ int retval = 0;
+
+ mtx_lock(&kld_mtx);
+ TAILQ_FOREACH(lf, &linker_files, link) {
+ retval = predicate(lf, context);
+ if (retval != 0)
+ break;
+ }
+ mtx_unlock(&kld_mtx);
+ return (retval);
+}
+
linker_file_t
linker_make_file(const char *pathname, linker_class_t lc)
{
@@ -496,6 +518,9 @@
LINKER_GET_NEXT_FILE_ID(lf->id);
lf->ndeps = 0;
lf->deps = NULL;
+ lf->loadcnt = ++loadcnt;
+ lf->sdt_probes = NULL;
+ lf->sdt_nprobes = 0;
STAILQ_INIT(&lf->common);
TAILQ_INIT(&lf->modules);
mtx_lock(&kld_mtx);
@@ -601,6 +626,12 @@
}
int
+linker_ctf_get(linker_file_t file, linker_ctf_t *lc)
+{
+ return (LINKER_CTF_GET(file, lc));
+}
+
+int
linker_file_add_dependency(linker_file_t file, linker_file_t dep)
{
linker_file_t *newdeps;
@@ -629,8 +660,17 @@
linker_file_lookup_set(linker_file_t file, const char *name,
void *firstp, void *lastp, int *countp)
{
+ return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
+}
- return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
+/*
+ * List all functions in a file.
+ */
+int
+linker_file_function_listall(linker_file_t lf,
+ linker_function_nameval_callback_t callback_func, void *arg)
+{
+ return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
}
caddr_t
@@ -850,7 +890,13 @@
lf = linker_find_file_by_id(fileid);
if (lf) {
KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
- if (lf->userrefs == 0) {
+
+ /* Check if there are DTrace probes enabled on this file. */
+ if (lf->nenabled > 0) {
+ printf("kldunload: attempt to unload file that has"
+ " DTrace probes enabled\n");
+ error = EBUSY;
+ } else if (lf->userrefs == 0) {
/*
* XXX: maybe LINKER_UNLOAD_FORCE should override ?
*/
@@ -975,10 +1021,21 @@
int
kldstat(struct thread *td, struct kldstat_args *uap)
{
+ struct kld_file_stat stat;
linker_file_t lf;
- int error = 0;
- int namelen, version, version_num;
- struct kld_file_stat *stat;
+ int error, namelen, version, version_num;
+
+ /*
+ * Check the version of the user's structure.
+ */
+ if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0)
+ return (error);
+ if (version == sizeof(struct kld_file_stat_1))
+ version_num = 1;
+ else if (version == sizeof(struct kld_file_stat))
+ version_num = 2;
+ else
+ return (EINVAL);
#ifdef MAC
error = mac_check_kld_stat(td->td_ucred);
@@ -987,57 +1044,33 @@
#endif
mtx_lock(&Giant);
-
lf = linker_find_file_by_id(uap->fileid);
if (lf == NULL) {
- error = ENOENT;
- goto out;
+ mtx_unlock(&Giant);
+ return (ENOENT);
}
- stat = uap->stat;
- /*
- * Check the version of the user's structure.
- */
- if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
- goto out;
- if (version == sizeof(struct kld_file_stat_1))
- version_num = 1;
- else if (version == sizeof(struct kld_file_stat))
- version_num = 2;
- else {
- error = EINVAL;
- goto out;
- }
-
/* Version 1 fields: */
namelen = strlen(lf->filename) + 1;
if (namelen > MAXPATHLEN)
namelen = MAXPATHLEN;
- if ((error = copyout(lf->filename, &stat->name[0], namelen)) != 0)
- goto out;
- if ((error = copyout(&lf->refs, &stat->refs, sizeof(int))) != 0)
- goto out;
- if ((error = copyout(&lf->id, &stat->id, sizeof(int))) != 0)
- goto out;
- if ((error = copyout(&lf->address, &stat->address,
- sizeof(caddr_t))) != 0)
- goto out;
- if ((error = copyout(&lf->size, &stat->size, sizeof(size_t))) != 0)
- goto out;
+ bcopy(lf->filename, &stat.name[0], namelen);
+ stat.refs = lf->refs;
+ stat.id = lf->id;
+ stat.address = lf->address;
+ stat.size = lf->size;
if (version_num > 1) {
/* Version 2 fields: */
namelen = strlen(lf->pathname) + 1;
if (namelen > MAXPATHLEN)
namelen = MAXPATHLEN;
- if ((error = copyout(lf->pathname, &stat->pathname[0],
- namelen)) != 0)
- goto out;
+ bcopy(lf->pathname, &stat.pathname[0], namelen);
}
+ mtx_unlock(&Giant);
td->td_retval[0] = 0;
-out:
- mtx_unlock(&Giant);
- return (error);
+
+ return (copyout(&stat, uap->stat, sizeof(struct kld_file_stat)));
}
/*
==== //depot/projects/dtrace6/src/sys/kern/linker_if.m#2 (text+ko) ====
@@ -23,7 +23,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD: src/sys/kern/linker_if.m,v 1.6 2005/01/06 23:35:39 imp Exp $
+# $FreeBSD: src/sys/kern/linker_if.m,v 1.8 2008/05/23 04:06:49 jb Exp $
#
#include <sys/linker.h>
@@ -64,6 +64,17 @@
};
#
+# Call the callback with each specified function and it's value
+# defined in the file.
+# Stop and return the error if the callback returns an error.
+#
+METHOD int each_function_nameval {
+ linker_file_t file;
+ linker_function_nameval_callback_t callback;
+ void* opaque;
+};
+
+#
# Search for a linker set in a file. Return a pointer to the first
# entry (which is itself a pointer), and the number of entries.
# "stop" points to the entry beyond the last valid entry.
@@ -85,6 +96,15 @@
};
#
+# Load CTF data if necessary and if there is a .SUNW_ctf section
+# in the ELF file, returning info in the linker CTF structure.
+#
+METHOD int ctf_get {
+ linker_file_t file;
+ linker_ctf_t *lc;
+};
+
+#
# Load a file, returning the new linker_file_t in *result. If
# the class does not recognise the file type, zero should be
# returned, without modifying *result. If the file is
==== //depot/projects/dtrace6/src/sys/sys/linker.h#5 (text+ko) ====
@@ -59,6 +59,8 @@
size_t size;
} linker_symval_t;
+typedef int (*linker_function_nameval_callback_t)(linker_file_t, int, linker_symval_t *, void *);
+
struct common_symbol {
STAILQ_ENTRY(common_symbol) link;
char* name;
@@ -113,6 +115,11 @@
extern linker_file_t linker_kernel_file;
/*
+ * Function type used when iterating over the list of linker files.
+ */
+typedef int linker_predicate_t(linker_file_t, void *);
+
+/*
* Add a new file class to the linker.
*/
int linker_add_class(linker_class_t _cls);
@@ -139,6 +146,13 @@
linker_file_t _file);
/*
+ * Iterate over all of the currently loaded linker files calling the
+ * predicate function while the function returns 0. Returns the value
+ * returned by the last predicate function.
+ */
+int linker_file_foreach(linker_predicate_t *_predicate, void *_context);
+
+/*
* Find a currently loaded file given its filename.
*/
linker_file_t linker_find_file_by_name(const char* _filename);
@@ -171,6 +185,12 @@
int _deps);
/*
+ * List all functions in a file.
+ */
+int linker_file_function_listall(linker_file_t,
+ linker_function_nameval_callback_t, void *);
+
+/*
* Lookup a linker set in a file. Return pointers to the first entry,
* last + 1, and count of entries. Use: for (p = start; p < stop; p++) {}
* void *start is really: "struct yoursetmember ***start;"
@@ -271,6 +291,20 @@
const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx);
const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx);
+typedef struct linker_ctf {
+ const uint8_t *ctftab; /* Decompressed CTF data. */
+ int ctfcnt; /* Number of CTF data bytes. */
+ const Elf_Sym *symtab; /* Ptr to the symbol table. */
+ int nsym; /* Number of symbols. */
+ const char *strtab; /* Ptr to the string table. */
+ int strcnt; /* Number of string bytes. */
+ uint32_t **ctfoffp; /* Ptr to array of obj/fnc offsets. */
+ uint32_t **typoffp; /* Ptr to array of type offsets. */
+ long *typlenp; /* Ptr to number of type data entries. */
+} linker_ctf_t;
+
+int linker_ctf_get(linker_file_t, linker_ctf_t *);
+
int elf_cpu_load_file(linker_file_t);
int elf_cpu_unload_file(linker_file_t);
More information about the p4-projects
mailing list