Я работаю над проектом C++, который загружается в виде DLL в игровой движок с закрытым исходным кодом (который подвергается обратному проектированию) с целью исправления ошибок и расширения логики игрового движка. Для взаимодействия с игрой мне, в частности, нужно иметь своего рода объявления функций игрового движка, глобальных переменных и т. д. Типы легко определить, и даже сами переменные (
Код: Выделить всё
reinterpret_castКак это выглядит в исходном коде:
Код: Выделить всё
class BeaconClass
{
public:
BeaconClass() JMP_THIS(0x430210)
void Draw(Surface* pSurface, RectangleStruct bounds) JMP_THIS(0x430250)
void SetCoordAndHouse(CoordStruct coord, int houseId) JMP_THIS(0x430590)
//...
};
< /code>
Расширение на: < /p>
class BeaconClass
{
public:
BeaconClass()
{
_asm{pop ecx};
_asm{mov esp, ebp};
_asm{pop ebp};
_asm{mov eax, 0x430210};
_asm{jmp eax};
}
// ...

Но такое поведение зависит от компилятора, и часто вы не можете помешать компилятору выдавать нежелательный код в конструкторы конкретно. Когда я попытался переключиться с MSVC на clang-cl - такие хаки начали давать сбой, и я вылетел из-за поврежденного стека/EIP, а компилятор сгенерировал кучу разных инструкций для более сложного случая ctor:
Код: Выделить всё
class NOVTABLE CCFileClass : public CDFileClass
{
// ...
//Constructor
CCFileClass(const char* pFileName)
: CCFileClass(noinit_t())
{ JMP_THIS(0x4739F0); }
protected:
explicit __forceinline CCFileClass(noinit_t)
: CDFileClass(noinit_t())
{ }
//Properties
public:
MemoryBuffer Buffer;
// ...
};
Очевидно, что это очень сильно противоречит тому, что предназначено и является довольно нечистым способом сделать это, поэтому ...
Вопрос
Каким-то образом возможно объявить символ с адресом a-la extern Адрес?
Код: Выделить всё
class NOVTABLE BuildingClass : public TechnoClass
{
//...
[[address(0x43EF90)]]
int GetCurrentFrame();
//...
Код: Выделить всё
mov ecx, pBuilding
call 0x43EF90
Предположим, цепочки инструментов Clang/MSVC. В настоящее время проект работает на MSVC, но рассматривается возможность перехода на clang с совместимостью с MSVC (если это вообще возможно).
Рассматриваемые альтернативы
- Определение символов в ассемблере с использованием искаженного имени — работает, но чрезвычайно громоздко для довольно простой задачи, не может быть записано в режиме реального времени, а также создает функцию преобразования.
- Использовать как есть - очень непереносимо, происходит сбой при переходе на clang, очень сильно зависит от неясного недокументированного поведения, которое может сломаться.
- Использование голых функций - невозможно для ctors, dtors.
- Использование символов, определенных из компоновщик - может работать, но я бы предпочел, чтобы каждое определение символа соответствовало его объявлению, такое разделение является громоздким.
Подробнее здесь: https://stackoverflow.com/questions/797 ... ed-address
Мобильная версия