Date: Sat, 15 Dec 2007 02:30:32 GMT From: John Birrell <jb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 130927 for review Message-ID: <200712150230.lBF2UWc2094816@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=130927 Change 130927 by jb@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 {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712150230.lBF2UWc2094816>