• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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