summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authorjb <jb@FreeBSD.org>2008-04-26 04:39:26 +0000
committerjb <jb@FreeBSD.org>2008-04-26 04:39:26 +0000
commitbefef11246d1f5c665de70ccbaf5b0cd9da68660 (patch)
tree3bed48c7f7bd5fe0d4da9b5a7816d7413b3ddadd /cddl
parent52ee64efcde2fb346f6e7d05f9e48d6258623f84 (diff)
downloadFreeBSD-src-befef11246d1f5c665de70ccbaf5b0cd9da68660.zip
FreeBSD-src-befef11246d1f5c665de70ccbaf5b0cd9da68660.tar.gz
* 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.
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c105
1 files changed, 98 insertions, 7 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
index 2519703..af17501 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
@@ -26,15 +26,23 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
+#if defined(sun)
#include <sys/modctl.h>
#include <sys/kobj.h>
#include <sys/kobj_impl.h>
#include <sys/sysmacros.h>
#include <sys/elf.h>
#include <sys/task.h>
+#else
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/stat.h>
+#endif
#include <unistd.h>
+#if defined(sun)
#include <project.h>
+#endif
#include <strings.h>
#include <stdlib.h>
#include <libelf.h>
@@ -42,6 +50,9 @@
#include <assert.h>
#include <errno.h>
#include <dirent.h>
+#if !defined(sun)
+#include <fcntl.h>
+#endif
#include <dt_strtab.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
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;
size_t ss_size = dmp->dm_strtab.cts_size;
uint_t i, n = dmp->dm_nsymelems;
@@ -83,9 +94,14 @@ dt_module_syminit32(dt_module_t *dmp)
continue; /* skip null or invalid names */
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 */
+#if !defined(sun)
+ sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
+#endif
+ }
+
dt_module_symhash_insert(dmp, name, i);
}
@@ -95,7 +111,7 @@ dt_module_syminit32(dt_module_t *dmp)
static uint_t
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;
size_t ss_size = dmp->dm_strtab.cts_size;
uint_t i, n = dmp->dm_nsymelems;
@@ -112,9 +128,14 @@ dt_module_syminit64(dt_module_t *dmp)
continue; /* skip null or invalid names */
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 */
+#if !defined(sun)
+ sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
+#endif
+ }
+
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)
return (0);
+#if defined(sun)
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;
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);
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_symtab, 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_aslen = 0;
- dmp->dm_text_va = NULL;
+ dmp->dm_text_va = 0;
dmp->dm_text_size = 0;
- dmp->dm_data_va = NULL;
+ dmp->dm_data_va = 0;
dmp->dm_data_size = 0;
- dmp->dm_bss_va = NULL;
+ dmp->dm_bss_va = 0;
dmp->dm_bss_size = 0;
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'.
* 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
+#if defined(sun)
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];
struct stat64 st;
@@ -796,8 +842,17 @@ dt_module_update(dtrace_hdl_t *dtp, const char *name)
Elf_Data *dp;
Elf_Scn *sp;
+#if defined(sun)
(void) snprintf(fname, sizeof (fname),
"%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 ||
(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;
+#if defined(sun)
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)
dmp->dm_flags |= DT_DM_PRIMARY;
@@ -887,11 +958,15 @@ dtrace_update(dtrace_hdl_t *dtp)
{
dt_module_t *dmp;
DIR *dirp;
+#if defined(__FreeBSD__)
+ int fileid;
+#endif
for (dmp = dt_list_next(&dtp->dt_modlist);
dmp != NULL; dmp = dt_list_next(dmp))
dt_module_unload(dtp, dmp);
+#if defined(sun)
/*
* Open /system/object and attempt to create a libdtrace module for
* each kernel module that is loaded on the current system.
@@ -907,6 +982,18 @@ dtrace_update(dtrace_hdl_t *dtp)
(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.
@@ -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, "pgid")->di_id = getpgid(0);
dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
+#if defined(sun)
dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
+#endif
dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
+#if defined(sun)
dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
+#endif
dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();
/*
OpenPOWER on IntegriCloud