summaryrefslogtreecommitdiff
path: root/cxxfilt/cxxfilt.c
diff options
context:
space:
mode:
Diffstat (limited to 'cxxfilt/cxxfilt.c')
-rw-r--r--cxxfilt/cxxfilt.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/cxxfilt/cxxfilt.c b/cxxfilt/cxxfilt.c
new file mode 100644
index 0000000000000..d30cfaeffdd77
--- /dev/null
+++ b/cxxfilt/cxxfilt.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2009 Kai Wang
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <ctype.h>
+#include <err.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: cxxfilt.c 2185 2011-11-19 16:07:16Z jkoshy $");
+
+#define STRBUFSZ 8192
+
+static int stripus = 0;
+static int noparam = 0;
+static int format = 0;
+
+enum options
+{
+ OPTION_HELP,
+ OPTION_VERSION
+};
+
+static struct option longopts[] =
+{
+ {"format", required_argument, NULL, 's'},
+ {"help", no_argument, NULL, OPTION_HELP},
+ {"no-params", no_argument, NULL, 'p'},
+ {"no-strip-underscores", no_argument, NULL, 'n'},
+ {"strip-underscores", no_argument, NULL, '_'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+};
+
+static struct {
+ const char *fname;
+ int fvalue;
+} flist[] = {
+ {"auto", 0},
+ {"arm", ELFTC_DEM_ARM},
+ {"gnu", ELFTC_DEM_GNU2},
+ {"gnu-v3", ELFTC_DEM_GNU3}
+};
+
+#define USAGE_MESSAGE "\
+Usage: %s [options] [encoded-names...]\n\
+ Translate C++ symbol names to human-readable form.\n\n\
+ Options:\n\
+ -_ | --strip-underscores Remove leading underscores prior to decoding.\n\
+ -n | --no-strip-underscores Do not remove leading underscores.\n\
+ -p | --no-params (Accepted but ignored).\n\
+ -s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\
+ Valid schemes are: 'arm', 'auto', 'gnu' and\n\
+ 'gnu-v3'.\n\
+ --help Print a help message.\n\
+ --version Print a version identifier and exit.\n"
+
+static void
+usage(void)
+{
+
+ (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+ exit(1);
+}
+
+static void
+version(void)
+{
+ fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+ exit(0);
+}
+
+static int
+find_format(const char *fstr)
+{
+ int i;
+
+ for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) {
+ if (!strcmp(fstr, flist[i].fname))
+ return (flist[i].fvalue);
+ }
+
+ return (-1);
+}
+
+static char *
+demangle(char *name, int strict, int *pos)
+{
+ static char dem[STRBUFSZ];
+ char nb[STRBUFSZ];
+ int p, t;
+
+ if (stripus && *name == '_') {
+ strncpy(nb, name + 1, sizeof(nb) - 1);
+ t = 1;
+ } else {
+ strncpy(nb, name, sizeof(nb) - 1);
+ t = 0;
+ }
+ nb[sizeof(nb) - 1] = '\0';
+
+ p = strlen(nb);
+ if (p <= 0)
+ return NULL;
+
+ while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) {
+ if (!strict && p > 1) {
+ nb[--p] = '\0';
+ continue;
+ } else
+ return (NULL);
+ }
+
+ if (pos != NULL)
+ *pos = t ? p + 1 : p;
+
+ return (dem);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *dem, buf[STRBUFSZ];
+ int c, i, p, s, opt;
+
+ while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) !=
+ -1) {
+ switch (opt) {
+ case '_':
+ stripus = 1;
+ break;
+ case 'n':
+ stripus = 0;
+ break;
+ case 'p':
+ noparam = 1;
+ break;
+ case 's':
+ if ((format = find_format(optarg)) < 0)
+ errx(EXIT_FAILURE, "unsupported format: %s",
+ optarg);
+ break;
+ case 'V':
+ version();
+ /* NOT REACHED */
+ case OPTION_HELP:
+ default:
+ usage();
+ /* NOT REACHED */
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (*argv != NULL) {
+ for (i = 0; i < argc; i++) {
+ if ((dem = demangle(argv[i], 1, NULL)) == NULL)
+ fprintf(stderr, "Failed: %s\n", argv[i]);
+ else
+ printf("%s\n", dem);
+ }
+ } else {
+ p = 0;
+ for (;;) {
+ c = fgetc(stdin);
+ if (c == EOF || !isprint(c) || strchr(" \t\n", c)) {
+ if (p > 0) {
+ buf[p] = '\0';
+ if ((dem = demangle(buf, 0, &s)) ==
+ NULL)
+ printf("%s", buf);
+ else {
+ printf("%s", dem);
+ for (i = s; i < p; i++)
+ putchar(buf[i]);
+ }
+ p = 0;
+ }
+ if (c == EOF)
+ break;
+ if (isprint(c) || strchr(" \t\n", c))
+ putchar(c);
+ } else {
+ if ((size_t) p >= sizeof(buf) - 1)
+ warnx("buffer overflowed");
+ else
+ buf[p++] = c;
+ }
+
+ }
+ }
+
+ exit(0);
+}