0001
0002 #include <sys/types.h>
0003 #include <stdio.h>
0004 #include <stdlib.h>
0005 #include <string.h>
0006 #include "symbol.h"
0007
0008 #include "demangle-java.h"
0009
0010 #include <linux/ctype.h>
0011 #include <linux/kernel.h>
0012
0013 enum {
0014 MODE_PREFIX = 0,
0015 MODE_CLASS = 1,
0016 MODE_FUNC = 2,
0017 MODE_TYPE = 3,
0018 MODE_CTYPE = 4,
0019 };
0020
0021 #define BASE_ENT(c, n) [c - 'A']=n
0022 static const char *base_types['Z' - 'A' + 1] = {
0023 BASE_ENT('B', "byte" ),
0024 BASE_ENT('C', "char" ),
0025 BASE_ENT('D', "double" ),
0026 BASE_ENT('F', "float" ),
0027 BASE_ENT('I', "int" ),
0028 BASE_ENT('J', "long" ),
0029 BASE_ENT('S', "short" ),
0030 BASE_ENT('Z', "boolean" ),
0031 };
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 static char *
0045 __demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode)
0046 {
0047 int rlen = 0;
0048 int array = 0;
0049 int narg = 0;
0050 const char *q;
0051
0052 if (!end)
0053 end = str + strlen(str);
0054
0055 for (q = str; q != end; q++) {
0056
0057 if (rlen == (maxlen - 1))
0058 break;
0059
0060 switch (*q) {
0061 case 'L':
0062 if (mode == MODE_PREFIX || mode == MODE_TYPE) {
0063 if (mode == MODE_TYPE) {
0064 if (narg)
0065 rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
0066 narg++;
0067 }
0068 if (mode == MODE_PREFIX)
0069 mode = MODE_CLASS;
0070 else
0071 mode = MODE_CTYPE;
0072 } else
0073 buf[rlen++] = *q;
0074 break;
0075 case 'B':
0076 case 'C':
0077 case 'D':
0078 case 'F':
0079 case 'I':
0080 case 'J':
0081 case 'S':
0082 case 'Z':
0083 if (mode == MODE_TYPE) {
0084 if (narg)
0085 rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
0086 rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']);
0087 while (array--)
0088 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
0089 array = 0;
0090 narg++;
0091 } else
0092 buf[rlen++] = *q;
0093 break;
0094 case 'V':
0095 if (mode == MODE_TYPE) {
0096 rlen += scnprintf(buf + rlen, maxlen - rlen, "void");
0097 while (array--)
0098 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
0099 array = 0;
0100 } else
0101 buf[rlen++] = *q;
0102 break;
0103 case '[':
0104 if (mode != MODE_TYPE)
0105 goto error;
0106 array++;
0107 break;
0108 case '(':
0109 if (mode != MODE_FUNC)
0110 goto error;
0111 buf[rlen++] = *q;
0112 mode = MODE_TYPE;
0113 break;
0114 case ')':
0115 if (mode != MODE_TYPE)
0116 goto error;
0117 buf[rlen++] = *q;
0118 narg = 0;
0119 break;
0120 case ';':
0121 if (mode != MODE_CLASS && mode != MODE_CTYPE)
0122 goto error;
0123
0124 if (isalpha(*(q + 1)) && mode == MODE_CLASS)
0125 rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
0126 if (mode == MODE_CLASS)
0127 mode = MODE_FUNC;
0128 else if (mode == MODE_CTYPE)
0129 mode = MODE_TYPE;
0130 break;
0131 case '/':
0132 if (mode != MODE_CLASS && mode != MODE_CTYPE)
0133 goto error;
0134 rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
0135 break;
0136 default :
0137 buf[rlen++] = *q;
0138 }
0139 }
0140 buf[rlen] = '\0';
0141 return buf;
0142 error:
0143 return NULL;
0144 }
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 char *
0158 java_demangle_sym(const char *str, int flags)
0159 {
0160 char *buf, *ptr;
0161 char *p;
0162 size_t len, l1 = 0;
0163
0164 if (!str)
0165 return NULL;
0166
0167
0168 p = strrchr(str, ')');
0169 if (!p)
0170 return NULL;
0171
0172
0173
0174
0175 len = strlen(str) * 3 + 1;
0176 buf = malloc(len);
0177 if (!buf)
0178 return NULL;
0179
0180 buf[0] = '\0';
0181 if (!(flags & JAVA_DEMANGLE_NORET)) {
0182
0183
0184
0185 ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE);
0186 if (!ptr)
0187 goto error;
0188
0189
0190 l1 = strlen(buf);
0191 buf[l1++] = ' ';
0192 }
0193
0194
0195 ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX);
0196 if (!ptr)
0197 goto error;
0198
0199 return buf;
0200 error:
0201 free(buf);
0202 return NULL;
0203 }