Add the full module path name to the kld_file_stat structure
for kldstat(2). This allows libdtrace to determine the exact file from which a kernel module was loaded without having to guess. The kldstat(2) API is versioned with the size of the kld_file_stat structure, so this change creates version 2. Add the pathname to the verbose output of kldstat(8) too. MFC: 3 days
This commit is contained in:
parent
a3347b3e74
commit
1676805c18
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user