Linux Audio

Check our new training course

Loading...
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2#include <sys/types.h>
  3#include <stdio.h>
 
  4#include <string.h>
  5#include "util.h"
  6#include "debug.h"
  7#include "symbol.h"
  8
  9#include "demangle-java.h"
 10
 11#include "sane_ctype.h"
 
 12
 13enum {
 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
 22static 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 */
 44static 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;
141error:
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 */
156char *
157java_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;
199error:
200	free(buf);
201	return NULL;
202}
v6.8
  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
 13enum {
 14	MODE_PREFIX = 0,
 15	MODE_CLASS  = 1,
 16	MODE_FUNC   = 2,
 17	MODE_TYPE   = 3,
 18	MODE_CTYPE  = 4, /* class arg */
 19};
 20
 21#define BASE_ENT(c, n)	[c - 'A']=n
 22static 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', "boolean" ),
 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 */
 44static 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_TYPE) {
 63				if (mode == MODE_TYPE) {
 64					if (narg)
 65						rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
 66					narg++;
 67				}
 
 68				if (mode == MODE_PREFIX)
 69					mode = MODE_CLASS;
 70				else
 71					mode = MODE_CTYPE;
 72			} else
 73				buf[rlen++] = *q;
 74			break;
 75		case 'B':
 76		case 'C':
 77		case 'D':
 78		case 'F':
 79		case 'I':
 80		case 'J':
 81		case 'S':
 82		case 'Z':
 83			if (mode == MODE_TYPE) {
 84				if (narg)
 85					rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
 86				rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']);
 87				while (array--)
 88					rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
 89				array = 0;
 90				narg++;
 91			} else
 92				buf[rlen++] = *q;
 93			break;
 94		case 'V':
 95			if (mode == MODE_TYPE) {
 96				rlen += scnprintf(buf + rlen, maxlen - rlen, "void");
 97				while (array--)
 98					rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
 99				array = 0;
100			} else
101				buf[rlen++] = *q;
102			break;
103		case '[':
104			if (mode != MODE_TYPE)
105				goto error;
106			array++;
107			break;
108		case '(':
109			if (mode != MODE_FUNC)
110				goto error;
111			buf[rlen++] = *q;
112			mode = MODE_TYPE;
113			break;
114		case ')':
115			if (mode != MODE_TYPE)
116				goto error;
117			buf[rlen++] = *q;
118			narg = 0;
119			break;
120		case ';':
121			if (mode != MODE_CLASS && mode != MODE_CTYPE)
122				goto error;
123			/* safe because at least one other char to process */
124			if (isalpha(*(q + 1)) && mode == MODE_CLASS)
125				rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
126			if (mode == MODE_CLASS)
127				mode = MODE_FUNC;
128			else if (mode == MODE_CTYPE)
129				mode = MODE_TYPE;
130			break;
131		case '/':
132			if (mode != MODE_CLASS && mode != MODE_CTYPE)
133				goto error;
134			rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
135			break;
136		default :
137			buf[rlen++] = *q;
138		}
139	}
140	buf[rlen] = '\0';
141	return buf;
142error:
143	return NULL;
144}
145
146/*
147 * Demangle Java function signature (openJDK, not GCJ)
148 * input:
149 * 	str: string to parse. String is not modified
150 *    flags: combination of JAVA_DEMANGLE_* flags to modify demangling
151 * return:
152 *	if input can be demangled, then a newly allocated string is returned.
153 *	if input cannot be demangled, then NULL is returned
154 *
155 * Note: caller is responsible for freeing demangled string
156 */
157char *
158java_demangle_sym(const char *str, int flags)
159{
160	char *buf, *ptr;
161	char *p;
162	size_t len, l1 = 0;
163
164	if (!str)
165		return NULL;
166
167	/* find start of return type */
168	p = strrchr(str, ')');
169	if (!p)
170		return NULL;
171
172	/*
173	 * expansion factor estimated to 3x
174	 */
175	len = strlen(str) * 3 + 1;
176	buf = malloc(len);
177	if (!buf)
178		return NULL;
179
180	buf[0] = '\0';
181	if (!(flags & JAVA_DEMANGLE_NORET)) {
182		/*
183		 * get return type first
184		 */
185		ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE);
186		if (!ptr)
187			goto error;
188
189		/* add space between return type and function prototype */
190		l1 = strlen(buf);
191		buf[l1++] = ' ';
192	}
193
194	/* process function up to return type */
195	ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX);
196	if (!ptr)
197		goto error;
198
199	return buf;
200error:
201	free(buf);
202	return NULL;
203}