mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-27 09:55:34 -05:00
add mangler for gd::string symbols
This commit is contained in:
parent
4715072c86
commit
3559064b45
4 changed files with 163 additions and 3 deletions
|
@ -1,4 +1,5 @@
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
|
#include "AndroidSymbol.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
namespace format_strings {
|
namespace format_strings {
|
||||||
|
@ -120,9 +121,16 @@ std::string generateAddressHeader(Root const& root) {
|
||||||
address_str = fmt::format("base::get() + 0x{:x}", codegen::platformNumber(fn->binds));
|
address_str = fmt::format("base::get() + 0x{:x}", codegen::platformNumber(fn->binds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (codegen::shouldAndroidBind(fn)) {
|
||||||
|
auto const mangled = generateAndroidSymbol(c, fn);
|
||||||
|
address_str = fmt::format(
|
||||||
|
"reinterpret_cast<uintptr_t>(dlsym(reinterpret_cast<void*>(geode::base::get()), \"{}\"))",
|
||||||
|
mangled
|
||||||
|
);
|
||||||
|
}
|
||||||
else if (codegen::getStatus(field) == BindStatus::Binded && fn->prototype.type == FunctionType::Normal) {
|
else if (codegen::getStatus(field) == BindStatus::Binded && fn->prototype.type == FunctionType::Normal) {
|
||||||
address_str = fmt::format(
|
address_str = fmt::format(
|
||||||
"0/*addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))*/",
|
"addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))",
|
||||||
str_if("Non", !fn->prototype.is_virtual),
|
str_if("Non", !fn->prototype.is_virtual),
|
||||||
codegen::getParameterTypes(fn->prototype),
|
codegen::getParameterTypes(fn->prototype),
|
||||||
field.parent,
|
field.parent,
|
||||||
|
|
143
codegen/src/AndroidSymbol.hpp
Normal file
143
codegen/src/AndroidSymbol.hpp
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Shared.hpp"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
std::string mangleIdent(std::string_view str) {
|
||||||
|
if (str.find("::") != -1) {
|
||||||
|
std::string result = "N";
|
||||||
|
auto s = str;
|
||||||
|
do {
|
||||||
|
const auto i = s.find("::");
|
||||||
|
const auto t = s.substr(0, i);
|
||||||
|
result += std::to_string(t.size()) + std::string(t);
|
||||||
|
if (i == -1) s = "";
|
||||||
|
else
|
||||||
|
s = s.substr(i + 2);
|
||||||
|
} while(s.size());
|
||||||
|
return result + "E";
|
||||||
|
} else {
|
||||||
|
return std::to_string(str.size()) + std::string(str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string intToString(unsigned int value, unsigned int radix) {
|
||||||
|
static constexpr char base36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
std::string result;
|
||||||
|
do {
|
||||||
|
unsigned int remainder = value % radix;
|
||||||
|
value /= radix;
|
||||||
|
result.insert(result.begin(), base36[remainder]);
|
||||||
|
} while (value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string lookForSeen(std::vector<std::string>& seen, std::string mangled) {
|
||||||
|
for (int i = 0; i < seen.size(); ++i) {
|
||||||
|
if (seen[i] == mangled) {
|
||||||
|
if (i == 0) return "S_";
|
||||||
|
// yes, its base 36
|
||||||
|
return "S" + intToString(i - 1, 36) + "_";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string subsSeen(std::vector<std::string>& seen, std::string mangled, bool subs) {
|
||||||
|
if (!subs) return mangled;
|
||||||
|
if (mangled.empty()) return mangled;
|
||||||
|
if (auto x = lookForSeen(seen, mangled); !x.empty()) return x;
|
||||||
|
seen.push_back(mangled);
|
||||||
|
return mangled;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string mangleType(std::vector<std::string>& seen, std::string name, bool subs = true) {
|
||||||
|
if (name == "int") return "i";
|
||||||
|
if (name == "float") return "f";
|
||||||
|
if (name == "bool") return "b";
|
||||||
|
if (name == "char") return "c";
|
||||||
|
if (name == "gd::string") return "Ss";
|
||||||
|
if (name == "cocos2d::ccColor3B") return mangleType(seen, "cocos2d::_ccColor3B", subs);
|
||||||
|
// too lazy
|
||||||
|
if (name == "gd::map<gd::string, gd::string>") return "St3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE";
|
||||||
|
if (name == "cocos2d::SEL_MenuHandler") {
|
||||||
|
const auto a = mangleType(seen, "cocos2d::CCObject", subs);
|
||||||
|
const auto b = mangleType(seen, "cocos2d::CCObject*", subs);
|
||||||
|
const auto fnptr = subsSeen(seen, "Fv" + b + "E", subs);
|
||||||
|
return subsSeen(seen, "M" + a + fnptr, subs);
|
||||||
|
}
|
||||||
|
if (name.find('*') == name.size() - 1) {
|
||||||
|
auto inner = mangleType(seen, name.substr(0, name.size() - 1), false);
|
||||||
|
if (auto x = lookForSeen(seen, "P" + inner); !x.empty()) return x;
|
||||||
|
inner = mangleType(seen, name.substr(0, name.size() - 1), subs);
|
||||||
|
return subsSeen(seen, "P" + inner, subs);
|
||||||
|
}
|
||||||
|
if (name.find('&') == name.size() - 1) {
|
||||||
|
auto inner = mangleType(seen, name.substr(0, name.size() - 1), false);
|
||||||
|
if (auto x = lookForSeen(seen, "R" + inner); !x.empty()) return x;
|
||||||
|
inner = mangleType(seen, name.substr(0, name.size() - 1), subs);
|
||||||
|
return subsSeen(seen, "R" + inner, subs);
|
||||||
|
}
|
||||||
|
if (auto i = name.find("const"); i != -1) {
|
||||||
|
std::string inner;
|
||||||
|
// at the end of the name
|
||||||
|
if (i == name.size() - 5) {
|
||||||
|
inner = mangleType(seen, name.substr(0, i - 1));
|
||||||
|
} else if (i == 0) {
|
||||||
|
inner = mangleType(seen, name.substr(6));
|
||||||
|
} else {
|
||||||
|
inner = "v";
|
||||||
|
std::cout << "um " << name << std::endl;
|
||||||
|
}
|
||||||
|
return subsSeen(seen, "K" + inner, subs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.find("::") != -1) {
|
||||||
|
std::string result = "";
|
||||||
|
std::string substituted = "";
|
||||||
|
auto s = name;
|
||||||
|
do {
|
||||||
|
const auto i = s.find("::");
|
||||||
|
const auto t = s.substr(0, i);
|
||||||
|
auto part = std::to_string(t.size()) + std::string(t);
|
||||||
|
if (auto x = lookForSeen(seen, result + part); !x.empty()) {
|
||||||
|
substituted = x;
|
||||||
|
} else {
|
||||||
|
substituted = subsSeen(seen, substituted + part, subs);
|
||||||
|
}
|
||||||
|
result += part;
|
||||||
|
|
||||||
|
if (i == -1) s = "";
|
||||||
|
else s = s.substr(i + 2);
|
||||||
|
} while(s.size());
|
||||||
|
if (substituted.size() == 3 && substituted[0] == 'S')
|
||||||
|
return substituted;
|
||||||
|
return "N" + substituted + "E";
|
||||||
|
} else {
|
||||||
|
return subsSeen(seen, mangleIdent(name), subs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string generateAndroidSymbol(const Class& clazz, const FunctionBindField* fn) {
|
||||||
|
auto& decl = fn->prototype;
|
||||||
|
|
||||||
|
std::string mangledSymbol = "_Z" + mangleIdent(clazz.name + "::" + decl.name);
|
||||||
|
if (decl.args.empty()) {
|
||||||
|
mangledSymbol += "v";
|
||||||
|
} else {
|
||||||
|
std::vector<std::string> seen;
|
||||||
|
static constexpr auto firstPart = [](std::string_view str, std::string_view sep) {
|
||||||
|
return str.substr(0, str.find(sep));
|
||||||
|
};
|
||||||
|
// this is S_
|
||||||
|
seen.push_back(mangleIdent(firstPart(clazz.name, "::")));
|
||||||
|
for (auto& [ty, _] : decl.args) {
|
||||||
|
mangledSymbol += mangleType(seen, ty.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mangledSymbol;
|
||||||
|
}
|
|
@ -129,6 +129,15 @@ namespace codegen {
|
||||||
return BindStatus::Unbindable;
|
return BindStatus::Unbindable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool shouldAndroidBind(const FunctionBindField* fn) {
|
||||||
|
if (codegen::platform == Platform::Android) {
|
||||||
|
for (auto& [type, name] : fn->prototype.args) {
|
||||||
|
if (can_find(type.name, "gd::")) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
inline BindStatus getStatus(Field const& field) {
|
inline BindStatus getStatus(Field const& field) {
|
||||||
return getStatusWithPlatform(codegen::platform, field);
|
return getStatusWithPlatform(codegen::platform, field);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,10 +198,10 @@ std::string generateBindingSource(Root const& root) {
|
||||||
) {
|
) {
|
||||||
used_declare_format = format_strings::declare_virtual_error;
|
used_declare_format = format_strings::declare_virtual_error;
|
||||||
}
|
}
|
||||||
else if (codegen::getStatus(f) != BindStatus::NeedsBinding) {
|
else if (codegen::getStatus(f) != BindStatus::NeedsBinding && !codegen::shouldAndroidBind(fn)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!used_declare_format) {
|
if (!used_declare_format) {
|
||||||
switch (fn->prototype.type) {
|
switch (fn->prototype.type) {
|
||||||
|
|
Loading…
Reference in a new issue