⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dt_module.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)dt_module.c	1.8	04/11/22 SMI"#include <sys/types.h>#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>#include <unistd.h>#include <project.h>#include <strings.h>#include <stdlib.h>#include <libelf.h>#include <limits.h>#include <assert.h>#include <errno.h>#include <alloca.h>#define	_POSIX_PTHREAD_SEMANTICS#include <dirent.h>#undef	_POSIX_PTHREAD_SEMANTICS#include <dt_strtab.h>#include <dt_module.h>#include <dt_impl.h>static const char *dt_module_strtab; /* active strtab for qsort callbacks */static voiddt_module_symhash_insert(dt_module_t *dmp, const char *name, uint_t id){	dt_sym_t *dsp = &dmp->dm_symchains[dmp->dm_symfree];	uint_t h;	assert(dmp->dm_symfree < dmp->dm_nsymelems + 1);	dsp->ds_symid = id;	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;	dsp->ds_next = dmp->dm_symbuckets[h];	dmp->dm_symbuckets[h] = dmp->dm_symfree++;}static uint_tdt_module_syminit32(dt_module_t *dmp){	const 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;	uint_t asrsv = 0;	for (i = 0; i < n; i++, sym++) {		const char *name = base + sym->st_name;		uchar_t type = ELF32_ST_TYPE(sym->st_info);		if (type >= STT_NUM || type == STT_SECTION)			continue; /* skip sections and unknown types */		if (sym->st_name == 0 || sym->st_name >= ss_size)			continue; /* skip null or invalid names */		if (sym->st_value != 0 &&		    (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))			asrsv++; /* reserve space in the address map */		dt_module_symhash_insert(dmp, name, i);	}	return (asrsv);}static uint_tdt_module_syminit64(dt_module_t *dmp){	const 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;	uint_t asrsv = 0;	for (i = 0; i < n; i++, sym++) {		const char *name = base + sym->st_name;		uchar_t type = ELF64_ST_TYPE(sym->st_info);		if (type >= STT_NUM || type == STT_SECTION)			continue; /* skip sections and unknown types */		if (sym->st_name == 0 || sym->st_name >= ss_size)			continue; /* skip null or invalid names */		if (sym->st_value != 0 &&		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))			asrsv++; /* reserve space in the address map */		dt_module_symhash_insert(dmp, name, i);	}	return (asrsv);}/* * Sort comparison function for 32-bit symbol address-to-name lookups.  We sort * symbols by value.  If values are equal, we prefer the symbol that is * non-zero sized, typed, not weak, or lexically first, in that order. */static intdt_module_symcomp32(const void *lp, const void *rp){	Elf32_Sym *lhs = *((Elf32_Sym **)lp);	Elf32_Sym *rhs = *((Elf32_Sym **)rp);	if (lhs->st_value != rhs->st_value)		return (lhs->st_value > rhs->st_value ? 1 : -1);	if ((lhs->st_size == 0) != (rhs->st_size == 0))		return (lhs->st_size == 0 ? 1 : -1);	if ((ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=	    (ELF32_ST_TYPE(rhs->st_info) == STT_NOTYPE))		return (ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);	if ((ELF32_ST_BIND(lhs->st_info) == STB_WEAK) !=	    (ELF32_ST_BIND(rhs->st_info) == STB_WEAK))		return (ELF32_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);	return (strcmp(dt_module_strtab + lhs->st_name,	    dt_module_strtab + rhs->st_name));}/* * Sort comparison function for 64-bit symbol address-to-name lookups.  We sort * symbols by value.  If values are equal, we prefer the symbol that is * non-zero sized, typed, not weak, or lexically first, in that order. */static intdt_module_symcomp64(const void *lp, const void *rp){	Elf64_Sym *lhs = *((Elf64_Sym **)lp);	Elf64_Sym *rhs = *((Elf64_Sym **)rp);	if (lhs->st_value != rhs->st_value)		return (lhs->st_value > rhs->st_value ? 1 : -1);	if ((lhs->st_size == 0) != (rhs->st_size == 0))		return (lhs->st_size == 0 ? 1 : -1);	if ((ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=	    (ELF64_ST_TYPE(rhs->st_info) == STT_NOTYPE))		return (ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);	if ((ELF64_ST_BIND(lhs->st_info) == STB_WEAK) !=	    (ELF64_ST_BIND(rhs->st_info) == STB_WEAK))		return (ELF64_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);	return (strcmp(dt_module_strtab + lhs->st_name,	    dt_module_strtab + rhs->st_name));}static voiddt_module_symsort32(dt_module_t *dmp){	Elf32_Sym *symtab = (Elf32_Sym *)dmp->dm_symtab.cts_data;	Elf32_Sym **sympp = (Elf32_Sym **)dmp->dm_asmap;	const dt_sym_t *dsp = dmp->dm_symchains + 1;	uint_t i, n = dmp->dm_symfree;	for (i = 1; i < n; i++, dsp++) {		Elf32_Sym *sym = symtab + dsp->ds_symid;		if (sym->st_value != 0 &&		    (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))			*sympp++ = sym;	}	dmp->dm_aslen = (uint_t)(sympp - (Elf32_Sym **)dmp->dm_asmap);	assert(dmp->dm_aslen <= dmp->dm_asrsv);	dt_module_strtab = dmp->dm_strtab.cts_data;	qsort(dmp->dm_asmap, dmp->dm_aslen,	    sizeof (Elf32_Sym *), dt_module_symcomp32);	dt_module_strtab = NULL;}static voiddt_module_symsort64(dt_module_t *dmp){	Elf64_Sym *symtab = (Elf64_Sym *)dmp->dm_symtab.cts_data;	Elf64_Sym **sympp = (Elf64_Sym **)dmp->dm_asmap;	const dt_sym_t *dsp = dmp->dm_symchains + 1;	uint_t i, n = dmp->dm_symfree;	for (i = 1; i < n; i++, dsp++) {		Elf64_Sym *sym = symtab + dsp->ds_symid;		if (sym->st_value != 0 &&		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))			*sympp++ = sym;	}	dmp->dm_aslen = (uint_t)(sympp - (Elf64_Sym **)dmp->dm_asmap);	assert(dmp->dm_aslen <= dmp->dm_asrsv);	dt_module_strtab = dmp->dm_strtab.cts_data;	qsort(dmp->dm_asmap, dmp->dm_aslen,	    sizeof (Elf64_Sym *), dt_module_symcomp64);	dt_module_strtab = NULL;}static GElf_Sym *dt_module_symgelf32(const Elf32_Sym *src, GElf_Sym *dst){	if (dst != NULL) {		dst->st_name = src->st_name;		dst->st_info = src->st_info;		dst->st_other = src->st_other;		dst->st_shndx = src->st_shndx;		dst->st_value = src->st_value;		dst->st_size = src->st_size;	}	return (dst);}static GElf_Sym *dt_module_symgelf64(const Elf64_Sym *src, GElf_Sym *dst){	if (dst != NULL)		bcopy(src, dst, sizeof (GElf_Sym));	return (dst);}static GElf_Sym *dt_module_symname32(dt_module_t *dmp, const char *name,    GElf_Sym *symp, uint_t *idp){	const Elf32_Sym *symtab = dmp->dm_symtab.cts_data;	const char *strtab = dmp->dm_strtab.cts_data;	const Elf32_Sym *sym;	const dt_sym_t *dsp;	uint_t i, h;	if (dmp->dm_nsymelems == 0)		return (NULL);	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;	for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {		dsp = &dmp->dm_symchains[i];		sym = symtab + dsp->ds_symid;		if (strcmp(name, strtab + sym->st_name) == 0) {			if (idp != NULL)				*idp = dsp->ds_symid;			return (dt_module_symgelf32(sym, symp));		}	}	return (NULL);}static GElf_Sym *dt_module_symname64(dt_module_t *dmp, const char *name,    GElf_Sym *symp, uint_t *idp){	const Elf64_Sym *symtab = dmp->dm_symtab.cts_data;	const char *strtab = dmp->dm_strtab.cts_data;	const Elf64_Sym *sym;	const dt_sym_t *dsp;	uint_t i, h;	if (dmp->dm_nsymelems == 0)		return (NULL);	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;	for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {		dsp = &dmp->dm_symchains[i];		sym = symtab + dsp->ds_symid;		if (strcmp(name, strtab + sym->st_name) == 0) {			if (idp != NULL)				*idp = dsp->ds_symid;			return (dt_module_symgelf64(sym, symp));		}	}	return (NULL);}static GElf_Sym *dt_module_symaddr32(dt_module_t *dmp, GElf_Addr addr,    GElf_Sym *symp, uint_t *idp){	const Elf32_Sym **asmap = (const Elf32_Sym **)dmp->dm_asmap;	const Elf32_Sym *symtab = dmp->dm_symtab.cts_data;	const Elf32_Sym *sym;	uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;	Elf32_Addr v;	if (dmp->dm_aslen == 0)		return (NULL);	while (hi - lo > 1) {		mid = (lo + hi) / 2;		if (addr >= asmap[mid]->st_value)			lo = mid;		else			hi = mid;	}	i = addr < asmap[hi]->st_value ? lo : hi;	sym = asmap[i];	v = sym->st_value;	/*	 * If the previous entry has the same value, improve our choice.  The	 * order of equal-valued symbols is determined by the comparison func.	 */	while (i-- != 0 && asmap[i]->st_value == v)		sym = asmap[i];	if (addr - sym->st_value < MAX(sym->st_size, 1)) {		if (idp != NULL)			*idp = (uint_t)(sym - symtab);		return (dt_module_symgelf32(sym, symp));	}	return (NULL);}static GElf_Sym *dt_module_symaddr64(dt_module_t *dmp, GElf_Addr addr,    GElf_Sym *symp, uint_t *idp){	const Elf64_Sym **asmap = (const Elf64_Sym **)dmp->dm_asmap;	const Elf64_Sym *symtab = dmp->dm_symtab.cts_data;	const Elf64_Sym *sym;	uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;	Elf64_Addr v;	if (dmp->dm_aslen == 0)		return (NULL);	while (hi - lo > 1) {		mid = (lo + hi) / 2;		if (addr >= asmap[mid]->st_value)			lo = mid;		else			hi = mid;	}	i = addr < asmap[hi]->st_value ? lo : hi;	sym = asmap[i];	v = sym->st_value;	/*	 * If the previous entry has the same value, improve our choice.  The	 * order of equal-valued symbols is determined by the comparison func.	 */	while (i-- != 0 && asmap[i]->st_value == v)		sym = asmap[i];	if (addr - sym->st_value < MAX(sym->st_size, 1)) {		if (idp != NULL)			*idp = (uint_t)(sym - symtab);		return (dt_module_symgelf64(sym, symp));	}	return (NULL);}static const dt_modops_t dt_modops_32 = {	dt_module_syminit32,	dt_module_symsort32,	dt_module_symname32,	dt_module_symaddr32};static const dt_modops_t dt_modops_64 = {	dt_module_syminit64,	dt_module_symsort64,	dt_module_symname64,	dt_module_symaddr64};dt_module_t *dt_module_create(dtrace_hdl_t *dtp, const char *name){	uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;	dt_module_t *dmp;	for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) {		if (strcmp(dmp->dm_name, name) == 0)			return (dmp);	}	if ((dmp = malloc(sizeof (dt_module_t))) == NULL)		return (NULL); /* caller must handle allocation failure */	bzero(dmp, sizeof (dt_module_t));	(void) strlcpy(dmp->dm_name, name, sizeof (dmp->dm_name));	dt_list_append(&dtp->dt_modlist, dmp);	dmp->dm_next = dtp->dt_mods[h];	dtp->dt_mods[h] = dmp;	dtp->dt_nmods++;	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)		dmp->dm_ops = &dt_modops_64;	else		dmp->dm_ops = &dt_modops_32;	return (dmp);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -