xref: /onnv-gate/usr/src/cmd/dis/dis_util.c (revision 1545:8f6fb1eeee38)
1*1545Seschrock /*
2*1545Seschrock  * CDDL HEADER START
3*1545Seschrock  *
4*1545Seschrock  * The contents of this file are subject to the terms of the
5*1545Seschrock  * Common Development and Distribution License (the "License").
6*1545Seschrock  * You may not use this file except in compliance with the License.
7*1545Seschrock  *
8*1545Seschrock  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1545Seschrock  * or http://www.opensolaris.org/os/licensing.
10*1545Seschrock  * See the License for the specific language governing permissions
11*1545Seschrock  * and limitations under the License.
12*1545Seschrock  *
13*1545Seschrock  * When distributing Covered Code, include this CDDL HEADER in each
14*1545Seschrock  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1545Seschrock  * If applicable, add the following below this CDDL HEADER, with the
16*1545Seschrock  * fields enclosed by brackets "[]" replaced with your own identifying
17*1545Seschrock  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1545Seschrock  *
19*1545Seschrock  * CDDL HEADER END
20*1545Seschrock  */
21*1545Seschrock 
22*1545Seschrock /*
23*1545Seschrock  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*1545Seschrock  * Use is subject to license terms.
25*1545Seschrock  */
26*1545Seschrock 
27*1545Seschrock #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*1545Seschrock 
29*1545Seschrock #include <dlfcn.h>
30*1545Seschrock #include <stdarg.h>
31*1545Seschrock #include <stdio.h>
32*1545Seschrock #include <stdlib.h>
33*1545Seschrock #include <demangle.h>
34*1545Seschrock 
35*1545Seschrock #include "dis_util.h"
36*1545Seschrock 
37*1545Seschrock int g_error;	/* global process exit status, set when warn() is called */
38*1545Seschrock 
39*1545Seschrock /*
40*1545Seschrock  * Fatal error.  Print out the error with a leading "dis: ", and then exit the
41*1545Seschrock  * program.
42*1545Seschrock  */
43*1545Seschrock void
die(const char * fmt,...)44*1545Seschrock die(const char *fmt, ...)
45*1545Seschrock {
46*1545Seschrock 	va_list ap;
47*1545Seschrock 
48*1545Seschrock 	(void) fprintf(stderr, "dis: fatal: ");
49*1545Seschrock 
50*1545Seschrock 	va_start(ap, fmt);
51*1545Seschrock 	(void) vfprintf(stderr, fmt, ap);
52*1545Seschrock 	va_end(ap);
53*1545Seschrock 
54*1545Seschrock 	(void) fprintf(stderr, "\n");
55*1545Seschrock 
56*1545Seschrock 	exit(1);
57*1545Seschrock }
58*1545Seschrock 
59*1545Seschrock /*
60*1545Seschrock  * Non-fatal error.  Print out the error with a leading "dis: ", set the global
61*1545Seschrock  * error flag, and return.
62*1545Seschrock  */
63*1545Seschrock void
warn(const char * fmt,...)64*1545Seschrock warn(const char *fmt, ...)
65*1545Seschrock {
66*1545Seschrock 	va_list ap;
67*1545Seschrock 
68*1545Seschrock 	(void) fprintf(stderr, "dis: warning: ");
69*1545Seschrock 
70*1545Seschrock 	va_start(ap, fmt);
71*1545Seschrock 	(void) vfprintf(stderr, fmt, ap);
72*1545Seschrock 	va_end(ap);
73*1545Seschrock 
74*1545Seschrock 	(void) fprintf(stderr, "\n");
75*1545Seschrock 
76*1545Seschrock 	g_error = 1;
77*1545Seschrock }
78*1545Seschrock 
79*1545Seschrock /*
80*1545Seschrock  * Convenience wrapper around malloc() to cleanly exit if any allocation fails.
81*1545Seschrock  */
82*1545Seschrock void *
safe_malloc(size_t size)83*1545Seschrock safe_malloc(size_t size)
84*1545Seschrock {
85*1545Seschrock 	void *ret;
86*1545Seschrock 
87*1545Seschrock 	if ((ret = calloc(1, size)) == NULL)
88*1545Seschrock 		die("Out of memory");
89*1545Seschrock 
90*1545Seschrock 	return (ret);
91*1545Seschrock }
92*1545Seschrock 
93*1545Seschrock 
94*1545Seschrock /*
95*1545Seschrock  * Generic interface to demangle C++ names.  Calls cplus_demangle to do the
96*1545Seschrock  * necessary translation.  If the translation fails, the argument is returned
97*1545Seschrock  * unchanged.  The memory returned is only valid until the next call to
98*1545Seschrock  * demangle().
99*1545Seschrock  *
100*1545Seschrock  * We dlopen() libdemangle.so rather than linking directly against it in case it
101*1545Seschrock  * is not installed on the system.
102*1545Seschrock  */
103*1545Seschrock const char *
dis_demangle(const char * name)104*1545Seschrock dis_demangle(const char *name)
105*1545Seschrock {
106*1545Seschrock 	static char *demangled_name;
107*1545Seschrock 	static int (*demangle_func)() = NULL;
108*1545Seschrock 	static int size = BUFSIZE;
109*1545Seschrock 	static int first_flag = 0;
110*1545Seschrock 	int ret;
111*1545Seschrock 
112*1545Seschrock 	/*
113*1545Seschrock 	 * If this is the first call, allocate storage
114*1545Seschrock 	 * for the buffer.
115*1545Seschrock 	 */
116*1545Seschrock 	if (first_flag == 0) {
117*1545Seschrock 		void *demangle_hand;
118*1545Seschrock 
119*1545Seschrock 		demangle_hand = dlopen("libdemangle.so.1", RTLD_LAZY);
120*1545Seschrock 		if (demangle_hand != NULL)
121*1545Seschrock 			demangle_func = (int (*)(int))dlsym(
122*1545Seschrock 				demangle_hand, "cplus_demangle");
123*1545Seschrock 
124*1545Seschrock 		demangled_name = safe_malloc(size);
125*1545Seschrock 		first_flag = 1;
126*1545Seschrock 	}
127*1545Seschrock 
128*1545Seschrock 	/*
129*1545Seschrock 	 * If libdemangle is not present, pass through unchanged.
130*1545Seschrock 	 */
131*1545Seschrock 	if (demangle_func == NULL)
132*1545Seschrock 		return (name);
133*1545Seschrock 
134*1545Seschrock 	/*
135*1545Seschrock 	 * The function returns -1 when the buffer size is not sufficient.
136*1545Seschrock 	 */
137*1545Seschrock 	while ((ret = (*demangle_func)(name, demangled_name, size)) == -1) {
138*1545Seschrock 		free(demangled_name);
139*1545Seschrock 		size = size + BUFSIZE;
140*1545Seschrock 		demangled_name = safe_malloc(size);
141*1545Seschrock 	}
142*1545Seschrock 
143*1545Seschrock 	if (ret != 0)
144*1545Seschrock 		return (name);
145*1545Seschrock 
146*1545Seschrock 	return (demangled_name);
147*1545Seschrock }
148