add mangler for gd::string symbols

This commit is contained in:
matcool 2023-09-14 16:31:39 -03:00
parent 4715072c86
commit 3559064b45
No known key found for this signature in database
GPG key ID: BF58756086D7AB1C
4 changed files with 163 additions and 3 deletions

View file

@ -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,

View 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;
}

View file

@ -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);
} }

View file

@ -198,7 +198,7 @@ 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;
} }