diff options
Diffstat (limited to 'usr/src/tools/ctf/dump/dump.c')
| -rw-r--r-- | usr/src/tools/ctf/dump/dump.c | 1028 | 
1 files changed, 0 insertions, 1028 deletions
| diff --git a/usr/src/tools/ctf/dump/dump.c b/usr/src/tools/ctf/dump/dump.c deleted file mode 100644 index 5579bae596..0000000000 --- a/usr/src/tools/ctf/dump/dump.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License").  You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc.  All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident	"%Z%%M%	%I%	%E% SMI" - -#include <sys/types.h> -#include <sys/sysmacros.h> -#include <sys/stat.h> -#include <sys/mman.h> - -#include <strings.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <gelf.h> -#include <zlib.h> - -#include "ctf_headers.h" -#include "utils.h" -#include "symbol.h" - -#define	WARN(x)	{ warn(x); return (E_ERROR); } - -/* - * Flags that indicate what data is to be displayed.  An explicit `all' value is - * provided to allow the code to distinguish between a request for everything - * (currently requested by invoking ctfdump without flags) and individual - * requests for all of the types of data (an invocation with all flags).  In the - * former case, we want to be able to implicitly adjust the definition of `all' - * based on the CTF version of the file being dumped.  For example, if a v2 file - * is being dumped, `all' includes F_LABEL - a request to dump the label - * section.  If a v1 file is being dumped, `all' does not include F_LABEL, - * because v1 CTF doesn't support labels.  We need to be able to distinguish - * between `ctfdump foo', which has an implicit request for labels if `foo' - * supports them, and `ctfdump -l foo', which has an explicity request.  In the - * latter case, we exit with an error if `foo' is a v1 CTF file. - */ -static enum { -	F_DATA	= 0x01,		/* show data object section */ -	F_FUNC	= 0x02,		/* show function section */ -	F_HDR	= 0x04,		/* show header */ -	F_STR	= 0x08,		/* show string table */ -	F_TYPES	= 0x10,		/* show type section */ -	F_STATS = 0x20, 	/* show statistics */ -	F_LABEL	= 0x40,		/* show label section */ -	F_ALL	= 0x80,		/* explicit request for `all' */ -	F_ALLMSK = 0xff		/* show all sections and statistics */ -} flags = 0; - -static struct { -	ulong_t s_ndata;	/* total number of data objects */ -	ulong_t s_nfunc;	/* total number of functions */ -	ulong_t s_nargs;	/* total number of function arguments */ -	ulong_t s_argmax;	/* longest argument list */ -	ulong_t s_ntypes;	/* total number of types */ -	ulong_t s_types[16];	/* number of types by kind */ -	ulong_t s_nsmem;	/* total number of struct members */ -	ulong_t s_nsbytes;	/* total size of all structs */ -	ulong_t s_smmax;	/* largest struct in terms of members */ -	ulong_t s_sbmax;	/* largest struct in terms of bytes */ -	ulong_t s_numem;	/* total number of union members */ -	ulong_t s_nubytes;	/* total size of all unions */ -	ulong_t s_ummax;	/* largest union in terms of members */ -	ulong_t s_ubmax;	/* largest union in terms of bytes */ -	ulong_t s_nemem;	/* total number of enum members */ -	ulong_t s_emmax;	/* largest enum in terms of members */ -	ulong_t s_nstr;		/* total number of strings */ -	size_t s_strlen;	/* total length of all strings */ -	size_t s_strmax;	/* longest string length */ -} stats; - -typedef struct ctf_data { -	caddr_t cd_ctfdata;	/* Pointer to the CTF data */ -	size_t cd_ctflen;	/* Length of CTF data */ - -	/* -	 * cd_symdata will be non-NULL if the CTF data is being retrieved from -	 * an ELF file with a symbol table.  cd_strdata and cd_nsyms should be -	 * used only if cd_symdata is non-NULL. -	 */ -	Elf_Data *cd_symdata;	/* Symbol table */ -	Elf_Data *cd_strdata;	/* Symbol table strings */ -	int cd_nsyms;		/* Number of symbol table entries */ -} ctf_data_t; - -static const char * -ref_to_str(uint_t name, const ctf_header_t *hp, const ctf_data_t *cd) -{ -	size_t offset = CTF_NAME_OFFSET(name); -	const char *s = cd->cd_ctfdata + hp->cth_stroff + offset; - -	if (CTF_NAME_STID(name) != CTF_STRTAB_0) -		return ("<< ??? - name in external strtab >>"); - -	if (offset >= hp->cth_strlen) -		return ("<< ??? - name exceeds strlab len >>"); - -	if (hp->cth_stroff + offset >= cd->cd_ctflen) -		return ("<< ??? - file truncated >>"); - -	if (s[0] == '\0') -		return ("(anon)"); - -	return (s); -} - -static const char * -int_encoding_to_str(uint_t encoding) -{ -	static char buf[32]; - -	if (encoding == 0 || (encoding & ~(CTF_INT_SIGNED | CTF_INT_CHAR | -	    CTF_INT_BOOL | CTF_INT_VARARGS)) != 0) -		(void) snprintf(buf, sizeof (buf), " 0x%x", encoding); -	else { -		buf[0] = '\0'; -		if (encoding & CTF_INT_SIGNED) -			(void) strcat(buf, " SIGNED"); -		if (encoding & CTF_INT_CHAR) -			(void) strcat(buf, " CHAR"); -		if (encoding & CTF_INT_BOOL) -			(void) strcat(buf, " BOOL"); -		if (encoding & CTF_INT_VARARGS) -			(void) strcat(buf, " VARARGS"); -	} - -	return (buf + 1); -} - -static const char * -fp_encoding_to_str(uint_t encoding) -{ -	static const char *const encs[] = { -		NULL, "SINGLE", "DOUBLE", "COMPLEX", "DCOMPLEX", "LDCOMPLEX", -		"LDOUBLE", "INTERVAL", "DINTERVAL", "LDINTERVAL", "IMAGINARY", -		"DIMAGINARY", "LDIMAGINARY" -	}; - -	static char buf[16]; - -	if (encoding < 1 || encoding >= (sizeof (encs) / sizeof (char *))) { -		(void) snprintf(buf, sizeof (buf), "%u", encoding); -		return (buf); -	} - -	return (encs[encoding]); -} - -static void -print_line(const char *s) -{ -	static const char line[] = "----------------------------------------" -	    "----------------------------------------"; -	(void) printf("\n%s%.*s\n\n", s, (int)(78 - strlen(s)), line); -} - -static int -print_header(const ctf_header_t *hp, const ctf_data_t *cd) -{ -	print_line("- CTF Header "); - -	(void) printf("  cth_magic    = 0x%04x\n", hp->cth_magic); -	(void) printf("  cth_version  = %u\n", hp->cth_version); -	(void) printf("  cth_flags    = 0x%02x\n", hp->cth_flags); -	(void) printf("  cth_parlabel = %s\n", -	    ref_to_str(hp->cth_parlabel, hp, cd)); -	(void) printf("  cth_parname  = %s\n", -	    ref_to_str(hp->cth_parname, hp, cd)); -	(void) printf("  cth_lbloff   = %u\n", hp->cth_lbloff); -	(void) printf("  cth_objtoff  = %u\n", hp->cth_objtoff); -	(void) printf("  cth_funcoff  = %u\n", hp->cth_funcoff); -	(void) printf("  cth_typeoff  = %u\n", hp->cth_typeoff); -	(void) printf("  cth_stroff   = %u\n", hp->cth_stroff); -	(void) printf("  cth_strlen   = %u\n", hp->cth_strlen); - -	return (E_SUCCESS); -} - -static int -print_labeltable(const ctf_header_t *hp, const ctf_data_t *cd) -{ -	/* LINTED - pointer alignment */ -	const ctf_lblent_t *ctl = (ctf_lblent_t *)(cd->cd_ctfdata + -	    hp->cth_lbloff); -	ulong_t i, n = (hp->cth_objtoff - hp->cth_lbloff) / sizeof (*ctl); - -	print_line("- Label Table "); - -	if (hp->cth_lbloff & 3) -		WARN("cth_lbloff is not aligned properly\n"); -	if (hp->cth_lbloff >= cd->cd_ctflen) -		WARN("file is truncated or cth_lbloff is corrupt\n"); -	if (hp->cth_objtoff >= cd->cd_ctflen) -		WARN("file is truncated or cth_objtoff is corrupt\n"); -	if (hp->cth_lbloff > hp->cth_objtoff) -		WARN("file is corrupt -- cth_lbloff > cth_objtoff\n"); - -	for (i = 0; i < n; i++, ctl++) { -		(void) printf("  %5u %s\n", ctl->ctl_typeidx, -		    ref_to_str(ctl->ctl_label, hp, cd)); -	} - -	return (E_SUCCESS); -} - -/* - * Given the current symbol index (-1 to start at the beginning of the symbol - * table) and the type of symbol to match, this function returns the index of - * the next matching symbol (if any), and places the name of that symbol in - * *namep.  If no symbol is found, -1 is returned. - */ -static int -next_sym(const ctf_data_t *cd, const int symidx, const uchar_t matchtype, -    char **namep) -{ -	int i; - -	for (i = symidx + 1; i < cd->cd_nsyms; i++) { -		GElf_Sym sym; -		char *name; -		int type; - -		if (gelf_getsym(cd->cd_symdata, i, &sym) == 0) -			return (-1); - -		name = (char *)cd->cd_strdata->d_buf + sym.st_name; -		type = GELF_ST_TYPE(sym.st_info); - -		/* -		 * Skip various types of symbol table entries. -		 */ -		if (type != matchtype || ignore_symbol(&sym, name)) -			continue; - -		/* Found one */ -		*namep = name; -		return (i); -	} - -	return (-1); -} - -static int -read_data(const ctf_header_t *hp, const ctf_data_t *cd) -{ -	/* LINTED - pointer alignment */ -	const ushort_t *idp = (ushort_t *)(cd->cd_ctfdata + hp->cth_objtoff); -	ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / sizeof (ushort_t); - -	if (flags != F_STATS) -		print_line("- Data Objects "); - -	if (hp->cth_objtoff & 1) -		WARN("cth_objtoff is not aligned properly\n"); -	if (hp->cth_objtoff >= cd->cd_ctflen) -		WARN("file is truncated or cth_objtoff is corrupt\n"); -	if (hp->cth_funcoff >= cd->cd_ctflen) -		WARN("file is truncated or cth_funcoff is corrupt\n"); -	if (hp->cth_objtoff > hp->cth_funcoff) -		WARN("file is corrupt -- cth_objtoff > cth_funcoff\n"); - -	if (flags != F_STATS) { -		int symidx, len, i; -		char *name = NULL; - -		for (symidx = -1, i = 0; i < n; i++) { -			int nextsym; - -			if (cd->cd_symdata == NULL || (nextsym = next_sym(cd, -			    symidx, STT_OBJECT, &name)) < 0) -				name = NULL; -			else -				symidx = nextsym; - -			len = printf("  [%u] %u", i, *idp++); -			if (name != NULL) -				(void) printf("%*s%s (%u)", (15 - len), "", -				    name, symidx); -			(void) putchar('\n'); -		} -	} - -	stats.s_ndata = n; -	return (E_SUCCESS); -} - -static int -read_funcs(const ctf_header_t *hp, const ctf_data_t *cd) -{ -	/* LINTED - pointer alignment */ -	const ushort_t *fp = (ushort_t *)(cd->cd_ctfdata + hp->cth_funcoff); - -	/* LINTED - pointer alignment */ -	const ushort_t *end = (ushort_t *)(cd->cd_ctfdata + hp->cth_typeoff); - -	ulong_t id; -	int symidx; - -	if (flags != F_STATS) -		print_line("- Functions "); - -	if (hp->cth_funcoff & 1) -		WARN("cth_funcoff is not aligned properly\n"); -	if (hp->cth_funcoff >= cd->cd_ctflen) -		WARN("file is truncated or cth_funcoff is corrupt\n"); -	if (hp->cth_typeoff >= cd->cd_ctflen) -		WARN("file is truncated or cth_typeoff is corrupt\n"); -	if (hp->cth_funcoff > hp->cth_typeoff) -		WARN("file is corrupt -- cth_funcoff > cth_typeoff\n"); - -	for (symidx = -1, id = 0; fp < end; id++) { -		ushort_t info = *fp++; -		ushort_t kind = CTF_INFO_KIND(info); -		ushort_t n = CTF_INFO_VLEN(info); -		ushort_t i; -		int nextsym; -		char *name; - -		if (cd->cd_symdata == NULL || (nextsym = next_sym(cd, symidx, -		    STT_FUNC, &name)) < 0) -			name = NULL; -		else -			symidx = nextsym; - -		if (kind == CTF_K_UNKNOWN && n == 0) -			continue; /* skip padding */ - -		if (kind != CTF_K_FUNCTION) { -			(void) printf("  [%lu] unexpected kind -- %u\n", -			    id, kind); -			return (E_ERROR); -		} - -		if (fp + n > end) { -			(void) printf("  [%lu] vlen %u extends past section " -			    "boundary\n", id, n); -			return (E_ERROR); -		} - -		if (flags != F_STATS) { -			(void) printf("  [%lu] FUNC ", id); -			if (name != NULL) -				(void) printf("(%s) ", name); -			(void) printf("returns: %u args: (", *fp++); - -			if (n != 0) { -				(void) printf("%u", *fp++); -				for (i = 1; i < n; i++) -					(void) printf(", %u", *fp++); -			} - -			(void) printf(")\n"); -		} else -			fp += n + 1; /* skip to next function definition */ - -		stats.s_nfunc++; -		stats.s_nargs += n; -		stats.s_argmax = MAX(stats.s_argmax, n); -	} - -	return (E_SUCCESS); -} - -static int -read_types(const ctf_header_t *hp, const ctf_data_t *cd) -{ -	/* LINTED - pointer alignment */ -	const ctf_type_t *tp = (ctf_type_t *)(cd->cd_ctfdata + hp->cth_typeoff); - -	/* LINTED - pointer alignment */ -	const ctf_type_t *end = (ctf_type_t *)(cd->cd_ctfdata + hp->cth_stroff); - -	ulong_t id; - -	if (flags != F_STATS) -		print_line("- Types "); - -	if (hp->cth_typeoff & 3) -		WARN("cth_typeoff is not aligned properly\n"); -	if (hp->cth_typeoff >= cd->cd_ctflen) -		WARN("file is truncated or cth_typeoff is corrupt\n"); -	if (hp->cth_stroff >= cd->cd_ctflen) -		WARN("file is truncated or cth_stroff is corrupt\n"); -	if (hp->cth_typeoff > hp->cth_stroff) -		WARN("file is corrupt -- cth_typeoff > cth_stroff\n"); - -	id = 1; -	if (hp->cth_parlabel || hp->cth_parname) -		id += 1 << CTF_PARENT_SHIFT; - -	for (/* */; tp < end; id++) { -		ulong_t i, n = CTF_INFO_VLEN(tp->ctt_info); -		size_t size, increment, vlen = 0; -		int kind = CTF_INFO_KIND(tp->ctt_info); - -		union { -			const void *ptr; -			const ctf_array_t *ap; -			const ctf_member_t *mp; -			const ctf_lmember_t *lmp; -			const ctf_enum_t *ep; -			const ushort_t *argp; -		} u; - -		if (flags != F_STATS) { -			(void) printf("  %c%lu%c ", -			    "[<"[CTF_INFO_ISROOT(tp->ctt_info)], id, -			    "]>"[CTF_INFO_ISROOT(tp->ctt_info)]); -		} - -		if (tp->ctt_size == CTF_LSIZE_SENT) { -			increment = sizeof (ctf_type_t); -			size = (size_t)CTF_TYPE_LSIZE(tp); -		} else { -			increment = sizeof (ctf_stype_t); -			size = tp->ctt_size; -		} -		u.ptr = (caddr_t)tp + increment; - -		switch (kind) { -		case CTF_K_INTEGER: -			if (flags != F_STATS) { -				uint_t encoding = *((const uint_t *)u.ptr); - -				(void) printf("INTEGER %s encoding=%s offset=%u" -				    " bits=%u", ref_to_str(tp->ctt_name, hp, -				    cd), int_encoding_to_str( -				    CTF_INT_ENCODING(encoding)), -				    CTF_INT_OFFSET(encoding), -				    CTF_INT_BITS(encoding)); -			} -			vlen = sizeof (uint_t); -			break; - -		case CTF_K_FLOAT: -			if (flags != F_STATS) { -				uint_t encoding = *((const uint_t *)u.ptr); - -				(void) printf("FLOAT %s encoding=%s offset=%u " -				    "bits=%u", ref_to_str(tp->ctt_name, hp, -				    cd), fp_encoding_to_str( -				    CTF_FP_ENCODING(encoding)), -				    CTF_FP_OFFSET(encoding), -				    CTF_FP_BITS(encoding)); -			} -			vlen = sizeof (uint_t); -			break; - -		case CTF_K_POINTER: -			if (flags != F_STATS) { -				(void) printf("POINTER %s refers to %u", -				    ref_to_str(tp->ctt_name, hp, cd), -				    tp->ctt_type); -			} -			break; - -		case CTF_K_ARRAY: -			if (flags != F_STATS) { -				(void) printf("ARRAY %s content: %u index: %u " -				    "nelems: %u\n", ref_to_str(tp->ctt_name, -				    hp, cd), u.ap->cta_contents, -				    u.ap->cta_index, u.ap->cta_nelems); -			} -			vlen = sizeof (ctf_array_t); -			break; - -		case CTF_K_FUNCTION: -			if (flags != F_STATS) { -				(void) printf("FUNCTION %s returns: %u args: (", -				    ref_to_str(tp->ctt_name, hp, cd), -				    tp->ctt_type); - -				if (n != 0) { -					(void) printf("%u", *u.argp++); -					for (i = 1; i < n; i++, u.argp++) -						(void) printf(", %u", *u.argp); -				} - -				(void) printf(")"); -			} - -			vlen = sizeof (ushort_t) * (n + (n & 1)); -			break; - -		case CTF_K_STRUCT: -		case CTF_K_UNION: -			if (kind == CTF_K_STRUCT) { -				stats.s_nsmem += n; -				stats.s_smmax = MAX(stats.s_smmax, n); -				stats.s_nsbytes += size; -				stats.s_sbmax = MAX(stats.s_sbmax, size); - -				if (flags != F_STATS) -					(void) printf("STRUCT"); -			} else { -				stats.s_numem += n; -				stats.s_ummax = MAX(stats.s_ummax, n); -				stats.s_nubytes += size; -				stats.s_ubmax = MAX(stats.s_ubmax, size); - -				if (flags != F_STATS) -					(void) printf("UNION"); -			} - -			if (flags != F_STATS) { -				(void) printf(" %s (%d bytes)\n", -				    ref_to_str(tp->ctt_name, hp, cd), size); - -				if (size >= CTF_LSTRUCT_THRESH) { -					for (i = 0; i < n; i++, u.lmp++) { -						(void) printf( -						    "\t%s type=%u off=%llu\n", -						    ref_to_str(u.lmp->ctlm_name, -						    hp, cd), u.lmp->ctlm_type, -						    CTF_LMEM_OFFSET(u.lmp)); -					} -				} else { -					for (i = 0; i < n; i++, u.mp++) { -						(void) printf( -						    "\t%s type=%u off=%u\n", -						    ref_to_str(u.mp->ctm_name, -						    hp, cd), u.mp->ctm_type, -						    u.mp->ctm_offset); -					} -				} -			} - -			vlen = n * (size >= CTF_LSTRUCT_THRESH ? -			    sizeof (ctf_lmember_t) : sizeof (ctf_member_t)); -			break; - -		case CTF_K_ENUM: -			if (flags != F_STATS) { -				(void) printf("ENUM %s\n", -				    ref_to_str(tp->ctt_name, hp, cd)); - -				for (i = 0; i < n; i++, u.ep++) { -					(void) printf("\t%s = %d\n", -					    ref_to_str(u.ep->cte_name, hp, cd), -					    u.ep->cte_value); -				} -			} - -			stats.s_nemem += n; -			stats.s_emmax = MAX(stats.s_emmax, n); - -			vlen = sizeof (ctf_enum_t) * n; -			break; - -		case CTF_K_FORWARD: -			if (flags != F_STATS) { -				(void) printf("FORWARD %s", -				    ref_to_str(tp->ctt_name, hp, cd)); -			} -			break; - -		case CTF_K_TYPEDEF: -			if (flags != F_STATS) { -				(void) printf("TYPEDEF %s refers to %u", -				    ref_to_str(tp->ctt_name, hp, cd), -				    tp->ctt_type); -			} -			break; - -		case CTF_K_VOLATILE: -			if (flags != F_STATS) { -				(void) printf("VOLATILE %s refers to %u", -				    ref_to_str(tp->ctt_name, hp, cd), -				    tp->ctt_type); -			} -			break; - -		case CTF_K_CONST: -			if (flags != F_STATS) { -				(void) printf("CONST %s refers to %u", -				    ref_to_str(tp->ctt_name, hp, cd), -				    tp->ctt_type); -			} -			break; - -		case CTF_K_RESTRICT: -			if (flags != F_STATS) { -				(void) printf("RESTRICT %s refers to %u", -				    ref_to_str(tp->ctt_name, hp, cd), -				    tp->ctt_type); -			} -			break; - -		case CTF_K_UNKNOWN: -			break; /* hole in type id space */ - -		default: -			(void) printf("unexpected kind %u\n", kind); -			return (E_ERROR); -		} - -		if (flags != F_STATS) -			(void) printf("\n"); - -		stats.s_ntypes++; -		stats.s_types[kind]++; - -		tp = (ctf_type_t *)((uintptr_t)tp + increment + vlen); -	} - -	return (E_SUCCESS); -} - -static int -read_strtab(const ctf_header_t *hp, const ctf_data_t *cd) -{ -	size_t n, off, len = hp->cth_strlen; -	const char *s = cd->cd_ctfdata + hp->cth_stroff; - -	if (flags != F_STATS) -		print_line("- String Table "); - -	if (hp->cth_stroff >= cd->cd_ctflen) -		WARN("file is truncated or cth_stroff is corrupt\n"); -	if (hp->cth_stroff + hp->cth_strlen > cd->cd_ctflen) -		WARN("file is truncated or cth_strlen is corrupt\n"); - -	for (off = 0; len != 0; off += n) { -		if (flags != F_STATS) { -			(void) printf("  [%lu] %s\n", (ulong_t)off, -			    s[0] == '\0' ? "\\0" : s); -		} -		n = strlen(s) + 1; -		len -= n; -		s += n; - -		stats.s_nstr++; -		stats.s_strlen += n; -		stats.s_strmax = MAX(stats.s_strmax, n); -	} - -	return (E_SUCCESS); -} - -static void -long_stat(const char *name, ulong_t value) -{ -	(void) printf("  %-36s= %lu\n", name, value); -} - -static void -fp_stat(const char *name, float value) -{ -	(void) printf("  %-36s= %.2f\n", name, value); -} - -static int -print_stats(void) -{ -	print_line("- CTF Statistics "); - -	long_stat("total number of data objects", stats.s_ndata); -	(void) printf("\n"); - -	long_stat("total number of functions", stats.s_nfunc); -	long_stat("total number of function arguments", stats.s_nargs); -	long_stat("maximum argument list length", stats.s_argmax); - -	if (stats.s_nfunc != 0) { -		fp_stat("average argument list length", -		    (float)stats.s_nargs / (float)stats.s_nfunc); -	} - -	(void) printf("\n"); - -	long_stat("total number of types", stats.s_ntypes); -	long_stat("total number of integers", stats.s_types[CTF_K_INTEGER]); -	long_stat("total number of floats", stats.s_types[CTF_K_FLOAT]); -	long_stat("total number of pointers", stats.s_types[CTF_K_POINTER]); -	long_stat("total number of arrays", stats.s_types[CTF_K_ARRAY]); -	long_stat("total number of func types", stats.s_types[CTF_K_FUNCTION]); -	long_stat("total number of structs", stats.s_types[CTF_K_STRUCT]); -	long_stat("total number of unions", stats.s_types[CTF_K_UNION]); -	long_stat("total number of enums", stats.s_types[CTF_K_ENUM]); -	long_stat("total number of forward tags", stats.s_types[CTF_K_FORWARD]); -	long_stat("total number of typedefs", stats.s_types[CTF_K_TYPEDEF]); -	long_stat("total number of volatile types", -	    stats.s_types[CTF_K_VOLATILE]); -	long_stat("total number of const types", stats.s_types[CTF_K_CONST]); -	long_stat("total number of restrict types", -	    stats.s_types[CTF_K_RESTRICT]); -	long_stat("total number of unknowns (holes)", -	    stats.s_types[CTF_K_UNKNOWN]); - -	(void) printf("\n"); - -	long_stat("total number of struct members", stats.s_nsmem); -	long_stat("maximum number of struct members", stats.s_smmax); -	long_stat("total size of all structs", stats.s_nsbytes); -	long_stat("maximum size of a struct", stats.s_sbmax); - -	if (stats.s_types[CTF_K_STRUCT] != 0) { -		fp_stat("average number of struct members", -		    (float)stats.s_nsmem / (float)stats.s_types[CTF_K_STRUCT]); -		fp_stat("average size of a struct", (float)stats.s_nsbytes / -		    (float)stats.s_types[CTF_K_STRUCT]); -	} - -	(void) printf("\n"); - -	long_stat("total number of union members", stats.s_numem); -	long_stat("maximum number of union members", stats.s_ummax); -	long_stat("total size of all unions", stats.s_nubytes); -	long_stat("maximum size of a union", stats.s_ubmax); - -	if (stats.s_types[CTF_K_UNION] != 0) { -		fp_stat("average number of union members", -		    (float)stats.s_numem / (float)stats.s_types[CTF_K_UNION]); -		fp_stat("average size of a union", (float)stats.s_nubytes / -		    (float)stats.s_types[CTF_K_UNION]); -	} - -	(void) printf("\n"); - -	long_stat("total number of enum members", stats.s_nemem); -	long_stat("maximum number of enum members", stats.s_emmax); - -	if (stats.s_types[CTF_K_ENUM] != 0) { -		fp_stat("average number of enum members", -		    (float)stats.s_nemem / (float)stats.s_types[CTF_K_ENUM]); -	} - -	(void) printf("\n"); - -	long_stat("total number of unique strings", stats.s_nstr); -	long_stat("bytes of string data", stats.s_strlen); -	long_stat("maximum string length", stats.s_strmax); - -	if (stats.s_nstr != 0) { -		fp_stat("average string length", -		    (float)stats.s_strlen / (float)stats.s_nstr); -	} - -	(void) printf("\n"); -	return (E_SUCCESS); -} - -static int -print_usage(FILE *fp, int verbose) -{ -	(void) fprintf(fp, "Usage: %s [-dfhlsSt] [-u file] file\n", getpname()); - -	if (verbose) { -		(void) fprintf(fp, -		    "\t-d  dump data object section\n" -		    "\t-f  dump function section\n" -		    "\t-h  dump file header\n" -		    "\t-l  dump label table\n" -		    "\t-s  dump string table\n" -		    "\t-S  dump statistics\n" -		    "\t-t  dump type section\n" -		    "\t-u  save uncompressed CTF to a file\n"); -	} - -	return (E_USAGE); -} - -static Elf_Scn * -findelfscn(Elf *elf, GElf_Ehdr *ehdr, char *secname) -{ -	GElf_Shdr shdr; -	Elf_Scn *scn; -	char *name; - -	for (scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; ) { -		if (gelf_getshdr(scn, &shdr) != NULL && (name = -		    elf_strptr(elf, ehdr->e_shstrndx, shdr.sh_name)) != NULL && -		    strcmp(name, secname) == 0) -			return (scn); -	} - -	return (NULL); -} - -int -main(int argc, char *argv[]) -{ -	const char *filename = NULL; -	const char *ufile = NULL; -	int error = 0; -	int c, fd, ufd; - -	ctf_data_t cd; -	const ctf_preamble_t *pp; -	ctf_header_t *hp; -	Elf *elf; -	GElf_Ehdr ehdr; - -	(void) elf_version(EV_CURRENT); - -	for (opterr = 0; optind < argc; optind++) { -		while ((c = getopt(argc, argv, "dfhlsStu:")) != (int)EOF) { -			switch (c) { -			case 'd': -				flags |= F_DATA; -				break; -			case 'f': -				flags |= F_FUNC; -				break; -			case 'h': -				flags |= F_HDR; -				break; -			case 'l': -				flags |= F_LABEL; -				break; -			case 's': -				flags |= F_STR; -				break; -			case 'S': -				flags |= F_STATS; -				break; -			case 't': -				flags |= F_TYPES; -				break; -			case 'u': -				ufile = optarg; -				break; -			default: -				if (optopt == '?') -					return (print_usage(stdout, 1)); -				warn("illegal option -- %c\n", optopt); -				return (print_usage(stderr, 0)); -			} -		} - -		if (optind < argc) { -			if (filename != NULL) -				return (print_usage(stderr, 0)); -			filename = argv[optind]; -		} -	} - -	if (filename == NULL) -		return (print_usage(stderr, 0)); - -	if (flags == 0 && ufile == NULL) -		flags = F_ALLMSK; - -	if ((fd = open(filename, O_RDONLY)) == -1) -		die("failed to open %s", filename); - -	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) != NULL && -	    gelf_getehdr(elf, &ehdr) != NULL) { - -		Elf_Data *dp; -		Elf_Scn *ctfscn = findelfscn(elf, &ehdr, ".SUNW_ctf"); -		Elf_Scn *symscn; -		GElf_Shdr ctfshdr; - -		if (ctfscn == NULL || (dp = elf_getdata(ctfscn, NULL)) == NULL) -			die("%s does not contain .SUNW_ctf data\n", filename); - -		cd.cd_ctfdata = dp->d_buf; -		cd.cd_ctflen = dp->d_size; - -		/* -		 * If the sh_link field of the CTF section header is non-zero -		 * it indicates which section contains the symbol table that -		 * should be used. We default to the .symtab section if sh_link -		 * is zero or if there's an error reading the section header. -		 */ -		if (gelf_getshdr(ctfscn, &ctfshdr) != NULL && -		    ctfshdr.sh_link != 0) { -			symscn = elf_getscn(elf, ctfshdr.sh_link); -		} else { -			symscn = findelfscn(elf, &ehdr, ".symtab"); -		} - -		/* If we found a symbol table, find the corresponding strings */ -		if (symscn != NULL) { -			GElf_Shdr shdr; -			Elf_Scn *symstrscn; - -			if (gelf_getshdr(symscn, &shdr) != NULL) { -				symstrscn = elf_getscn(elf, shdr.sh_link); - -				cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize; -				cd.cd_symdata = elf_getdata(symscn, NULL); -				cd.cd_strdata = elf_getdata(symstrscn, NULL); -			} -		} -	} else { -		struct stat st; - -		if (fstat(fd, &st) == -1) -			die("failed to fstat %s", filename); - -		cd.cd_ctflen = st.st_size; -		cd.cd_ctfdata = mmap(NULL, cd.cd_ctflen, PROT_READ, -		    MAP_PRIVATE, fd, 0); -		if (cd.cd_ctfdata == MAP_FAILED) -			die("failed to mmap %s", filename); -	} - -	/* -	 * Get a pointer to the CTF data buffer and interpret the first portion -	 * as a ctf_header_t.  Validate the magic number and size. -	 */ - -	if (cd.cd_ctflen < sizeof (ctf_preamble_t)) -		die("%s does not contain a CTF preamble\n", filename); - -	/* LINTED - pointer alignment */ -	pp = (const ctf_preamble_t *)cd.cd_ctfdata; - -	if (pp->ctp_magic != CTF_MAGIC) -		die("%s does not appear to contain CTF data\n", filename); - -	if (pp->ctp_version == CTF_VERSION) { -		/* LINTED - pointer alignment */ -		hp = (ctf_header_t *)cd.cd_ctfdata; -		cd.cd_ctfdata = (caddr_t)cd.cd_ctfdata + sizeof (ctf_header_t); - -		if (cd.cd_ctflen < sizeof (ctf_header_t)) { -			die("%s does not contain a v%d CTF header\n", filename, -			    CTF_VERSION); -		} - -	} else { -		die("%s contains unsupported CTF version %d\n", filename, -		    pp->ctp_version); -	} - -	/* -	 * If the data buffer is compressed, then malloc a buffer large enough -	 * to hold the decompressed data, and use zlib to decompress it. -	 */ -	if (hp->cth_flags & CTF_F_COMPRESS) { -		z_stream zstr; -		void *buf; -		int rc; - -		if ((buf = malloc(hp->cth_stroff + hp->cth_strlen)) == NULL) -			die("failed to allocate decompression buffer"); - -		bzero(&zstr, sizeof (z_stream)); -		zstr.next_in = (void *)cd.cd_ctfdata; -		zstr.avail_in = cd.cd_ctflen; -		zstr.next_out = buf; -		zstr.avail_out = hp->cth_stroff + hp->cth_strlen; - -		if ((rc = inflateInit(&zstr)) != Z_OK) -			die("failed to initialize zlib: %s\n", zError(rc)); - -		if ((rc = inflate(&zstr, Z_FINISH)) != Z_STREAM_END) -			die("failed to decompress CTF data: %s\n", zError(rc)); - -		if ((rc = inflateEnd(&zstr)) != Z_OK) -			die("failed to finish decompression: %s\n", zError(rc)); - -		if (zstr.total_out != hp->cth_stroff + hp->cth_strlen) -			die("CTF data is corrupt -- short decompression\n"); - -		cd.cd_ctfdata = buf; -		cd.cd_ctflen = hp->cth_stroff + hp->cth_strlen; -	} - -	if (flags & F_HDR) -		error |= print_header(hp, &cd); -	if (flags & (F_LABEL)) -		error |= print_labeltable(hp, &cd); -	if (flags & (F_DATA | F_STATS)) -		error |= read_data(hp, &cd); -	if (flags & (F_FUNC | F_STATS)) -		error |= read_funcs(hp, &cd); -	if (flags & (F_TYPES | F_STATS)) -		error |= read_types(hp, &cd); -	if (flags & (F_STR | F_STATS)) -		error |= read_strtab(hp, &cd); -	if (flags & F_STATS) -		error |= print_stats(); - -	/* -	 * If the -u option is specified, write the uncompressed CTF data to a -	 * raw CTF file.  CTF data can already be extracted compressed by -	 * applying elfdump -w -N .SUNW_ctf to an ELF file, so we don't bother. -	 */ -	if (ufile != NULL) { -		ctf_header_t h; - -		bcopy(hp, &h, sizeof (h)); -		h.cth_flags &= ~CTF_F_COMPRESS; - -		if ((ufd = open(ufile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0 || -		    write(ufd, &h, sizeof (h)) != sizeof (h) || -		    write(ufd, cd.cd_ctfdata, cd.cd_ctflen) != cd.cd_ctflen) { -			warn("failed to write CTF data to '%s'", ufile); -			error |= E_ERROR; -		} - -		(void) close(ufd); -	} - -	if (elf != NULL) -		(void) elf_end(elf); - -	(void) close(fd); -	return (error); -} | 
