Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include "demangle-rust.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Mangled Rust symbols look like this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *     _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * The original symbol is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *     <std::sys::fd::FileDesc as core::ops::Drop>::drop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * The last component of the path is a 64-bit hash in lowercase hex, prefixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * with "h". Rust does not have a global namespace between crates, an illusion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * which Rust maintains by using the hash to distinguish things that would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * otherwise have the same symbol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * Any path component not starting with a XID_Start character is prefixed with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * "_".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * The following escape sequences are used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *     ","  =>  $C$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *     "@"  =>  $SP$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *     "*"  =>  $BP$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *     "&"  =>  $RF$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *     "<"  =>  $LT$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  *     ">"  =>  $GT$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *     "("  =>  $LP$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  *     ")"  =>  $RP$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *     " "  =>  $u20$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *     "'"  =>  $u27$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  *     "["  =>  $u5b$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  *     "]"  =>  $u5d$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  *     "~"  =>  $u7e$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * A double ".." means "::" and a single "." means "-".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static const char *hash_prefix = "::h";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static const size_t hash_prefix_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static const size_t hash_len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) static bool is_prefixed_hash(const char *start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static bool looks_like_rust(const char *sym, size_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static bool unescape(const char **in, char **out, const char *seq, char value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  *     sym: symbol that has been through BFD-demangling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * This function looks for the following indicators:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  *  1. The hash must consist of "h" followed by 16 lowercase hex digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  *  2. As a sanity check, the hash must use between 5 and 15 of the 16 possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  *     hex digits. This is true of 99.9998% of hashes so once in your life you
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *     may see a false negative. The point is to notice path components that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  *     could be Rust hashes but are probably not, like "haaaaaaaaaaaaaaaa". In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  *     this case a false positive (non-Rust symbol has an important path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  *     component removed because it looks like a Rust hash) is worse than a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  *     false negative (the rare Rust symbol is not demangled) so this sets the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  *     balance in favor of false negatives.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  *  3. There must be no characters other than a-zA-Z0-9 and _.:$
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  *  4. There must be no unrecognized $-sign sequences.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  *  5. There must be no sequence of three or more dots in a row ("...").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) rust_is_mangled(const char *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	size_t len, len_without_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (!sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	len = strlen(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	if (len <= hash_prefix_len + hash_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		/* Not long enough to contain "::h" + hash + something else */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	len_without_hash = len - (hash_prefix_len + hash_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (!is_prefixed_hash(sym + len_without_hash))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	return looks_like_rust(sym, len_without_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  * A hash is the prefix "::h" followed by 16 lowercase hex digits. The hex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  * digits must comprise between 5 and 15 (inclusive) distinct digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static bool is_prefixed_hash(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	const char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	bool seen[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (strncmp(str, hash_prefix, hash_prefix_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	str += hash_prefix_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	memset(seen, false, sizeof(seen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	for (end = str + hash_len; str < end; str++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		if (*str >= '0' && *str <= '9')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			seen[*str - '0'] = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		else if (*str >= 'a' && *str <= 'f')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			seen[*str - 'a' + 10] = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	/* Count how many distinct digits seen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		if (seen[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return count >= 5 && count <= 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static bool looks_like_rust(const char *str, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	const char *end = str + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	while (str < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		switch (*str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		case '$':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			if (!strncmp(str, "$C$", 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 				str += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			else if (!strncmp(str, "$SP$", 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 					|| !strncmp(str, "$BP$", 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 					|| !strncmp(str, "$RF$", 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 					|| !strncmp(str, "$LT$", 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 					|| !strncmp(str, "$GT$", 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 					|| !strncmp(str, "$LP$", 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 					|| !strncmp(str, "$RP$", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 				str += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			else if (!strncmp(str, "$u20$", 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 					|| !strncmp(str, "$u27$", 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 					|| !strncmp(str, "$u5b$", 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 					|| !strncmp(str, "$u5d$", 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 					|| !strncmp(str, "$u7e$", 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 				str += 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		case '.':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			/* Do not allow three or more consecutive dots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			if (!strncmp(str, "...", 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			/* Fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		case 'a' ... 'z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		case 'A' ... 'Z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		case '0' ... '9':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		case '_':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		case ':':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * INPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  *     sym: symbol for which rust_is_mangled(sym) returns true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * The input is demangled in-place because the mangled name is always longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  * than the demangled one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) rust_demangle_sym(char *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	const char *in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	char *out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	const char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (!sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	in = sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	out = sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	end = sym + strlen(sym) - (hash_prefix_len + hash_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	while (in < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		switch (*in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		case '$':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			if (!(unescape(&in, &out, "$C$", ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 					|| unescape(&in, &out, "$SP$", '@')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 					|| unescape(&in, &out, "$BP$", '*')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 					|| unescape(&in, &out, "$RF$", '&')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 					|| unescape(&in, &out, "$LT$", '<')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 					|| unescape(&in, &out, "$GT$", '>')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 					|| unescape(&in, &out, "$LP$", '(')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 					|| unescape(&in, &out, "$RP$", ')')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 					|| unescape(&in, &out, "$u20$", ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 					|| unescape(&in, &out, "$u27$", '\'')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 					|| unescape(&in, &out, "$u5b$", '[')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 					|| unescape(&in, &out, "$u5d$", ']')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 					|| unescape(&in, &out, "$u7e$", '~'))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 				pr_err("demangle-rust: unexpected escape sequence");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 				goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		case '_':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			 * If this is the start of a path component and the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			 * character is an escape sequence, ignore the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 			 * underscore. The mangler inserts an underscore to make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			 * sure the path component begins with a XID_Start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			 * character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 			if ((in == sym || in[-1] == ':') && in[1] == '$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 				in++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 				*out++ = *in++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		case '.':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			if (in[1] == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 				/* ".." becomes "::" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 				*out++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 				*out++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 				in += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				/* "." becomes "-" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 				*out++ = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 				in++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		case 'a' ... 'z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		case 'A' ... 'Z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		case '0' ... '9':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		case ':':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			*out++ = *in++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			pr_err("demangle-rust: unexpected character '%c' in symbol\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 				*in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	*out = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static bool unescape(const char **in, char **out, const char *seq, char value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	size_t len = strlen(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	if (strncmp(*in, seq, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	**out = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	*in += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	*out += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }