root/tools/perf/util/demangle-java.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __demangle_java_sym
  2. java_demangle_sym

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

/* [<][>][^][v][top][bottom][index][help] */