* Initial commit of new UI c# component * Initial commit of new UI frontend component * target WinExe to hide console window in release mode, move ui exe into resources * force single file publishing and add initial gh workflow for publishing ui * fix workflow errors * update dependencies and remove cxxdemangler, as it was outdated * fix c# single file output due to invalid output path * smaller tweaks, hack around loops in cpp type layouting * process other queued exports even if one fails and show error message * add basic support for processing LC_DYLD_CHAINED_FIXUPS * ELF loading should not use the file offset for loading the dynamic section * fix symbol table loading in some modified elfs * add "start export" button on format selection screen, clear all toasts after selecting an export format * embed ui executable directly into c# assembly * only build tauri component in c# release builds * add il2cpp file (binary, metadata) export to advanced tab * fix and enable binary ninja fake string segment support * add support for metadata * unify logic for getting element type index * fix new ui not allowing script exports other than ida * new ui: clear out loaded binary if no IL2CPP images could be loaded * fix toAddr calls in ghidra script target * remove dependency on a section being named .text in loaded pe files * tweak symbol reading a bit and remove sht relocation reading * add initial support for required forward references in il2cpp types, also fix issues with type names clashing with il2cpp api types * reduce clang errors for header file, fix better array size struct, emit required forward definitions in header * expose forward definitions in AppModel, fix issue with method-only used types not being emitted * remove debug log line * fix spelling mistakes in gui outputs * fix il2cpp_array_size_t not being an actual type for later method definitions * change the default port for new ui dev to 5000 * show current version and hash in new ui footer * seperate redux ui impl into FrontendCore project * make inspector version a server api, split up output subtypes and tweak some option names * add redux CLI based on redux GUI output formats * replace all Console.WriteLine calls in core inspector with AnsiConsole calls * add workflow for new cli and add back old gui workflow * disable aot publish and enable single file for redux cli
90 lines
3.9 KiB
C#
90 lines
3.9 KiB
C#
/*
|
|
Copyright 2017-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
|
|
Copyright 2020 Robert Xiao - https://robertxiao.ca
|
|
|
|
All rights reserved.
|
|
*/
|
|
|
|
namespace Il2CppInspector.Cpp
|
|
{
|
|
/// <summary>
|
|
/// A utility class for managing names in a common namespace.
|
|
/// </summary>
|
|
public class CppNamespace
|
|
{
|
|
// The central data structure that keeps track of which names have been generated
|
|
// The value for any given key K is the number of unique objects originally named K, minus 1.
|
|
// Each time we see a particular name assigned to a new, different object, we bump its rename count
|
|
// and give it a suffix. For example, if we have three different objects all named X,
|
|
// we'd name them X, X_1, and X_2, and renameCount["X"] would be 2.
|
|
private readonly Dictionary<string, int> renameCount = new Dictionary<string, int>();
|
|
|
|
// Mark a name as reserved without assigning an object to it (e.g. for keywords and built-in names)
|
|
public void ReserveName(string name) {
|
|
if (!renameCount.TryAdd(name, 0)) {
|
|
throw new Exception($"Can't reserve {name}: already taken!");
|
|
}
|
|
}
|
|
|
|
// Try to mark a name as reserved without assigning an object to it (e.g. for keywords and built-in names)
|
|
public bool TryReserveName(string name)
|
|
{
|
|
return renameCount.TryAdd(name, 0);
|
|
}
|
|
|
|
// Create a Namer object which will give names to objects of type T which are unique within this namespace
|
|
public Namer<T> MakeNamer<T>(Namer<T>.KeyFunc keyFunc) {
|
|
return new Namer<T>(this, keyFunc);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A class for managing objects of a common type within a namespace.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
public class Namer<T>
|
|
{
|
|
// Parent namespace
|
|
private CppNamespace ns;
|
|
|
|
// Names given out by this Namer.
|
|
private readonly Dictionary<T, string> names = new Dictionary<T, string>();
|
|
|
|
// The function which maps a T object to a suitably mangled name
|
|
// That name might be further mangled by the Namer to make the name unique within the namespace
|
|
public delegate string KeyFunc(T t);
|
|
private readonly KeyFunc keyFunc;
|
|
|
|
public Namer(CppNamespace ns, KeyFunc keyFunc) {
|
|
this.ns = ns;
|
|
this.keyFunc = keyFunc;
|
|
}
|
|
|
|
// Uniquely name an object within the parent namespace
|
|
public string GetName(T t) {
|
|
// If we've named this particular object before, just return that name
|
|
if (names.TryGetValue(t, out var name))
|
|
return name;
|
|
|
|
// Obtain the mangled name for the object
|
|
name = keyFunc(t);
|
|
// Check if the mangled name has been given to another object - if it has,
|
|
// we need to give the object a new suffixed name (e.g. X_1).
|
|
// We might need to repeat this process if the new suffixed name also exists.
|
|
// Each iteration tacks on another suffix - so we normally expect this to only take
|
|
// a single iteration. (It might take multiple iterations in rare cases, e.g.
|
|
// another object had the mangled name X_1).
|
|
if (ns.renameCount.ContainsKey(name)) {
|
|
int v = ns.renameCount[name] + 1;
|
|
while (ns.renameCount.ContainsKey(name + "_" + v))
|
|
v++;
|
|
ns.renameCount[name] = v;
|
|
name = name + "_" + v;
|
|
}
|
|
ns.renameCount[name] = 0;
|
|
names[t] = name;
|
|
return name;
|
|
}
|
|
}
|
|
}
|
|
}
|