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