1
2#include <sys/types.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include "debug.h"
7#include "symbol.h"
8
9#include "demangle-java.h"
10
11#include <linux/ctype.h>
12#include <linux/kernel.h>
13
14enum {
15 MODE_PREFIX = 0,
16 MODE_CLASS = 1,
17 MODE_FUNC = 2,
18 MODE_TYPE = 3,
19 MODE_CTYPE = 3,
20};
21
22#define BASE_ENT(c, n) [c - 'A']=n
23static const char *base_types['Z' - 'A' + 1] = {
24 BASE_ENT('B', "byte" ),
25 BASE_ENT('C', "char" ),
26 BASE_ENT('D', "double" ),
27 BASE_ENT('F', "float" ),
28 BASE_ENT('I', "int" ),
29 BASE_ENT('J', "long" ),
30 BASE_ENT('S', "short" ),
31 BASE_ENT('Z', "bool" ),
32};
33
34
35
36
37
38
39
40
41
42
43
44
45static char *
46__demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode)
47{
48 int rlen = 0;
49 int array = 0;
50 int narg = 0;
51 const char *q;
52
53 if (!end)
54 end = str + strlen(str);
55
56 for (q = str; q != end; q++) {
57
58 if (rlen == (maxlen - 1))
59 break;
60
61 switch (*q) {
62 case 'L':
63 if (mode == MODE_PREFIX || mode == MODE_CTYPE) {
64 if (mode == MODE_CTYPE) {
65 if (narg)
66 rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
67 narg++;
68 }
69 rlen += scnprintf(buf + rlen, maxlen - rlen, "class ");
70 if (mode == MODE_PREFIX)
71 mode = MODE_CLASS;
72 } else
73 buf[rlen++] = *q;
74 break;
75 case 'B':
76 case 'C':
77 case 'D':
78 case 'F':
79 case 'I':
80 case 'J':
81 case 'S':
82 case 'Z':
83 if (mode == MODE_TYPE) {
84 if (narg)
85 rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
86 rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']);
87 while (array--)
88 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
89 array = 0;
90 narg++;
91 } else
92 buf[rlen++] = *q;
93 break;
94 case 'V':
95 if (mode == MODE_TYPE) {
96 rlen += scnprintf(buf + rlen, maxlen - rlen, "void");
97 while (array--)
98 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
99 array = 0;
100 } else
101 buf[rlen++] = *q;
102 break;
103 case '[':
104 if (mode != MODE_TYPE)
105 goto error;
106 array++;
107 break;
108 case '(':
109 if (mode != MODE_FUNC)
110 goto error;
111 buf[rlen++] = *q;
112 mode = MODE_TYPE;
113 break;
114 case ')':
115 if (mode != MODE_TYPE)
116 goto error;
117 buf[rlen++] = *q;
118 narg = 0;
119 break;
120 case ';':
121 if (mode != MODE_CLASS && mode != MODE_CTYPE)
122 goto error;
123
124 if (isalpha(*(q + 1)))
125 rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
126 if (mode == MODE_CLASS)
127 mode = MODE_FUNC;
128 else if (mode == MODE_CTYPE)
129 mode = MODE_TYPE;
130 break;
131 case '/':
132 if (mode != MODE_CLASS && mode != MODE_CTYPE)
133 goto error;
134 rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
135 break;
136 default :
137 buf[rlen++] = *q;
138 }
139 }
140 buf[rlen] = '\0';
141 return buf;
142error:
143 return NULL;
144}
145
146
147
148
149
150
151
152
153
154
155
156
157char *
158java_demangle_sym(const char *str, int flags)
159{
160 char *buf, *ptr;
161 char *p;
162 size_t len, l1 = 0;
163
164 if (!str)
165 return NULL;
166
167
168 p = strrchr(str, ')');
169 if (!p)
170 return NULL;
171
172
173
174
175 len = strlen(str) * 3 + 1;
176 buf = malloc(len);
177 if (!buf)
178 return NULL;
179
180 buf[0] = '\0';
181 if (!(flags & JAVA_DEMANGLE_NORET)) {
182
183
184
185 ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE);
186 if (!ptr)
187 goto error;
188
189
190 l1 = strlen(buf);
191 buf[l1++] = ' ';
192 }
193
194
195 ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX);
196 if (!ptr)
197 goto error;
198
199 return buf;
200error:
201 free(buf);
202 return NULL;
203}
204