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