PERFORCE change 130927 for review

John Birrell jb at FreeBSD.org
Fri Dec 14 18:30:33 PST 2007


http://perforce.freebsd.org/chv.cgi?CH=130927

Change 130927 by jb at jb_freebsd1 on 2007/12/15 02:29:50

	MFdtrace

Affected files ...

.. //depot/projects/dtrace7/src/sys/kern/kern_linker.c#2 edit
.. //depot/projects/dtrace7/src/sys/kern/linker_if.m#2 edit
.. //depot/projects/dtrace7/src/sys/sys/linker.h#2 edit

Differences ...

==== //depot/projects/dtrace7/src/sys/kern/kern_linker.c#2 (text+ko) ====

@@ -97,6 +97,12 @@
 
 static struct sx kld_sx;	/* 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;
 static int next_file_id = 1;
@@ -534,7 +540,7 @@
 	KLD_LOCK_ASSERT();
 	filename = linker_basename(pathname);
 
-	KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
+	KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname));
 	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
 	if (lf == NULL)
 		return (NULL);
@@ -542,9 +548,13 @@
 	lf->userrefs = 0;
 	lf->flags = 0;
 	lf->filename = linker_strdup(filename);
+	lf->pathname = linker_strdup(pathname);
 	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);
 	TAILQ_INSERT_TAIL(&linker_files, lf, link);
@@ -629,6 +639,10 @@
 		free(file->filename, M_LINKER);
 		file->filename = NULL;
 	}
+	if (file->pathname) {
+		free(file->pathname, M_LINKER);
+		file->pathname = NULL;
+	}
 	kobj_delete((kobj_t) file, M_LINKER);
 	return (0);
 }
@@ -676,6 +690,16 @@
 	return (error);
 }
 
+/*
+ * List all functions in a file.
+ */
+int
+linker_file_function_listall(linker_file_t lf,
+    int (*callback_func)(linker_file_t, linker_symval_t *, void *), void *arg)
+{
+	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
+}
+
 caddr_t
 linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
 {
@@ -920,7 +944,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 ?
 			 */
@@ -1041,15 +1071,18 @@
 {
 	struct kld_file_stat stat;
 	linker_file_t lf;
-	int error, namelen;
+	int error, namelen, version, version_num;
 
 	/*
 	 * Check the version of the user's structure.
 	 */
-	error = copyin(uap->stat, &stat, sizeof(struct kld_file_stat));
-	if (error)
+	if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0)
 		return (error);
-	if (stat.version != sizeof(struct kld_file_stat))
+	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
@@ -1065,6 +1098,7 @@
 		return (ENOENT);
 	}
 
+	/* Version 1 fields: */
 	namelen = strlen(lf->filename) + 1;
 	if (namelen > MAXPATHLEN)
 		namelen = MAXPATHLEN;
@@ -1073,6 +1107,13 @@
 	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;
+		bcopy(lf->pathname, &stat.pathname[0], namelen);
+	}
 	KLD_UNLOCK();
 
 	td->td_retval[0] = 0;

==== //depot/projects/dtrace7/src/sys/kern/linker_if.m#2 (text+ko) ====

@@ -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.

==== //depot/projects/dtrace7/src/sys/sys/linker.h#2 (text+ko) ====

@@ -59,6 +59,8 @@
     size_t		size;
 } linker_symval_t;
 
+typedef int (*linker_function_nameval_callback_t)(linker_file_t, linker_symval_t *, void *);
+
 struct common_symbol {
     STAILQ_ENTRY(common_symbol) link;
     char*		name;
@@ -73,6 +75,7 @@
 #define LINKER_FILE_LINKED	0x1	/* file has been fully linked */
     TAILQ_ENTRY(linker_file) link;	/* list of all loaded files */
     char*		filename;	/* file which was loaded */
+    char*		pathname;	/* file name with full path */
     int			id;		/* unique id */
     caddr_t		address;	/* load address */
     size_t		size;		/* size of file */
@@ -81,6 +84,18 @@
     STAILQ_HEAD(, common_symbol) common; /* list of common symbols */
     TAILQ_HEAD(, module) modules;	/* modules in this file */
     TAILQ_ENTRY(linker_file) loaded;	/* preload dependency support */
+    int			loadcnt;	/* load counter value */
+
+    /*
+     * Function Boundary Tracing (FBT) or Statically Defined Tracing (SDT)
+     * fields.
+     */
+    int			nenabled;	/* number of enabled probes. */
+    int			fbt_nentries;	/* number of fbt entries created. */
+    void		*sdt_probes;
+    int			sdt_nentries;
+    size_t		sdt_nprobes;
+    size_t		sdt_size;
 };
 
 /*
@@ -141,6 +156,12 @@
 			   void *_start, void *_stop, int *_count);
 
 /*
+ * List all functions in a file.
+ */
+int linker_file_function_listall(linker_file_t, int (*)(linker_file_t,
+    linker_symval_t *, void *), void *);
+
+/*
  * Functions soley for use by the linker class handlers.
  */
 int linker_add_class(linker_class_t _cls);
@@ -245,15 +266,28 @@
 #define ELF_RELOC_REL	1
 #define ELF_RELOC_RELA	2
 
+/*
+ * This is version 1 of the KLD file status structure. It is identified
+ * by its _size_ in the version field.
+ */
+struct kld_file_stat_1 {
+    int		version;	/* set to sizeof(struct kld_file_stat_1) */
+    char        name[MAXPATHLEN];
+    int		refs;
+    int		id;
+    caddr_t	address;	/* load address */
+    size_t	size;		/* size in bytes */
+};
 #endif /* _KERNEL */
 
 struct kld_file_stat {
-    int		version;	/* set to sizeof(linker_file_stat) */
+    int		version;	/* set to sizeof(struct kld_file_stat) */
     char        name[MAXPATHLEN];
     int		refs;
     int		id;
     caddr_t	address;	/* load address */
     size_t	size;		/* size in bytes */
+    char        pathname[MAXPATHLEN];
 };
 
 struct kld_sym_lookup {


More information about the p4-projects mailing list