* Make this file compile cleanly.
* Use FreeBSD's kld syscalls to get kernel module information instead of using an object file system like Solaris uses.
This commit is contained in:
parent
d9ce014461
commit
f1e56186ea
@ -26,15 +26,23 @@
|
|||||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#if defined(sun)
|
||||||
#include <sys/modctl.h>
|
#include <sys/modctl.h>
|
||||||
#include <sys/kobj.h>
|
#include <sys/kobj.h>
|
||||||
#include <sys/kobj_impl.h>
|
#include <sys/kobj_impl.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <sys/elf.h>
|
#include <sys/elf.h>
|
||||||
#include <sys/task.h>
|
#include <sys/task.h>
|
||||||
|
#else
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/linker.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#if defined(sun)
|
||||||
#include <project.h>
|
#include <project.h>
|
||||||
|
#endif
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
@ -42,6 +50,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#if !defined(sun)
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <dt_strtab.h>
|
#include <dt_strtab.h>
|
||||||
#include <dt_module.h>
|
#include <dt_module.h>
|
||||||
@ -66,7 +77,7 @@ dt_module_symhash_insert(dt_module_t *dmp, const char *name, uint_t id)
|
|||||||
static uint_t
|
static uint_t
|
||||||
dt_module_syminit32(dt_module_t *dmp)
|
dt_module_syminit32(dt_module_t *dmp)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *sym = dmp->dm_symtab.cts_data;
|
Elf32_Sym *sym = dmp->dm_symtab.cts_data;
|
||||||
const char *base = dmp->dm_strtab.cts_data;
|
const char *base = dmp->dm_strtab.cts_data;
|
||||||
size_t ss_size = dmp->dm_strtab.cts_size;
|
size_t ss_size = dmp->dm_strtab.cts_size;
|
||||||
uint_t i, n = dmp->dm_nsymelems;
|
uint_t i, n = dmp->dm_nsymelems;
|
||||||
@ -83,9 +94,14 @@ dt_module_syminit32(dt_module_t *dmp)
|
|||||||
continue; /* skip null or invalid names */
|
continue; /* skip null or invalid names */
|
||||||
|
|
||||||
if (sym->st_value != 0 &&
|
if (sym->st_value != 0 &&
|
||||||
(ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
|
(ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
|
||||||
asrsv++; /* reserve space in the address map */
|
asrsv++; /* reserve space in the address map */
|
||||||
|
|
||||||
|
#if !defined(sun)
|
||||||
|
sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
dt_module_symhash_insert(dmp, name, i);
|
dt_module_symhash_insert(dmp, name, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +111,7 @@ dt_module_syminit32(dt_module_t *dmp)
|
|||||||
static uint_t
|
static uint_t
|
||||||
dt_module_syminit64(dt_module_t *dmp)
|
dt_module_syminit64(dt_module_t *dmp)
|
||||||
{
|
{
|
||||||
const Elf64_Sym *sym = dmp->dm_symtab.cts_data;
|
Elf64_Sym *sym = dmp->dm_symtab.cts_data;
|
||||||
const char *base = dmp->dm_strtab.cts_data;
|
const char *base = dmp->dm_strtab.cts_data;
|
||||||
size_t ss_size = dmp->dm_strtab.cts_size;
|
size_t ss_size = dmp->dm_strtab.cts_size;
|
||||||
uint_t i, n = dmp->dm_nsymelems;
|
uint_t i, n = dmp->dm_nsymelems;
|
||||||
@ -112,9 +128,14 @@ dt_module_syminit64(dt_module_t *dmp)
|
|||||||
continue; /* skip null or invalid names */
|
continue; /* skip null or invalid names */
|
||||||
|
|
||||||
if (sym->st_value != 0 &&
|
if (sym->st_value != 0 &&
|
||||||
(ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
|
(ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
|
||||||
asrsv++; /* reserve space in the address map */
|
asrsv++; /* reserve space in the address map */
|
||||||
|
|
||||||
|
#if !defined(sun)
|
||||||
|
sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
dt_module_symhash_insert(dmp, name, i);
|
dt_module_symhash_insert(dmp, name, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +510,13 @@ dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
|
|||||||
if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
|
if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
#if defined(sun)
|
||||||
ctsp->cts_data = dp->d_buf;
|
ctsp->cts_data = dp->d_buf;
|
||||||
|
#else
|
||||||
|
if ((ctsp->cts_data = malloc(dp->d_size)) == NULL)
|
||||||
|
return (0);
|
||||||
|
memcpy(ctsp->cts_data, dp->d_buf, dp->d_size);
|
||||||
|
#endif
|
||||||
ctsp->cts_size = dp->d_size;
|
ctsp->cts_size = dp->d_size;
|
||||||
|
|
||||||
dt_dprintf("loaded %s [%s] (%lu bytes)\n",
|
dt_dprintf("loaded %s [%s] (%lu bytes)\n",
|
||||||
@ -665,6 +692,18 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
|||||||
ctf_close(dmp->dm_ctfp);
|
ctf_close(dmp->dm_ctfp);
|
||||||
dmp->dm_ctfp = NULL;
|
dmp->dm_ctfp = NULL;
|
||||||
|
|
||||||
|
#if !defined(sun)
|
||||||
|
if (dmp->dm_ctdata.cts_data != NULL) {
|
||||||
|
free(dmp->dm_ctdata.cts_data);
|
||||||
|
}
|
||||||
|
if (dmp->dm_symtab.cts_data != NULL) {
|
||||||
|
free(dmp->dm_symtab.cts_data);
|
||||||
|
}
|
||||||
|
if (dmp->dm_strtab.cts_data != NULL) {
|
||||||
|
free(dmp->dm_strtab.cts_data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
|
bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
|
||||||
bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
|
bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
|
||||||
bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
|
bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
|
||||||
@ -690,11 +729,11 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
|||||||
dmp->dm_asrsv = 0;
|
dmp->dm_asrsv = 0;
|
||||||
dmp->dm_aslen = 0;
|
dmp->dm_aslen = 0;
|
||||||
|
|
||||||
dmp->dm_text_va = NULL;
|
dmp->dm_text_va = 0;
|
||||||
dmp->dm_text_size = 0;
|
dmp->dm_text_size = 0;
|
||||||
dmp->dm_data_va = NULL;
|
dmp->dm_data_va = 0;
|
||||||
dmp->dm_data_size = 0;
|
dmp->dm_data_size = 0;
|
||||||
dmp->dm_bss_va = NULL;
|
dmp->dm_bss_va = 0;
|
||||||
dmp->dm_bss_size = 0;
|
dmp->dm_bss_size = 0;
|
||||||
|
|
||||||
if (dmp->dm_extern != NULL) {
|
if (dmp->dm_extern != NULL) {
|
||||||
@ -781,9 +820,16 @@ dt_module_modelname(dt_module_t *dmp)
|
|||||||
/*
|
/*
|
||||||
* Update our module cache by adding an entry for the specified module 'name'.
|
* Update our module cache by adding an entry for the specified module 'name'.
|
||||||
* We create the dt_module_t and populate it using /system/object/<name>/.
|
* We create the dt_module_t and populate it using /system/object/<name>/.
|
||||||
|
*
|
||||||
|
* On FreeBSD, the module name is passed as the full module file name,
|
||||||
|
* including the path.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
|
#if defined(sun)
|
||||||
dt_module_update(dtrace_hdl_t *dtp, const char *name)
|
dt_module_update(dtrace_hdl_t *dtp, const char *name)
|
||||||
|
#else
|
||||||
|
dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char fname[MAXPATHLEN];
|
char fname[MAXPATHLEN];
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
@ -796,8 +842,17 @@ dt_module_update(dtrace_hdl_t *dtp, const char *name)
|
|||||||
Elf_Data *dp;
|
Elf_Data *dp;
|
||||||
Elf_Scn *sp;
|
Elf_Scn *sp;
|
||||||
|
|
||||||
|
#if defined(sun)
|
||||||
(void) snprintf(fname, sizeof (fname),
|
(void) snprintf(fname, sizeof (fname),
|
||||||
"%s/%s/object", OBJFS_ROOT, name);
|
"%s/%s/object", OBJFS_ROOT, name);
|
||||||
|
#else
|
||||||
|
GElf_Phdr ph;
|
||||||
|
char name[MAXPATHLEN];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
(void) strlcpy(name, k_stat->name, sizeof(name));
|
||||||
|
(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
|
if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
|
||||||
(dmp = dt_module_create(dtp, name)) == NULL) {
|
(dmp = dt_module_create(dtp, name)) == NULL) {
|
||||||
@ -869,7 +924,23 @@ dt_module_update(dtrace_hdl_t *dtp, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dmp->dm_flags |= DT_DM_KERNEL;
|
dmp->dm_flags |= DT_DM_KERNEL;
|
||||||
|
#if defined(sun)
|
||||||
dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
|
dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
|
||||||
|
#else
|
||||||
|
#if defined(__i386__)
|
||||||
|
/*
|
||||||
|
* Find the first load section and figure out the relocation
|
||||||
|
* offset for the symbols. The kernel module will not need
|
||||||
|
* relocation, but the kernel linker modules will.
|
||||||
|
*/
|
||||||
|
for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) {
|
||||||
|
if (ph.p_type == PT_LOAD) {
|
||||||
|
dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dmp->dm_info.objfs_info_primary)
|
if (dmp->dm_info.objfs_info_primary)
|
||||||
dmp->dm_flags |= DT_DM_PRIMARY;
|
dmp->dm_flags |= DT_DM_PRIMARY;
|
||||||
@ -887,11 +958,15 @@ dtrace_update(dtrace_hdl_t *dtp)
|
|||||||
{
|
{
|
||||||
dt_module_t *dmp;
|
dt_module_t *dmp;
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
int fileid;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (dmp = dt_list_next(&dtp->dt_modlist);
|
for (dmp = dt_list_next(&dtp->dt_modlist);
|
||||||
dmp != NULL; dmp = dt_list_next(dmp))
|
dmp != NULL; dmp = dt_list_next(dmp))
|
||||||
dt_module_unload(dtp, dmp);
|
dt_module_unload(dtp, dmp);
|
||||||
|
|
||||||
|
#if defined(sun)
|
||||||
/*
|
/*
|
||||||
* Open /system/object and attempt to create a libdtrace module for
|
* Open /system/object and attempt to create a libdtrace module for
|
||||||
* each kernel module that is loaded on the current system.
|
* each kernel module that is loaded on the current system.
|
||||||
@ -907,6 +982,18 @@ dtrace_update(dtrace_hdl_t *dtp)
|
|||||||
|
|
||||||
(void) closedir(dirp);
|
(void) closedir(dirp);
|
||||||
}
|
}
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
/*
|
||||||
|
* Use FreeBSD's kernel loader interface to discover what kernel
|
||||||
|
* modules are loaded and create a libdtrace module for each one.
|
||||||
|
*/
|
||||||
|
for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
|
||||||
|
struct kld_file_stat k_stat;
|
||||||
|
k_stat.version = sizeof(k_stat);
|
||||||
|
if (kldstat(fileid, &k_stat) == 0)
|
||||||
|
dt_module_update(dtp, &k_stat);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up all the macro identifiers and set di_id to the latest value.
|
* Look up all the macro identifiers and set di_id to the latest value.
|
||||||
@ -919,9 +1006,13 @@ dtrace_update(dtrace_hdl_t *dtp)
|
|||||||
dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
|
dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
|
||||||
dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
|
dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
|
||||||
dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
|
dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
|
||||||
|
#if defined(sun)
|
||||||
dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
|
dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
|
||||||
|
#endif
|
||||||
dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
|
dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
|
||||||
|
#if defined(sun)
|
||||||
dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
|
dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
|
||||||
|
#endif
|
||||||
dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();
|
dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user