1 /**
2 * @file demangle_java_symbol.cpp
3 * Demangle a java symbol
4 *
5 * @remark Copyright 2007 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Philippe Elie
9 */
10
11 #include "demangle_java_symbol.h"
12
13 #include <algorithm>
14
15 using namespace std;
16
17 namespace {
18
19 /**
20 * The grammar we implement:
21 *
22 * field_type:
23 * base_type | object_type | array_type
24 * base_type:
25 * B | C | D | F | I | J | S | Z
26 * object_type:
27 * L<classname>;
28 * array_type:
29 * [field_type
30 * method_descriptor:
31 * ( field_type* ) return_descriptor
32 * return_descriptor:
33 * field_type | V
34 * method_signature:
35 * object_type method_name method_descriptor
36 *
37 */
38
39 bool array_type(string & result,
40 string::const_iterator & begin, string::const_iterator end);
41 bool object_type(string & result,
42 string::const_iterator & begin, string::const_iterator end);
43
44
base_type(string & result,string::const_iterator & begin,string::const_iterator end)45 bool base_type(string & result,
46 string::const_iterator & begin, string::const_iterator end)
47 {
48 bool ret = true;
49
50 if (begin == end)
51 return false;
52
53 switch (*begin) {
54 case 'B': result += "byte"; break;
55 case 'C': result += "char"; break;
56 case 'D': result += "double"; break;
57 case 'F': result += "float"; break;
58 case 'I': result += "int"; break;
59 case 'J': result += "long"; break;
60 case 'S': result += "short"; break;
61 case 'Z': result += "boolean"; break;
62 default: ret = false; break;
63 }
64
65 if (ret)
66 ++begin;
67 return ret;
68 }
69
70
field_type(string & result,string::const_iterator & begin,string::const_iterator end)71 bool field_type(string & result,
72 string::const_iterator & begin, string::const_iterator end)
73 {
74 if (base_type(result, begin, end))
75 return true;
76
77 if (object_type(result, begin, end))
78 return true;
79
80 if (array_type(result, begin, end))
81 return true;
82
83 return false;
84 }
85
86
array_type(string & result,string::const_iterator & begin,string::const_iterator end)87 bool array_type(string & result,
88 string::const_iterator & begin, string::const_iterator end)
89 {
90 if (begin == end || *begin != '[')
91 return false;
92
93 ++begin;
94 if (field_type(result, begin, end)) {
95 result += "[]";
96 return true;
97 }
98
99 return false;
100 }
101
102
list_of_field_type(string & result,string::const_iterator & begin,string::const_iterator end)103 bool list_of_field_type(string & result,
104 string::const_iterator & begin, string::const_iterator end)
105 {
106 bool first = false;
107 while (begin != end) {
108 if (first)
109 result += ", ";
110
111 if (!field_type(result, begin, end))
112 return false;
113
114 first = true;
115 }
116
117 return true;
118 }
119
120
return_descriptor(string & result,string::const_iterator & begin,string::const_iterator end)121 bool return_descriptor(string & result,
122 string::const_iterator & begin, string::const_iterator end)
123 {
124 if (begin == end)
125 return false;
126 if (*begin == 'V') {
127 ++begin;
128 result = "void " + result;
129 return true;
130 }
131
132 string temp;
133 if (!field_type(temp, begin, end))
134 return false;
135 result = temp + " " + result;
136
137 return true;
138 }
139
140
method_descriptor(string & result,string::const_iterator & begin,string::const_iterator end)141 bool method_descriptor(string & result,
142 string::const_iterator & begin, string::const_iterator end)
143 {
144 if (begin == end || *begin != '(')
145 return false;
146 ++begin;
147 string::const_iterator pos = find(begin, end, ')');
148 if (pos == end)
149 return false;
150
151 result += "(";
152
153 if (!list_of_field_type(result, begin, pos))
154 return false;
155
156 if (begin == end || *begin != ')')
157 return false;
158
159 ++begin;
160
161 if (!return_descriptor(result, begin, end))
162 return false;
163
164 result += ')';
165
166 return true;
167 }
168
169
methode_name(string & result,string::const_iterator & begin,string::const_iterator end)170 bool methode_name(string & result,
171 string::const_iterator & begin, string::const_iterator end)
172 {
173 if (begin == end)
174 return false;
175
176 string::const_iterator pos = find(begin, end, '(');
177 if (pos == end)
178 return false;
179
180 result += '.' + string(begin, pos);
181 begin = pos;
182
183 return true;
184 }
185
186
object_type(string & result,string::const_iterator & begin,string::const_iterator end)187 bool object_type(string & result,
188 string::const_iterator & begin, string::const_iterator end)
189 {
190 if (begin == end || *begin != 'L')
191 return false;
192 string::const_iterator pos = find(begin, end, ';');
193 if (pos == end)
194 return false;
195
196 string temp = string(begin + 1, pos);
197 replace(temp.begin(), temp.end(), '/', '.');
198 result += temp;
199
200 begin = pos + 1;
201
202 return true;
203 }
204
205
demangle_symbol(string::const_iterator begin,string::const_iterator end)206 string demangle_symbol(string::const_iterator begin,
207 string::const_iterator end)
208 {
209 string result;
210
211 if (!object_type(result, begin, end))
212 return string();
213
214 if (!methode_name(result, begin, end))
215 return string();
216
217 if (!method_descriptor(result, begin, end))
218 return string();
219
220 if (begin != end) {
221 if (*begin == '~') {
222 // special case for disambiguated symbol.
223 result += string(begin, end);
224 } else {
225 return string();
226 }
227 }
228
229 return result;
230 }
231
232 } // anonymous namespace
233
234
demangle_java_symbol(string const & name)235 string const demangle_java_symbol(string const & name)
236 {
237 return demangle_symbol(name.begin(), name.end());
238 }
239