* 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:
John Birrell 2008-04-26 04:39:26 +00:00
parent d9ce014461
commit f1e56186ea
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178559

View File

@ -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();
/*