C++: Improve handling of pointers
This commit is contained in:
@@ -30,7 +30,12 @@ namespace Il2CppInspector.Cpp
|
|||||||
public class CppType
|
public class CppType
|
||||||
{
|
{
|
||||||
// The name of the type
|
// The name of the type
|
||||||
public string Name { get; internal set; }
|
protected string name;
|
||||||
|
|
||||||
|
public virtual string Name {
|
||||||
|
get => name;
|
||||||
|
set => name = value;
|
||||||
|
}
|
||||||
|
|
||||||
// The size of the C++ type in bytes
|
// The size of the C++ type in bytes
|
||||||
public virtual int Size { get; protected set; }
|
public virtual int Size { get; protected set; }
|
||||||
@@ -40,7 +45,20 @@ namespace Il2CppInspector.Cpp
|
|||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => Name + " // Size: " + Size;
|
// Generate pointer to this type
|
||||||
|
public CppPointerType AsPointer(int WordSize, string Name = null) => new CppPointerType(WordSize) {Name = Name, ElementType = this};
|
||||||
|
|
||||||
|
public override string ToString() => $"/* {Size:x2} */ {Name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// A pointer type
|
||||||
|
public class CppPointerType : CppType
|
||||||
|
{
|
||||||
|
public override string Name => name ?? ElementType.Name + "*";
|
||||||
|
|
||||||
|
public CppType ElementType { get; set; }
|
||||||
|
|
||||||
|
public CppPointerType(int WordSize) : base(null, WordSize) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A struct, union or class type (type with fields)
|
// A struct, union or class type (type with fields)
|
||||||
@@ -85,7 +103,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
foreach (var field in Fields.Values.SelectMany(f => f))
|
foreach (var field in Fields.Values.SelectMany(f => f))
|
||||||
sb.AppendLine(" " + field);
|
sb.AppendLine(" " + field);
|
||||||
|
|
||||||
sb.Append($"}}; // Size: 0x{Size:x2}");
|
sb.Append($"}} /* Size: 0x{Size:x2} */");
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
@@ -94,30 +112,27 @@ namespace Il2CppInspector.Cpp
|
|||||||
// A field in a C++ type
|
// A field in a C++ type
|
||||||
public struct CppField
|
public struct CppField
|
||||||
{
|
{
|
||||||
// The type collection this belongs to
|
|
||||||
public CppTypes CppTypes { get; set; }
|
|
||||||
|
|
||||||
// The name of the field
|
// The name of the field
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
// The offset of the field into the type
|
// The offset of the field into the type
|
||||||
public int Offset { get; set; }
|
public int Offset { get; set; }
|
||||||
|
|
||||||
// The size of the field (this will differ from the type size if the field is a pointer)
|
// The size of the field
|
||||||
public int Size => IsPointer? CppTypes.WordSize : Type.Size;
|
public int Size => Type.Size;
|
||||||
|
|
||||||
// The type of the field
|
// The type of the field
|
||||||
// This type will be wrong (by design) for function pointers, pointers to pointers etc.
|
// This type will be wrong (by design) for function pointers, pointers to pointers etc.
|
||||||
// and we only want it to calculate offsets so we hide this
|
// and we only want it to calculate offsets so we hide this
|
||||||
internal CppType Type { get; set; }
|
internal CppType Type { get; set; }
|
||||||
|
|
||||||
// True if the field is a pointer
|
|
||||||
internal bool IsPointer { get; set; }
|
|
||||||
|
|
||||||
// C++ representation of field (might be incorrect due to the above)
|
// C++ representation of field (might be incorrect due to the above)
|
||||||
public override string ToString() => $"/* 0x{Offset:x2} - 0x{Offset + Size - 1:x2} (0x{Size:x2}) */ " + Name +
|
public override string ToString() => $"/* 0x{Offset:x2} - 0x{Offset + Size - 1:x2} (0x{Size:x2}) */"
|
||||||
// nested anonymous types
|
// nested anonymous types
|
||||||
(Type.Name == "" ? "\n" + Type : "");
|
+ (Type is CppComplexType && Type.Name == "" ? "\n" + Type + " " + Name :
|
||||||
|
// regular fields
|
||||||
|
$" {Type.Name} {Name}")
|
||||||
|
+ ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
// A collection of C++ types
|
// A collection of C++ types
|
||||||
@@ -146,7 +161,8 @@ namespace Il2CppInspector.Cpp
|
|||||||
new CppType("char", 1),
|
new CppType("char", 1),
|
||||||
new CppType("int", 4),
|
new CppType("int", 4),
|
||||||
new CppType("float", 4),
|
new CppType("float", 4),
|
||||||
new CppType("double", 8)
|
new CppType("double", 8),
|
||||||
|
new CppType("void", 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
public CppTypes(int wordSize) {
|
public CppTypes(int wordSize) {
|
||||||
@@ -156,7 +172,6 @@ namespace Il2CppInspector.Cpp
|
|||||||
// This is all compiler-dependent, let's hope for the best!
|
// This is all compiler-dependent, let's hope for the best!
|
||||||
Types.Add("uintptr_t", new CppType("uintptr_t", WordSize));
|
Types.Add("uintptr_t", new CppType("uintptr_t", WordSize));
|
||||||
Types.Add("size_t", new CppType("size_t", WordSize));
|
Types.Add("size_t", new CppType("size_t", WordSize));
|
||||||
Types.Add("void", new CppType("void", WordSize));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a block of C++ source code, adding any types found
|
// Parse a block of C++ source code, adding any types found
|
||||||
@@ -184,6 +199,8 @@ namespace Il2CppInspector.Cpp
|
|||||||
// TODO: comma-separated fields
|
// TODO: comma-separated fields
|
||||||
// TODO: #ifdef IS_32BIT
|
// TODO: #ifdef IS_32BIT
|
||||||
// TODO: volatile
|
// TODO: volatile
|
||||||
|
// TODO: function pointer signatures
|
||||||
|
// TODO: multiple indirection
|
||||||
|
|
||||||
while ((line = lines.ReadLine()) != null) {
|
while ((line = lines.ReadLine()) != null) {
|
||||||
|
|
||||||
@@ -243,9 +260,10 @@ namespace Il2CppInspector.Cpp
|
|||||||
typedef = rgxTypedefPtr.Match(line);
|
typedef = rgxTypedefPtr.Match(line);
|
||||||
if (typedef.Success) {
|
if (typedef.Success) {
|
||||||
var alias = typedef.Groups[2].Captures[0].ToString();
|
var alias = typedef.Groups[2].Captures[0].ToString();
|
||||||
Types.Add(alias, Types["uintptr_t"]);
|
var existingType = typedef.Groups[1].Captures[0].ToString();
|
||||||
|
Types.Add(alias, Types[existingType].AsPointer(WordSize, alias));
|
||||||
|
|
||||||
Debug.WriteLine($"[TYPEDEF PTR ] {line} -- Adding pointer typedef to {alias}");
|
Debug.WriteLine($"[TYPEDEF PTR ] {line} -- Adding pointer typedef from {existingType} to {alias}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +376,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Otherwise it's a field name in the current type
|
// Otherwise it's a field name in the current type
|
||||||
else {
|
else {
|
||||||
var parent = currentType.Peek();
|
var parent = currentType.Peek();
|
||||||
parent.AddField(new CppField { CppTypes = this, Name = name, Type = ct });
|
parent.AddField(new CppField { Name = name, Type = ct });
|
||||||
|
|
||||||
Debug.WriteLine($"[FIELD END ] {line} -- {ct.Name} {name}");
|
Debug.WriteLine($"[FIELD END ] {line} -- {ct.Name} {name}");
|
||||||
}
|
}
|
||||||
@@ -371,7 +389,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
var name = fieldFnPtr.Groups[1].Captures[0].ToString();
|
var name = fieldFnPtr.Groups[1].Captures[0].ToString();
|
||||||
|
|
||||||
var ct = currentType.Peek();
|
var ct = currentType.Peek();
|
||||||
ct.AddField(new CppField() {CppTypes = this, Name = name, Type = Types["uintptr_t"], IsPointer = false});
|
ct.AddField(new CppField {Name = name, Type = Types["uintptr_t"]});
|
||||||
|
|
||||||
Debug.WriteLine($"[FIELD FNPTR ] {line} -- {name}");
|
Debug.WriteLine($"[FIELD FNPTR ] {line} -- {name}");
|
||||||
continue;
|
continue;
|
||||||
@@ -387,7 +405,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
var type = fieldMatch.Groups[1].Captures[0].ToString();
|
var type = fieldMatch.Groups[1].Captures[0].ToString();
|
||||||
|
|
||||||
var ct = currentType.Peek();
|
var ct = currentType.Peek();
|
||||||
ct.AddField(new CppField {CppTypes = this, Name = name, Type = Types[type], IsPointer = fieldPtr.Success});
|
ct.AddField(new CppField {Name = name, Type = fieldPtr.Success? Types[type].AsPointer(WordSize) : Types[type]});
|
||||||
|
|
||||||
Debug.WriteLine($"[FIELD {(fieldPtr.Success? "PTR":"VAL")} ] {line} -- {name}");
|
Debug.WriteLine($"[FIELD {(fieldPtr.Success? "PTR":"VAL")} ] {line} -- {name}");
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user