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

📄 dt_consume.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_consume.c	1.15	04/12/18 SMI"#include <stdlib.h>#include <strings.h>#include <errno.h>#include <unistd.h>#include <limits.h>#include <assert.h>#include <ctype.h>#include <alloca.h>#include <dt_impl.h>static intdt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,    dtrace_bufdesc_t *buf, size_t offs){	dtrace_probedesc_t *pd = data->dtpda_pdesc, *npd;	dtrace_eprobedesc_t *epd = data->dtpda_edesc, *nepd;	char *p = pd->dtpd_provider, *n = pd->dtpd_name;	dtrace_flowkind_t flow = DTRACEFLOW_NONE;	const char *str = NULL;	static const char *e_str[2] = { " -> ", " => " };	static const char *r_str[2] = { " <- ", " <= " };	dtrace_epid_t next, id = epd->dtepd_epid;	int rval;	if (strcmp(n, "entry") == 0) {		flow = DTRACEFLOW_ENTRY;		str = e_str[strcmp(p, "syscall") == 0];	} else if (strcmp(n, "return") == 0 ||	    strcmp(n, "exit") == 0) {		flow = DTRACEFLOW_RETURN;		str = r_str[strcmp(p, "syscall") == 0];	}	/*	 * If we're going to indent this, we need to check the ID of our last	 * call.  If we're looking at the same probe ID but a different EPID,	 * we _don't_ want to indent.  (Yes, there are some minor holes in	 * this scheme -- it's a heuristic.)	 */	if (flow == DTRACEFLOW_ENTRY) {		if ((last != DTRACE_EPIDNONE && id != last &&		    pd->dtpd_id == dtp->dt_pdesc[last]->dtpd_id))			flow = DTRACEFLOW_NONE;	}	/*	 * If we're going to unindent this, it's more difficult to see if	 * we don't actually want to unindent it -- we need to look at the	 * _next_ EPID.	 */	if (flow == DTRACEFLOW_RETURN) {		offs += epd->dtepd_size;		do {			if (offs >= buf->dtbd_size) {				/*				 * We're at the end -- maybe.  If the oldest				 * record is non-zero, we need to wrap.				 */				if (buf->dtbd_oldest != 0) {					offs = 0;				} else {					goto out;				}			}			next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);			if (next == DTRACE_EPIDNONE)				offs += sizeof (id);		} while (next == DTRACE_EPIDNONE);		if ((rval = dt_epid_lookup(dtp, next, &nepd, &npd)) != 0)			return (rval);		if (next != id && npd->dtpd_id == pd->dtpd_id)			flow = DTRACEFLOW_NONE;	}out:	if (flow == DTRACEFLOW_ENTRY || flow == DTRACEFLOW_RETURN) {		data->dtpda_prefix = str;	} else {		data->dtpda_prefix = "| ";	}	if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)		data->dtpda_indent -= 2;	data->dtpda_flow = flow;	return (0);}static intdt_nullprobe(){	return (DTRACE_CONSUME_THIS);}static intdt_nullrec(){	return (DTRACE_CONSUME_NEXT);}intdt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,    size_t size, uint64_t normal){	const uint64_t *data = addr;	int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;	uint64_t total_bin_count = 0;	if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))		return (dt_set_errno(dtp, EDT_DMISMATCH));	while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)		first_bin++;	if (first_bin > 0)		first_bin--;	while (last_bin > 0 && data[last_bin] == 0)		last_bin--;	if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)		last_bin++;	for (i = first_bin; i <= last_bin; i++)		total_bin_count += data[i];	if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",	    "------------- Distribution -------------", "count") < 0)		return (-1);	for (i = first_bin; i <= last_bin; i++) {		float f = ((float)data[i] * 40.0) / (float)total_bin_count;		uint_t depth = (uint_t)(f + 0.5);		if (dt_printf(dtp, fp, "%16lld |%s%s %-9llu\n",		    (long long)DTRACE_QUANTIZE_BUCKETVAL(i),		    "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + 40 - depth,		    "                                        " + depth,		    (u_longlong_t)data[i] / normal) < 0)			return (-1);	}	return (0);}intdt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,    size_t size, uint64_t normal){	const uint64_t *data = addr;	int i, first_bin, last_bin, base;	uint64_t arg, total_bin_count = 0;	uint16_t step, levels;	if (size < sizeof (uint64_t))		return (dt_set_errno(dtp, EDT_DMISMATCH));	arg = *data++;	size -= sizeof (uint64_t);	base = DTRACE_LQUANTIZE_BASE(arg);	step = DTRACE_LQUANTIZE_STEP(arg);	levels = DTRACE_LQUANTIZE_LEVELS(arg);	first_bin = 0;	last_bin = levels + 1;	if (size != sizeof (uint64_t) * (levels + 2))		return (dt_set_errno(dtp, EDT_DMISMATCH));	while (first_bin < levels + 1 && data[first_bin] == 0)		first_bin++;	if (first_bin > 0)		first_bin--;	while (last_bin > 0 && data[last_bin] == 0)		last_bin--;	if (last_bin < levels + 1)		last_bin++;	for (i = first_bin; i <= last_bin; i++)		total_bin_count += data[i];	if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",	    "------------- Distribution -------------", "count") < 0)		return (-1);	for (i = first_bin; i <= last_bin; i++) {		float f = ((float)data[i] * 40.0) / (float)total_bin_count;		uint_t depth = (uint_t)(f + 0.5);		char c[32];		int err;		if (i == 0) {			(void) snprintf(c, sizeof (c), "< %d",			    base / (uint32_t)normal);			err = dt_printf(dtp, fp, "%16s ", c);		} else if (i == levels + 1) {			(void) snprintf(c, sizeof (c), ">= %d",			    base + (levels * step));			err = dt_printf(dtp, fp, "%16s ", c);		} else {			err = dt_printf(dtp, fp, "%16d ",			    base + (i - 1) * step);		}		if (err < 0 || dt_printf(dtp, fp, "|%s%s %-9llu\n",		    "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + 40 - depth,		    "                                        " + depth,		    (u_longlong_t)data[i] / normal) < 0)			return (-1);	}	return (0);}/*ARGSUSED*/static intdt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,    size_t size, uint64_t normal){	/* LINTED - alignment */	uint64_t *data = (uint64_t *)addr;	return (dt_printf(dtp, fp, " %16lld", data[0] ?	    (long long)(data[1] / normal / data[0]) : 0));}/*ARGSUSED*/intdt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,    size_t nbytes, int width, int quiet){	/*	 * If the byte stream is a series of printable characters, followed by	 * a terminating byte, we print it out as a string.  Otherwise, we	 * assume that it's something else and just print the bytes.	 */	int i, j, margin = 5;	char *c = (char *)addr;	if (nbytes == 0)		return (0);	if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)		goto raw;	for (i = 0; i < nbytes; i++) {		/*		 * We define a "printable character" to be one for which		 * isprint(3C) returns non-zero, isspace(3C) returns non-zero,		 * or a character which is either backspace or the bell.		 * Backspace and the bell are regrettably special because		 * they fail the first two tests -- and yet they are entirely		 * printable.  These are the only two control characters that		 * have meaning for the terminal and for which isprint(3C) and		 * isspace(3C) return 0.		 */		if (isprint(c[i]) || isspace(c[i]) ||		    c[i] == '\b' || c[i] == '\a')			continue;		if (c[i] == '\0' && i > 0) {			/*			 * This looks like it might be a string.  Before we			 * assume that it is indeed a string, check the			 * remainder of the byte range; if it contains			 * additional non-nul characters, we'll assume that			 * it's a binary stream that just happens to look like			 * a string, and we'll print out the individual bytes.			 */			for (j = i + 1; j < nbytes; j++) {				if (c[j] != '\0')					break;			}			if (j != nbytes)				break;			if (quiet)				return (dt_printf(dtp, fp, "%s", c));			else				return (dt_printf(dtp, fp, "  %-*s", width, c));		}		break;	}	if (i == nbytes) {		/*		 * The byte range is all printable characters, but there is		 * no trailing nul byte.  We'll assume that it's a string and		 * print it as such.		 */		char *s = alloca(nbytes + 1);		bcopy(c, s, nbytes);		s[nbytes] = '\0';		return (dt_printf(dtp, fp, "  %-*s", width, s));	}raw:	if (dt_printf(dtp, fp, "\n%*s      ", margin, "") < 0)		return (-1);	for (i = 0; i < 16; i++)		if (dt_printf(dtp, fp, "  %c", "0123456789abcdef"[i]) < 0)			return (-1);	if (dt_printf(dtp, fp, "  0123456789abcdef\n") < 0)		return (-1);	for (i = 0; i < nbytes; i += 16) {		if (dt_printf(dtp, fp, "%*s%5x:", margin, "", i) < 0)			return (-1);		for (j = i; j < i + 16 && j < nbytes; j++) {			if (dt_printf(dtp, fp, " %02x", (uchar_t)c[j]) < 0)				return (-1);		}		while (j++ % 16) {			if (dt_printf(dtp, fp, "   ") < 0)				return (-1);		}		if (dt_printf(dtp, fp, "  ") < 0)			return (-1);		for (j = i; j < i + 16 && j < nbytes; j++) {			if (dt_printf(dtp, fp, "%c",			    c[j] < ' ' || c[j] > '~' ? '.' : c[j]) < 0)				return (-1);		}		if (dt_printf(dtp, fp, "\n") < 0)			return (-1);	}	return (0);}intdt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,    caddr_t addr, int depth){	pc_t *pc = (pc_t *)(uintptr_t)addr;	dtrace_syminfo_t dts;	GElf_Sym sym;	int i, indent;	char c[PATH_MAX * 2];	if (dt_printf(dtp, fp, "\n") < 0)		return (-1);	if (format == NULL)		format = "%s";	if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)		indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];	else		indent = _dtrace_stkindent;	for (i = 0; i < depth && pc[i] != NULL; i++) {		if (dt_printf(dtp, fp, "%*s", indent, "") < 0)			return (-1);		if (dtrace_lookup_by_addr(dtp, pc[i], &sym, &dts) == 0) {			if (pc[i] > sym.st_value) {				(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",				    dts.dts_object, dts.dts_name,				    (u_longlong_t)pc[i] - sym.st_value);			} else {				(void) snprintf(c, sizeof (c), "%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, pc[i],			    NULL, &dts) == 0) {				(void) snprintf(c, sizeof (c), "%s`0x%llx",				    dts.dts_object, (u_longlong_t)pc[i]);			} else {				(void) snprintf(c, sizeof (c), "0x%llx",				    (u_longlong_t)pc[i]);			}		}		if (dt_printf(dtp, fp, format, c) < 0)			return (-1);		if (dt_printf(dtp, fp, "\n") < 0)			return (-1);	}	return (0);}intdt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format,    caddr_t addr, uint64_t arg){	uint64_t *pc = (uint64_t *)(uintptr_t)addr;	uint32_t depth = DTRACE_USTACK_NFRAMES(arg);	uint32_t strsize = DTRACE_USTACK_STRSIZE(arg);	const char *strbase = addr + (depth + 1) * sizeof (uint64_t);	const char *str = strsize ? strbase : NULL;	int err = 0;	char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2];	struct ps_prochandle *P;	GElf_Sym sym;	int i, indent;	pid_t pid;	if (depth == 0)		return (0);	pid = (pid_t)*pc++;	if (dt_printf(dtp, fp, "\n") < 0)		return (-1);	if (format == NULL)		format = "%s";	if (dtp->dt_options[DTRACEOPT_STACKINDENT] != DTRACEOPT_UNSET)		indent = (int)dtp->dt_options[DTRACEOPT_STACKINDENT];	else		indent = _dtrace_stkindent;	/*	 * Ultimately, we need to add an entry point in the library vector for	 * determining <symbol, offset> from <pid, address>.  For now, if	 * this is a vector open, we just print the raw address or string.	 */	if (dtp->dt_vector == NULL)		P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0);	else		P = NULL;	if (P != NULL)		dt_proc_lock(dtp, P); /* lock handle while we perform lookups */

⌨️ 快捷键说明

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