Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jun 2008 02:52:10 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 143149 for review
Message-ID:  <200806090252.m592qAv4048574@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=143149

Change 143149 by jb@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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200806090252.m592qAv4048574>