1 // SPDX-License-Identifier: GPL-2.0 << 2 #include <sys/types.h> 1 #include <sys/types.h> 3 #include <stdio.h> 2 #include <stdio.h> 4 #include <stdlib.h> << 5 #include <string.h> 3 #include <string.h> >> 4 #include "util.h" >> 5 #include "debug.h" 6 #include "symbol.h" 6 #include "symbol.h" 7 7 8 #include "demangle-java.h" 8 #include "demangle-java.h" 9 9 10 #include <linux/ctype.h> !! 10 #include "sane_ctype.h" 11 #include <linux/kernel.h> << 12 11 13 enum { 12 enum { 14 MODE_PREFIX = 0, 13 MODE_PREFIX = 0, 15 MODE_CLASS = 1, 14 MODE_CLASS = 1, 16 MODE_FUNC = 2, 15 MODE_FUNC = 2, 17 MODE_TYPE = 3, 16 MODE_TYPE = 3, 18 MODE_CTYPE = 4, /* class arg */ !! 17 MODE_CTYPE = 3, /* class arg */ 19 }; 18 }; 20 19 21 #define BASE_ENT(c, n) [c - 'A']=n 20 #define BASE_ENT(c, n) [c - 'A']=n 22 static const char *base_types['Z' - 'A' + 1] = 21 static const char *base_types['Z' - 'A' + 1] = { 23 BASE_ENT('B', "byte" ), 22 BASE_ENT('B', "byte" ), 24 BASE_ENT('C', "char" ), 23 BASE_ENT('C', "char" ), 25 BASE_ENT('D', "double" ), 24 BASE_ENT('D', "double" ), 26 BASE_ENT('F', "float" ), 25 BASE_ENT('F', "float" ), 27 BASE_ENT('I', "int" ), 26 BASE_ENT('I', "int" ), 28 BASE_ENT('J', "long" ), 27 BASE_ENT('J', "long" ), 29 BASE_ENT('S', "short" ), 28 BASE_ENT('S', "short" ), 30 BASE_ENT('Z', "boolean" ), !! 29 BASE_ENT('Z', "bool" ), 31 }; 30 }; 32 31 33 /* 32 /* 34 * demangle Java symbol between str and end po 33 * demangle Java symbol between str and end positions and stores 35 * up to maxlen characters into buf. The parse 34 * up to maxlen characters into buf. The parser starts in mode. 36 * 35 * 37 * Use MODE_PREFIX to process entire prototype 36 * Use MODE_PREFIX to process entire prototype till end position 38 * Use MODE_TYPE to process return type if str 37 * Use MODE_TYPE to process return type if str starts on return type char 39 * 38 * 40 * Return: 39 * Return: 41 * success: buf 40 * success: buf 42 * error : NULL 41 * error : NULL 43 */ 42 */ 44 static char * 43 static char * 45 __demangle_java_sym(const char *str, const cha 44 __demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode) 46 { 45 { 47 int rlen = 0; 46 int rlen = 0; 48 int array = 0; 47 int array = 0; 49 int narg = 0; 48 int narg = 0; 50 const char *q; 49 const char *q; 51 50 52 if (!end) 51 if (!end) 53 end = str + strlen(str); 52 end = str + strlen(str); 54 53 55 for (q = str; q != end; q++) { 54 for (q = str; q != end; q++) { 56 55 57 if (rlen == (maxlen - 1)) 56 if (rlen == (maxlen - 1)) 58 break; 57 break; 59 58 60 switch (*q) { 59 switch (*q) { 61 case 'L': 60 case 'L': 62 if (mode == MODE_PREFI !! 61 if (mode == MODE_PREFIX || mode == MODE_CTYPE) { 63 if (mode == MO !! 62 if (mode == MODE_CTYPE) { 64 if (na 63 if (narg) 65 64 rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); 66 narg++ 65 narg++; 67 } 66 } >> 67 rlen += scnprintf(buf + rlen, maxlen - rlen, "class "); 68 if (mode == MO 68 if (mode == MODE_PREFIX) 69 mode = 69 mode = MODE_CLASS; 70 else << 71 mode = << 72 } else 70 } else 73 buf[rlen++] = 71 buf[rlen++] = *q; 74 break; 72 break; 75 case 'B': 73 case 'B': 76 case 'C': 74 case 'C': 77 case 'D': 75 case 'D': 78 case 'F': 76 case 'F': 79 case 'I': 77 case 'I': 80 case 'J': 78 case 'J': 81 case 'S': 79 case 'S': 82 case 'Z': 80 case 'Z': 83 if (mode == MODE_TYPE) 81 if (mode == MODE_TYPE) { 84 if (narg) 82 if (narg) 85 rlen + 83 rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); 86 rlen += scnpri 84 rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']); 87 while (array-- 85 while (array--) 88 rlen + 86 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]"); 89 array = 0; 87 array = 0; 90 narg++; 88 narg++; 91 } else 89 } else 92 buf[rlen++] = 90 buf[rlen++] = *q; 93 break; 91 break; 94 case 'V': 92 case 'V': 95 if (mode == MODE_TYPE) 93 if (mode == MODE_TYPE) { 96 rlen += scnpri 94 rlen += scnprintf(buf + rlen, maxlen - rlen, "void"); 97 while (array-- 95 while (array--) 98 rlen + 96 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]"); 99 array = 0; 97 array = 0; 100 } else 98 } else 101 buf[rlen++] = 99 buf[rlen++] = *q; 102 break; 100 break; 103 case '[': 101 case '[': 104 if (mode != MODE_TYPE) 102 if (mode != MODE_TYPE) 105 goto error; 103 goto error; 106 array++; 104 array++; 107 break; 105 break; 108 case '(': 106 case '(': 109 if (mode != MODE_FUNC) 107 if (mode != MODE_FUNC) 110 goto error; 108 goto error; 111 buf[rlen++] = *q; 109 buf[rlen++] = *q; 112 mode = MODE_TYPE; 110 mode = MODE_TYPE; 113 break; 111 break; 114 case ')': 112 case ')': 115 if (mode != MODE_TYPE) 113 if (mode != MODE_TYPE) 116 goto error; 114 goto error; 117 buf[rlen++] = *q; 115 buf[rlen++] = *q; 118 narg = 0; 116 narg = 0; 119 break; 117 break; 120 case ';': 118 case ';': 121 if (mode != MODE_CLASS 119 if (mode != MODE_CLASS && mode != MODE_CTYPE) 122 goto error; 120 goto error; 123 /* safe because at lea 121 /* safe because at least one other char to process */ 124 if (isalpha(*(q + 1)) !! 122 if (isalpha(*(q + 1))) 125 rlen += scnpri 123 rlen += scnprintf(buf + rlen, maxlen - rlen, "."); 126 if (mode == MODE_CLASS 124 if (mode == MODE_CLASS) 127 mode = MODE_FU 125 mode = MODE_FUNC; 128 else if (mode == MODE_ 126 else if (mode == MODE_CTYPE) 129 mode = MODE_TY 127 mode = MODE_TYPE; 130 break; 128 break; 131 case '/': 129 case '/': 132 if (mode != MODE_CLASS 130 if (mode != MODE_CLASS && mode != MODE_CTYPE) 133 goto error; 131 goto error; 134 rlen += scnprintf(buf 132 rlen += scnprintf(buf + rlen, maxlen - rlen, "."); 135 break; 133 break; 136 default : 134 default : 137 buf[rlen++] = *q; 135 buf[rlen++] = *q; 138 } 136 } 139 } 137 } 140 buf[rlen] = '\0'; 138 buf[rlen] = '\0'; 141 return buf; 139 return buf; 142 error: 140 error: 143 return NULL; 141 return NULL; 144 } 142 } 145 143 146 /* 144 /* 147 * Demangle Java function signature (openJDK, 145 * Demangle Java function signature (openJDK, not GCJ) 148 * input: 146 * input: 149 * str: string to parse. String is not mo 147 * str: string to parse. String is not modified 150 * flags: combination of JAVA_DEMANGLE_* fl !! 148 * flags: comobination of JAVA_DEMANGLE_* flags to modify demangling 151 * return: 149 * return: 152 * if input can be demangled, then a newl 150 * if input can be demangled, then a newly allocated string is returned. 153 * if input cannot be demangled, then NUL 151 * if input cannot be demangled, then NULL is returned 154 * 152 * 155 * Note: caller is responsible for freeing dem 153 * Note: caller is responsible for freeing demangled string 156 */ 154 */ 157 char * 155 char * 158 java_demangle_sym(const char *str, int flags) 156 java_demangle_sym(const char *str, int flags) 159 { 157 { 160 char *buf, *ptr; 158 char *buf, *ptr; 161 char *p; 159 char *p; 162 size_t len, l1 = 0; 160 size_t len, l1 = 0; 163 161 164 if (!str) 162 if (!str) 165 return NULL; 163 return NULL; 166 164 167 /* find start of return type */ !! 165 /* find start of retunr type */ 168 p = strrchr(str, ')'); 166 p = strrchr(str, ')'); 169 if (!p) 167 if (!p) 170 return NULL; 168 return NULL; 171 169 172 /* 170 /* 173 * expansion factor estimated to 3x 171 * expansion factor estimated to 3x 174 */ 172 */ 175 len = strlen(str) * 3 + 1; 173 len = strlen(str) * 3 + 1; 176 buf = malloc(len); 174 buf = malloc(len); 177 if (!buf) 175 if (!buf) 178 return NULL; 176 return NULL; 179 177 180 buf[0] = '\0'; 178 buf[0] = '\0'; 181 if (!(flags & JAVA_DEMANGLE_NORET)) { 179 if (!(flags & JAVA_DEMANGLE_NORET)) { 182 /* 180 /* 183 * get return type first 181 * get return type first 184 */ 182 */ 185 ptr = __demangle_java_sym(p + 183 ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE); 186 if (!ptr) 184 if (!ptr) 187 goto error; 185 goto error; 188 186 189 /* add space between return ty 187 /* add space between return type and function prototype */ 190 l1 = strlen(buf); 188 l1 = strlen(buf); 191 buf[l1++] = ' '; 189 buf[l1++] = ' '; 192 } 190 } 193 191 194 /* process function up to return type 192 /* process function up to return type */ 195 ptr = __demangle_java_sym(str, p + 1, 193 ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX); 196 if (!ptr) 194 if (!ptr) 197 goto error; 195 goto error; 198 196 199 return buf; 197 return buf; 200 error: 198 error: 201 free(buf); 199 free(buf); 202 return NULL; 200 return NULL; 203 } 201 } 204 202
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.