Skip to content

Commit

Permalink
Add the full module path name to the kld_file_stat structure
Browse files Browse the repository at this point in the history
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
  • Loading branch information
John Birrell authored and John Birrell committed Oct 22, 2007
1 parent a3347b3 commit 1676805
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 9 deletions.
5 changes: 5 additions & 0 deletions lib/libc/sys/kldstat.2
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions sbin/kldstat/kldstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
45 changes: 38 additions & 7 deletions sys/kern/kern_linker.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -534,17 +540,21 @@ 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);
lf->refs = 1;
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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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 ?
*/
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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
Expand Down
26 changes: 26 additions & 0 deletions sys/sys/linker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
};

/*
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down

0 comments on commit 1676805

Please sign in to comment.