demangle-java.c 4.1 KB

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