2024-05-12 01:14:14 +00:00
|
|
|
#pragma once
|
|
|
|
|
2024-06-04 22:29:13 +00:00
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
#include "../common/common.h"
|
2024-05-12 01:14:14 +00:00
|
|
|
|
|
|
|
// Trampoline Function
|
2024-06-08 08:23:15 +00:00
|
|
|
uint32_t _raw_trampoline(uint32_t id, bool allow_early_return, uint32_t length, const unsigned char *args);
|
2024-06-04 22:29:13 +00:00
|
|
|
|
|
|
|
// Compile Trampoline Arguments
|
|
|
|
template <typename T>
|
2024-06-08 07:09:55 +00:00
|
|
|
void _handle_trampoline_arg(unsigned char *&out, const T &arg) {
|
2024-06-04 22:29:13 +00:00
|
|
|
block_pointer(T);
|
|
|
|
*(T *) out = arg;
|
|
|
|
out += sizeof(T);
|
|
|
|
}
|
|
|
|
// Array Specialization
|
|
|
|
struct copy_array {
|
|
|
|
template <typename T>
|
|
|
|
copy_array(uint32_t length, T *arr) {
|
|
|
|
block_pointer(T);
|
|
|
|
if (arr == nullptr) {
|
|
|
|
length = 0;
|
|
|
|
}
|
|
|
|
this->size = length * sizeof(T);
|
|
|
|
this->data = arr;
|
|
|
|
}
|
|
|
|
copy_array(const char *str) {
|
|
|
|
this->size = str != nullptr ? (strlen(str) + 1) : 0;
|
|
|
|
this->data = str;
|
|
|
|
}
|
|
|
|
uint32_t size;
|
|
|
|
const void *data;
|
|
|
|
};
|
|
|
|
template <>
|
2024-06-08 07:09:55 +00:00
|
|
|
inline void _handle_trampoline_arg<copy_array>(unsigned char *&out, const copy_array &arg) {
|
2024-06-04 22:29:13 +00:00
|
|
|
*(uint32_t *) out = arg.size;
|
|
|
|
out += sizeof(uint32_t);
|
|
|
|
if (arg.size > 0) {
|
|
|
|
memcpy(out, arg.data, arg.size);
|
|
|
|
out += arg.size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Variadic Templates
|
|
|
|
__attribute__((unused)) static void _add_to_trampoline_args(__attribute__((unused)) unsigned char *&out) {
|
|
|
|
}
|
|
|
|
template <typename T, typename... Args>
|
2024-06-08 07:09:55 +00:00
|
|
|
void _add_to_trampoline_args(unsigned char *&out, const T &first, const Args... args) {
|
2024-06-04 22:29:13 +00:00
|
|
|
_handle_trampoline_arg(out, first);
|
|
|
|
_add_to_trampoline_args(out, args...);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Main Trampoline Function
|
|
|
|
template <typename... Args>
|
2024-06-08 08:23:15 +00:00
|
|
|
unsigned int _trampoline(const unsigned int id, const bool allow_early_return, Args... args) {
|
|
|
|
static unsigned char out[MAX_TRAMPOLINE_ARGS_SIZE];
|
2024-06-04 22:29:13 +00:00
|
|
|
unsigned char *end = out;
|
|
|
|
_add_to_trampoline_args(end, args...);
|
|
|
|
const uint32_t length = end - out;
|
2024-06-08 08:23:15 +00:00
|
|
|
return _raw_trampoline(id, allow_early_return, length, out);
|
2024-06-04 22:29:13 +00:00
|
|
|
}
|
|
|
|
#define trampoline(...) _trampoline(_id, ##__VA_ARGS__)
|
2024-05-12 01:14:14 +00:00
|
|
|
|
|
|
|
// Macro
|
|
|
|
#define CALL(unique_id, name, return_type, args) \
|
|
|
|
return_type name args { \
|
|
|
|
static unsigned char _id = unique_id;
|