Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204// SPDX-License-Identifier: GPL-2.0#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "symbol.h"
#include "demangle-java.h"
#include <linux/ctype.h>#include <linux/kernel.h>
enum { MODE_PREFIX = 0, MODE_CLASS = 1, MODE_FUNC = 2, MODE_TYPE = 3, MODE_CTYPE = 4, /* class arg */};
#define BASE_ENT(c, n) [c - 'A']=nstatic const char *base_types['Z' - 'A' + 1] = { BASE_ENT('B', "byte" ), BASE_ENT('C', "char" ), BASE_ENT('D', "double" ), BASE_ENT('F', "float" ), BASE_ENT('I', "int" ), BASE_ENT('J', "long" ), BASE_ENT('S', "short" ), BASE_ENT('Z', "boolean" ),};
/* * demangle Java symbol between str and end positions and stores * up to maxlen characters into buf. The parser starts in mode. * * Use MODE_PREFIX to process entire prototype till end position * Use MODE_TYPE to process return type if str starts on return type char * * Return: * success: buf * error : NULL */static char *__demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode){ int rlen = 0; int array = 0; int narg = 0; const char *q;
if (!end) end = str + strlen(str);
for (q = str; q != end; q++) {
if (rlen == (maxlen - 1)) break;
switch (*q) { case 'L': if (mode == MODE_PREFIX || mode == MODE_TYPE) { if (mode == MODE_TYPE) { if (narg) rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); narg++; } if (mode == MODE_PREFIX) mode = MODE_CLASS; else mode = MODE_CTYPE; } else buf[rlen++] = *q; break; case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z': if (mode == MODE_TYPE) { if (narg) rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']); while (array--) rlen += scnprintf(buf + rlen, maxlen - rlen, "[]"); array = 0; narg++; } else buf[rlen++] = *q; break; case 'V': if (mode == MODE_TYPE) { rlen += scnprintf(buf + rlen, maxlen - rlen, "void"); while (array--) rlen += scnprintf(buf + rlen, maxlen - rlen, "[]"); array = 0; } else buf[rlen++] = *q; break; case '[': if (mode != MODE_TYPE) goto error; array++; break; case '(': if (mode != MODE_FUNC) goto error; buf[rlen++] = *q; mode = MODE_TYPE; break; case ')': if (mode != MODE_TYPE) goto error; buf[rlen++] = *q; narg = 0; break; case ';': if (mode != MODE_CLASS && mode != MODE_CTYPE) goto error; /* safe because at least one other char to process */ if (isalpha(*(q + 1)) && mode == MODE_CLASS) rlen += scnprintf(buf + rlen, maxlen - rlen, "."); if (mode == MODE_CLASS) mode = MODE_FUNC; else if (mode == MODE_CTYPE) mode = MODE_TYPE; break; case '/': if (mode != MODE_CLASS && mode != MODE_CTYPE) goto error; rlen += scnprintf(buf + rlen, maxlen - rlen, "."); break; default : buf[rlen++] = *q; } } buf[rlen] = '\0'; return buf;error: return NULL;}
/* * Demangle Java function signature (openJDK, not GCJ) * input: * str: string to parse. String is not modified * flags: combination of JAVA_DEMANGLE_* flags to modify demangling * return: * if input can be demangled, then a newly allocated string is returned. * if input cannot be demangled, then NULL is returned * * Note: caller is responsible for freeing demangled string */char *java_demangle_sym(const char *str, int flags){ char *buf, *ptr; const char *p; size_t len, l1 = 0;
if (!str) return NULL;
/* find start of return type */ p = strrchr(str, ')'); if (!p) return NULL;
/* * expansion factor estimated to 3x */ len = strlen(str) * 3 + 1; buf = malloc(len); if (!buf) return NULL;
buf[0] = '\0'; if (!(flags & JAVA_DEMANGLE_NORET)) { /* * get return type first */ ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE); if (!ptr) goto error;
/* add space between return type and function prototype */ l1 = strlen(buf); buf[l1++] = ' '; }
/* process function up to return type */ ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX); if (!ptr) goto error;
return buf;error: free(buf); return NULL;}