Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  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}