diff options
-rw-r--r-- | lib/libc/sys/kldstat.2 | 5 | ||||
-rw-r--r-- | sbin/kldstat/kldstat.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_linker.c | 45 | ||||
-rw-r--r-- | sys/sys/linker.h | 26 |
4 files changed, 71 insertions, 9 deletions
diff --git a/lib/libc/sys/kldstat.2 b/lib/libc/sys/kldstat.2 index 946417a..f2ca2a6 100644 --- a/lib/libc/sys/kldstat.2 +++ b/lib/libc/sys/kldstat.2 @@ -53,6 +53,7 @@ struct kld_file_stat { int id; caddr_t address; /* load address */ size_t size; /* size in bytes */ + char pathname[MAXPATHLEN]; }; .Ed .Pp @@ -77,6 +78,10 @@ The id of the file specified in The load address of the kld file. .It size The size of the file. +.It pathname +The full name of the file referred to by +.Fa fileid , +including the path. .El .Sh RETURN VALUES .Rv -std kldstat diff --git a/sbin/kldstat/kldstat.c b/sbin/kldstat/kldstat.c index 74f375e..4f4e786 100644 --- a/sbin/kldstat/kldstat.c +++ b/sbin/kldstat/kldstat.c @@ -60,9 +60,9 @@ static void printfile(int fileid, int verbose) if (kldstat(fileid, &stat) < 0) warn("can't stat file id %d", fileid); else - printf("%2d %4d %p %-8jx %s\n", + printf("%2d %4d %p %-8jx %s (%s)\n", stat.id, stat.refs, stat.address, (uintmax_t)stat.size, - stat.name); + stat.name, stat.pathname); if (verbose) { printf("\tContains modules:\n"); diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 7640334..324d349 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -97,6 +97,12 @@ linker_file_t linker_kernel_file; 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 @@ linker_make_file(const char *pathname, linker_class_t lc) 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 @@ linker_make_file(const char *pathname, linker_class_t lc) 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 @@ linker_file_unload(linker_file_t file, int flags) 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); } @@ -920,7 +934,13 @@ kern_kldunload(struct thread *td, int fileid, int flags) 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 +1061,18 @@ kldstat(struct thread *td, struct kldstat_args *uap) { 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 +1088,7 @@ kldstat(struct thread *td, struct kldstat_args *uap) return (ENOENT); } + /* Version 1 fields: */ namelen = strlen(lf->filename) + 1; if (namelen > MAXPATHLEN) namelen = MAXPATHLEN; @@ -1073,11 +1097,18 @@ kldstat(struct thread *td, struct kldstat_args *uap) 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; - return (copyout(&stat, uap->stat, sizeof(struct kld_file_stat))); + return (copyout(&stat, uap->stat, version)); } int diff --git a/sys/sys/linker.h b/sys/sys/linker.h index e35180a..83774e6 100644 --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -73,6 +73,7 @@ struct linker_file { #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 +82,18 @@ struct linker_file { 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; }; /* @@ -245,6 +258,18 @@ int elf_cpu_unload_file(linker_file_t); #define ELF_RELOC_REL 1 #define ELF_RELOC_RELA 2 +/* + * This is version 1 of the KLD file status structure. It is identified + * by it's _size_ in the version field. + */ +struct kld_file_stat_1 { + int version; /* set to sizeof(linker_file_stat) */ + char name[MAXPATHLEN]; + int refs; + int id; + caddr_t address; /* load address */ + size_t size; /* size in bytes */ +}; #endif /* _KERNEL */ struct kld_file_stat { @@ -254,6 +279,7 @@ struct kld_file_stat { int id; caddr_t address; /* load address */ size_t size; /* size in bytes */ + char pathname[MAXPATHLEN]; }; struct kld_sym_lookup { |