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 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 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 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 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 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 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 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 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 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 235 string const demangle_java_symbol(string const & name) 236 { 237 return demangle_symbol(name.begin(), name.end()); 238 } 239