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

📄 dt_printf.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_printf.c	1.12	04/12/18 SMI"#include <sys/sysmacros.h>#include <strings.h>#include <stdlib.h>#include <alloca.h>#include <assert.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include <dt_printf.h>#include <dt_string.h>#include <dt_impl.h>/*ARGSUSED*/static intpfcheck_addr(dt_pfargd_t *pfd, dt_node_t *dnp){	return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp));}/*ARGSUSED*/static intpfcheck_str(dt_pfargd_t *pfd, dt_node_t *dnp){	ctf_file_t *ctfp;	ctf_encoding_t e;	ctf_arinfo_t r;	ctf_id_t base;	uint_t kind;	if (dt_node_is_string(dnp))		return (1);	ctfp = dnp->dn_ctfp;	base = ctf_type_resolve(ctfp, dnp->dn_type);	kind = ctf_type_kind(ctfp, base);	return (kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 &&	    (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR &&	    ctf_type_encoding(ctfp, base, &e) == 0 && IS_CHAR(e));}/*ARGSUSED*/static intpfcheck_wstr(dt_pfargd_t *pfd, dt_node_t *dnp){	ctf_file_t *ctfp = dnp->dn_ctfp;	ctf_id_t base = ctf_type_resolve(ctfp, dnp->dn_type);	uint_t kind = ctf_type_kind(ctfp, base);	ctf_encoding_t e;	ctf_arinfo_t r;	return (kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 &&	    (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR &&	    ctf_type_kind(ctfp, base) == CTF_K_INTEGER &&	    ctf_type_encoding(ctfp, base, &e) == 0 && e.cte_bits == 32);}/*ARGSUSED*/static intpfcheck_csi(dt_pfargd_t *pfd, dt_node_t *dnp){	return (dt_node_is_integer(dnp) &&	    dt_node_type_size(dnp) <= sizeof (int));}/*ARGSUSED*/static intpfcheck_fp(dt_pfargd_t *pfd, dt_node_t *dnp){	return (dt_node_is_float(dnp));}/*ARGSUSED*/static intpfcheck_xint(dt_pfargd_t *pfd, dt_node_t *dnp){	return (dt_node_is_integer(dnp));}static intpfcheck_dint(dt_pfargd_t *pfd, dt_node_t *dnp){	if (dnp->dn_flags & DT_NF_SIGNED)		pfd->pfd_flags |= DT_PFCONV_SIGNED;	else		pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';	return (dt_node_is_integer(dnp));}/*ARGSUSED*/static intpfcheck_xshort(dt_pfargd_t *pfd, dt_node_t *dnp){	ctf_file_t *ctfp = dnp->dn_ctfp;	ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type);	char n[DT_TYPE_NAMELEN];	return (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && (	    strcmp(n, "short") == 0 || strcmp(n, "signed short") == 0 ||	    strcmp(n, "unsigned short") == 0));}/*ARGSUSED*/static intpfcheck_xlong(dt_pfargd_t *pfd, dt_node_t *dnp){	ctf_file_t *ctfp = dnp->dn_ctfp;	ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type);	char n[DT_TYPE_NAMELEN];	return (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && (	    strcmp(n, "long") == 0 || strcmp(n, "signed long") == 0 ||	    strcmp(n, "unsigned long") == 0));}/*ARGSUSED*/static intpfcheck_xlonglong(dt_pfargd_t *pfd, dt_node_t *dnp){	ctf_file_t *ctfp = dnp->dn_ctfp;	ctf_id_t type = dnp->dn_type;	char n[DT_TYPE_NAMELEN];	if (ctf_type_name(ctfp, ctf_type_resolve(ctfp, type), n,	    sizeof (n)) != NULL && (strcmp(n, "long long") == 0 ||	    strcmp(n, "signed long long") == 0 ||	    strcmp(n, "unsigned long long") == 0))		return (1);	/*	 * If the type used for %llx or %llX is not an [unsigned] long long, we	 * also permit it to be a [u]int64_t or any typedef thereof.  We know	 * that these typedefs are guaranteed to work with %ll[xX] in either	 * compilation environment even though they alias to "long" in LP64.	 */	while (ctf_type_kind(ctfp, type) == CTF_K_TYPEDEF) {		if (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL &&		    (strcmp(n, "int64_t") == 0 || strcmp(n, "uint64_t") == 0))			return (1);		type = ctf_type_reference(ctfp, type);	}	return (0);}static intpfcheck_type(dt_pfargd_t *pfd, dt_node_t *dnp){	return (ctf_type_compat(dnp->dn_ctfp, ctf_type_resolve(dnp->dn_ctfp,	    dnp->dn_type), pfd->pfd_conv->pfc_dctfp, pfd->pfd_conv->pfc_dtype));}/*ARGSUSED*/static intpfprint_sint(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t unormal){	int64_t normal = (int64_t)unormal;	int32_t n = (int32_t)normal;	switch (size) {	case sizeof (int8_t):		return (dt_printf(dtp, fp, format,		    (int32_t)*((int8_t *)addr) / n));	case sizeof (int16_t):		return (dt_printf(dtp, fp, format,		    (int32_t)*((int16_t *)addr) / n));	case sizeof (int32_t):		return (dt_printf(dtp, fp, format,		    *((int32_t *)addr) / n));	case sizeof (int64_t):		return (dt_printf(dtp, fp, format,		    *((int64_t *)addr) / normal));	default:		return (dt_set_errno(dtp, EDT_DMISMATCH));	}}/*ARGSUSED*/static intpfprint_uint(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	uint32_t n = (uint32_t)normal;	switch (size) {	case sizeof (uint8_t):		return (dt_printf(dtp, fp, format,		    (uint32_t)*((uint8_t *)addr) / n));	case sizeof (uint16_t):		return (dt_printf(dtp, fp, format,		    (uint32_t)*((uint16_t *)addr) / n));	case sizeof (uint32_t):		return (dt_printf(dtp, fp, format,		    *((uint32_t *)addr) / n));	case sizeof (uint64_t):		return (dt_printf(dtp, fp, format,		    *((uint64_t *)addr) / normal));	default:		return (dt_set_errno(dtp, EDT_DMISMATCH));	}}static intpfprint_dint(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	if (pfd->pfd_flags & DT_PFCONV_SIGNED)		return (pfprint_sint(dtp, fp, format, pfd, addr, size, normal));	else		return (pfprint_uint(dtp, fp, format, pfd, addr, size, normal));}/*ARGSUSED*/static intpfprint_fp(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	double n = (double)normal;	long double ldn = (long double)normal;	switch (size) {	case sizeof (float):		return (dt_printf(dtp, fp, format,		    (double)*((float *)addr) / n));	case sizeof (double):		return (dt_printf(dtp, fp, format,		    *((double *)addr) / n));	case sizeof (long double):		return (dt_printf(dtp, fp, format,		    *((long double *)addr) / ldn));	default:		return (dt_set_errno(dtp, EDT_DMISMATCH));	}}/*ARGSUSED*/static intpfprint_addr(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	dtrace_syminfo_t dts;	GElf_Sym sym;	GElf_Addr val;	size_t n = 20; /* for 0x%llx\0 */	char *s;	int err;	switch (size) {	case sizeof (uint32_t):		val = *((uint32_t *)addr);		break;	case sizeof (uint64_t):		val = *((uint64_t *)addr);		break;	default:		return (dt_set_errno(dtp, EDT_DMISMATCH));	}	if ((err = dtrace_lookup_by_addr(dtp, val, &sym, &dts)) == 0)		n += strlen(dts.dts_object) + strlen(dts.dts_name) + 2; /* +` */	s = alloca(n);	if (err == 0 && val != sym.st_value) {		(void) snprintf(s, n, "%s`%s+0x%llx", dts.dts_object,		    dts.dts_name, (u_longlong_t)val - sym.st_value);	} else if (err == 0) {		(void) snprintf(s, n, "%s`%s",		    dts.dts_object, dts.dts_name);	} else {		/*		 * We'll repeat the lookup, but this time we'll specify a NULL		 * GElf_Sym -- indicating that we're only interested in the		 * containing module.		 */		if (dtrace_lookup_by_addr(dtp, val, NULL, &dts) == 0) {			(void) snprintf(s, n, "%s`0x%llx", dts.dts_object,			    (u_longlong_t)val);		} else {			(void) snprintf(s, n, "0x%llx", (u_longlong_t)val);		}	}	return (dt_printf(dtp, fp, format, s));}/*ARGSUSED*/static intpfprint_uaddr(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	u_longlong_t val;	dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target");	char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2];	struct ps_prochandle *P = NULL;	pid_t pid;	GElf_Sym sym;	char *obj;	switch (size) {	case sizeof (uint32_t):		val = (u_longlong_t)*((uint32_t *)addr);		break;	case sizeof (uint64_t):		val = (u_longlong_t)*((uint64_t *)addr);		break;	default:		return (dt_set_errno(dtp, EDT_DMISMATCH));	}	if (dtp->dt_vector == NULL && idp != NULL && (pid = idp->di_id) != 0)		P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);	if (P == NULL) {		(void) snprintf(c, sizeof (c), "0x%llx", val);		return (dt_printf(dtp, fp, format, c));	}	dt_proc_lock(dtp, P);	if (Plookup_by_addr(P, val, name, sizeof (name), &sym) == 0) {		(void) Pobjname(P, val, objname, sizeof (objname));		obj = dt_basename(objname);		if (val > sym.st_value) {			(void) snprintf(c, sizeof (c), "%s`%s+0x%llx", obj,			    name, (u_longlong_t)(val - sym.st_value));		} else {			(void) snprintf(c, sizeof (c), "%s`%s", obj, name);		}	} else if (Pobjname(P, val, objname, sizeof (objname)) != NULL) {		(void) snprintf(c, sizeof (c), "%s`0x%llx",		    dt_basename(objname), val);	} else {		(void) snprintf(c, sizeof (c), "0x%llx", val);	}	dt_proc_unlock(dtp, P);	dt_proc_release(dtp, P);	return (dt_printf(dtp, fp, format, c));}/*ARGSUSED*/static intpfprint_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *vaddr, size_t size, uint64_t normal){	int depth = size / sizeof (pc_t), width;	dtrace_optval_t saved = dtp->dt_options[DTRACEOPT_STACKINDENT];	const dtrace_recdesc_t *rec = pfd->pfd_rec;	caddr_t addr = (caddr_t)vaddr;	int err = 0;	/*	 * We have stashed the value of the STACKINDENT option, and we will	 * now override it for the purposes of formatting the stack.  If the	 * field has been specified as left-aligned (i.e. (%-#), we set the	 * indentation to be the width.  This is a slightly odd semantic, but	 * it's useful functionality -- and it's slightly odd to begin with to	 * be using a single format specifier to be formatting multiple lines	 * of text...	 */	if (pfd->pfd_dynwidth < 0) {		assert(pfd->pfd_flags & DT_PFCONV_DYNWIDTH);		width = -pfd->pfd_dynwidth;	} else if (pfd->pfd_flags & DT_PFCONV_LEFT) {		width = pfd->pfd_dynwidth ? pfd->pfd_dynwidth : pfd->pfd_width;	} else {		width = 0;	}	dtp->dt_options[DTRACEOPT_STACKINDENT] = width;	switch (rec->dtrd_action) {	case DTRACEACT_USTACK:	case DTRACEACT_JSTACK:		err = dt_print_ustack(dtp, fp, format, addr, rec->dtrd_arg);		break;	case DTRACEACT_STACK:		err = dt_print_stack(dtp, fp, format, addr, depth);		break;	default:		assert(0);	}	dtp->dt_options[DTRACEOPT_STACKINDENT] = saved;	return (err);}/*ARGSUSED*/static intpfprint_time(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	char src[32], buf[32], *dst = buf;	hrtime_t time = *((uint64_t *)addr);	time_t sec = (time_t)(time / NANOSEC);	int i;	/*	 * ctime(3C) returns a string of the form "Dec  3 17:20:00 1973\n\0".	 * Below, we turn this into the canonical adb/mdb /[yY] format,	 * "1973 Dec  3 17:20:00".	 */	(void) ctime_r(&sec, src, sizeof (src));	/*	 * Place the 4-digit year at the head of the string...	 */	for (i = 20; i < 24; i++)		*dst++ = src[i];	/*	 * ...and follow it with the remainder (month, day, hh:mm:ss).	 */	for (i = 3; i < 19; i++)		*dst++ = src[i];	*dst = '\0';	return (dt_printf(dtp, fp, format, buf));}/* * This prints the time in RFC 822 standard form.  This is useful for emitting * notions of time that are consumed by standard tools (e.g., as part of an * RSS feed). *//*ARGSUSED*/static intpfprint_time822(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	hrtime_t time = *((uint64_t *)addr);	time_t sec = (time_t)(time / NANOSEC);	struct tm tm;	char buf[64];	(void) localtime_r(&sec, &tm);	(void) strftime(buf, sizeof (buf), "%a, %d %b %G %T %Z", &tm);	return (dt_printf(dtp, fp, format, buf));}/*ARGSUSED*/static intpfprint_cstr(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	char *s = alloca(size + 1);	bcopy(addr, s, size);	s[size] = '\0';	return (dt_printf(dtp, fp, format, s));}/*ARGSUSED*/static intpfprint_wstr(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	wchar_t *ws = alloca(size + sizeof (wchar_t));	bcopy(addr, ws, size);	ws[size / sizeof (wchar_t)] = L'\0';	return (dt_printf(dtp, fp, format, ws));}/*ARGSUSED*/static intpfprint_estr(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	char *s;	int n;	if ((s = strchr2esc(addr, size)) == NULL)		return (dt_set_errno(dtp, EDT_NOMEM));	n = dt_printf(dtp, fp, format, s);	free(s);	return (n);}static intpfprint_echr(dtrace_hdl_t *dtp, FILE *fp, const char *format,    const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal){	char c;	switch (size) {	case sizeof (int8_t):		c = *(int8_t *)addr;		break;	case sizeof (int16_t):		c = *(int16_t *)addr;		break;	case sizeof (int32_t):		c = *(int32_t *)addr;		break;	default:

⌨️ 快捷键说明

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