📄 dt_printf.c
字号:
/* * 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 + -