Linux Audio

Check our new training course

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