Starting a real parsing for demangler (still simple and no compression support yet)
This commit is contained in:
parent
9356c1bac9
commit
289f536c9b
2 changed files with 262 additions and 33 deletions
|
@ -1,60 +1,288 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Diagnostics
|
||||
{
|
||||
static class Demangle
|
||||
public static class Demangle
|
||||
{
|
||||
public static string ReadName(string mangled)
|
||||
/*
|
||||
<builtin-type> ::= v # void
|
||||
::= w # wchar_t
|
||||
::= b # bool
|
||||
::= c # char
|
||||
::= a # signed char
|
||||
::= h # unsigned char
|
||||
::= s # short
|
||||
::= t # unsigned short
|
||||
::= i # int
|
||||
::= j # unsigned int
|
||||
::= l # long
|
||||
::= m # unsigned long
|
||||
::= x # long long, __int64
|
||||
::= y # unsigned long long, __int64
|
||||
::= n # __int128
|
||||
::= o # unsigned __int128
|
||||
::= f # float
|
||||
::= d # double
|
||||
::= e # long double, __float80
|
||||
::= g # __float128
|
||||
::= z # ellipsis
|
||||
::= Dd # IEEE 754r decimal floating point (64 bits)
|
||||
::= De # IEEE 754r decimal floating point (128 bits)
|
||||
::= Df # IEEE 754r decimal floating point (32 bits)
|
||||
::= Dh # IEEE 754r half-precision floating point (16 bits)
|
||||
::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits)
|
||||
::= Di # char32_t
|
||||
::= Ds # char16_t
|
||||
::= Da # auto
|
||||
::= Dc # decltype(auto)
|
||||
::= Dn # std::nullptr_t (i.e., decltype(nullptr))
|
||||
*/
|
||||
private static readonly Dictionary<string, string> BuiltinTypes = new Dictionary<string, string>
|
||||
{
|
||||
string result = null;
|
||||
{ "v", "void" },
|
||||
{ "w", "wchar_t" },
|
||||
{ "b", "bool" },
|
||||
{ "c", "char" },
|
||||
{ "a", "signed char" },
|
||||
{ "h", "unsigned char" },
|
||||
{ "s", "short" },
|
||||
{ "t", "unsigned short" },
|
||||
{ "i", "int" },
|
||||
{ "j", "unsigned int" },
|
||||
{ "l", "long" },
|
||||
{ "m", "unsigned long" },
|
||||
{ "x", "long long, __int64" },
|
||||
{ "y", "unsigned long long, __int64" },
|
||||
{ "n", "__int128" },
|
||||
{ "o", "unsigned __int128" },
|
||||
{ "f", "float" },
|
||||
{ "d", "double" },
|
||||
{ "e", "long double, __float80" },
|
||||
{ "g", "__float128" },
|
||||
{ "z", "ellipsis" },
|
||||
{ "Dd", "__iec559_double" },
|
||||
{ "De", "__iec559_float128" },
|
||||
{ "Df", "__iec559_float" },
|
||||
{ "Dh", "__iec559_float16" },
|
||||
{ "Di", "char32_t" },
|
||||
{ "Ds", "char16_t" },
|
||||
{ "Da", "decltype(auto)" },
|
||||
{ "Dn", "std::nullptr_t" },
|
||||
};
|
||||
public static List<string> ReadName(string mangled, out int pos, List<string> compressionData)
|
||||
{
|
||||
List<string> res = new List<string>();
|
||||
string charCountTemp = null;
|
||||
int charCount = 0;
|
||||
int i;
|
||||
|
||||
foreach (var chr in mangled)
|
||||
pos = -1;
|
||||
for (i = 0; i < mangled.Length; i++)
|
||||
{
|
||||
if (charCount == 0)
|
||||
char chr = mangled[i];
|
||||
if (charCountTemp == null)
|
||||
{
|
||||
if (charCountTemp == null)
|
||||
if (ReadCVQualifiers(chr) != null)
|
||||
{
|
||||
if (chr == 'r' || chr == 'V' || chr == 'K')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (chr == 'E')
|
||||
{
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (Char.IsDigit(chr))
|
||||
if (chr == 'E')
|
||||
{
|
||||
charCountTemp += chr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!int.TryParse(charCountTemp, out charCount))
|
||||
{
|
||||
return mangled;
|
||||
}
|
||||
result += chr;
|
||||
charCount--;
|
||||
charCountTemp = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Char.IsDigit(chr))
|
||||
{
|
||||
charCountTemp += chr;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += chr;
|
||||
charCount--;
|
||||
if (charCount == 0)
|
||||
if (!int.TryParse(charCountTemp, out charCount))
|
||||
{
|
||||
result += "::";
|
||||
return null;
|
||||
}
|
||||
string demangledPart = mangled.Substring(i, charCount);
|
||||
if (res.Count == 0)
|
||||
res.Add(demangledPart);
|
||||
else
|
||||
res.Add(res[res.Count - 1] + "::" + demangledPart);
|
||||
i = i + charCount - 1;
|
||||
charCount = 0;
|
||||
charCountTemp = null;
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
if (res.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
pos = i;
|
||||
return res;
|
||||
}
|
||||
|
||||
public static string ReadBuiltinType(string mangledType, out int pos)
|
||||
{
|
||||
string res = null;
|
||||
string temp;
|
||||
pos = -1;
|
||||
temp = mangledType[0].ToString();
|
||||
if (!BuiltinTypes.TryGetValue(temp, out res))
|
||||
{
|
||||
temp = mangledType.Substring(0, 2);
|
||||
BuiltinTypes.TryGetValue(temp, out res);
|
||||
}
|
||||
if (res != null)
|
||||
pos = temp.Length;
|
||||
return res;
|
||||
}
|
||||
|
||||
private static string ReadCVQualifiers(char qualifier)
|
||||
{
|
||||
if (qualifier == 'r')
|
||||
return "restricted";
|
||||
else if (qualifier == 'V')
|
||||
return "volatile";
|
||||
else if (qualifier == 'K')
|
||||
return "const";
|
||||
else if (qualifier == 'R')
|
||||
return "&";
|
||||
else if (qualifier == 'O')
|
||||
return "&&";
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string ReadRefQualifiers(char qualifier)
|
||||
{
|
||||
if (qualifier == 'R')
|
||||
return "&";
|
||||
else if (qualifier == 'O')
|
||||
return "&&";
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string ReadSpecialQualifiers(char qualifier)
|
||||
{
|
||||
if (qualifier == 'P')
|
||||
return "*";
|
||||
else if (qualifier == 'C')
|
||||
return "complex";
|
||||
else if (qualifier == 'G')
|
||||
return "imaginary";
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<string> ReadParameters(string mangledParams, out int pos)
|
||||
{
|
||||
List<string> res = new List<string>();
|
||||
int i = 0;
|
||||
pos = -1;
|
||||
|
||||
string temp = null;
|
||||
string temp2 = null;
|
||||
for (i = 0; i < mangledParams.Length; i++)
|
||||
{
|
||||
char chr = mangledParams[i];
|
||||
string part = mangledParams.Substring(i);
|
||||
|
||||
// Try to read qualifiers
|
||||
temp2 = ReadCVQualifiers(chr);
|
||||
if (temp2 != null)
|
||||
{
|
||||
temp = temp2 + " " + temp;
|
||||
continue;
|
||||
}
|
||||
|
||||
temp2 = ReadRefQualifiers(chr);
|
||||
if (temp2 != null)
|
||||
{
|
||||
temp = temp + temp2;
|
||||
continue;
|
||||
}
|
||||
|
||||
temp2 = ReadSpecialQualifiers(chr);
|
||||
if (temp2 != null)
|
||||
{
|
||||
Console.WriteLine(temp);
|
||||
temp = temp + temp2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: extended-qualifier?
|
||||
|
||||
// Try builting
|
||||
temp2 = ReadBuiltinType(part, out pos);
|
||||
if (pos == -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (temp != null)
|
||||
temp = temp2 + " " + temp;
|
||||
else
|
||||
temp = temp2;
|
||||
res.Add(temp);
|
||||
temp = null;
|
||||
i = i + pos -1;
|
||||
}
|
||||
pos = i;
|
||||
return res;
|
||||
}
|
||||
|
||||
public static string ReadNameString(string mangled, out int pos)
|
||||
{
|
||||
List<string> name = ReadName(mangled, out pos, new List<string>());
|
||||
if (pos == -1 || name == null || name.Count == 0)
|
||||
{
|
||||
return mangled;
|
||||
}
|
||||
return result.Substring(0, result.Length - 2);
|
||||
foreach (var entry in name)
|
||||
{
|
||||
Console.WriteLine(entry);
|
||||
}
|
||||
|
||||
return name[name.Count - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
<mangled-name> ::= _Z <encoding>
|
||||
<encoding> ::= <function name> <bare-function-type>
|
||||
::= <data name>
|
||||
::= <special-name>
|
||||
*/
|
||||
public static string Parse(string mangled)
|
||||
{
|
||||
Console.WriteLine("Mangled: " + mangled);
|
||||
List<string> compressionData = new List<string>();
|
||||
string res = null;
|
||||
int pos = 0;
|
||||
|
||||
// We asume that we start with a function name
|
||||
// TODO: support special names
|
||||
if (mangled.StartsWith("_ZN"))
|
||||
{
|
||||
mangled = mangled.Substring(3);
|
||||
compressionData = ReadName(mangled, out pos, compressionData);
|
||||
if (pos == -1)
|
||||
return mangled;
|
||||
res = compressionData[compressionData.Count - 1];
|
||||
|
||||
compressionData.Remove(res);
|
||||
mangled = mangled.Substring(pos + 1);
|
||||
|
||||
// more data? maybe not a data name so...
|
||||
if (mangled != String.Empty)
|
||||
{
|
||||
List<string> parameters = ReadParameters(mangled, out pos);
|
||||
// parameters parsing error, we return the original data to avoid information loss.
|
||||
if (pos == -1)
|
||||
return mangled;
|
||||
res += "(";
|
||||
res += String.Join(", ", parameters);
|
||||
res += ")";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return mangled;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -307,7 +307,8 @@ namespace Ryujinx.Core.OsHle
|
|||
}
|
||||
else if (SubName.StartsWith("_ZN"))
|
||||
{
|
||||
SubName = Demangle.ReadName(SubName.Substring(3));
|
||||
int i = 0;
|
||||
SubName = Demangle.ReadNameString(SubName.Substring(3), out i);
|
||||
}
|
||||
|
||||
Trace.AppendLine(" " + SubName + " (" + GetNsoNameAndAddress(Position) + ")");
|
||||
|
|
Loading…
Add table
Reference in a new issue