brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · ddf33d5 Raw
204 lines · c
1// SPDX-License-Identifier: GPL-2.02#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']=n22static 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 stores35 * up to maxlen characters into buf. The parser starts in mode.36 *37 * Use MODE_PREFIX to process entire prototype till end position38 * Use MODE_TYPE to process return type if str starts on return type char39 *40 *  Return:41 *	success: buf42 *	error  : NULL43 */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				else71					mode = MODE_CTYPE;72			} else73				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			} else92				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			} else101				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 modified150 *    flags: combination of JAVA_DEMANGLE_* flags to modify demangling151 * return:152 *	if input can be demangled, then a newly allocated string is returned.153 *	if input cannot be demangled, then NULL is returned154 *155 * Note: caller is responsible for freeing demangled string156 */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 3x174	 */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 first184		 */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}204