31 lines
1.8 KiB
C++
31 lines
1.8 KiB
C++
#include "Relocation.h"
|
|
|
|
// the goal of this file is to support pointers in to a relocated binary with as little runtime overhead, code bloat, and hassle as possible
|
|
//
|
|
// since the main executable will always be loaded before the dll, the easiest solution is to perform the relocation in the constructor of
|
|
// a pointer class that supports conversion to T*. however, since we can't control anything about initialization order, each constructor
|
|
// must call GetModuleHandle(NULL) locally, which sucks. each pointer will need an entry in the static init table, and nothing can be done
|
|
// with the pointers in any other static constructors.
|
|
//
|
|
// one solution to this problem is init_seg(lib). any objects constructed in a file containing this pragma will be constructed before standard
|
|
// 'user' level code. this means we can use the constructor of that object to call GetModuleHandle once and initialize a global with the load
|
|
// address, which the pointer class constructor then references to fix up the addresses. this still creates an entry in the static init table
|
|
// for each pointer, but only calls GetModuleHandle once. pointers are not fixed up until all static init has finished, so other static ctors
|
|
// can't safely use pointers.
|
|
//
|
|
// the problem can't be solved further without moving the RelocPtr constructors in to init_seg(lib), which doesn't appear to be possible
|
|
// without forcing all pointers to be defined in a file with init_seg(lib). that is really ugly and doesn't seem like a good idea.
|
|
|
|
// anything in this file will initialized after the crt but before any user code
|
|
#pragma warning(disable: 4073) // yes this is intentional
|
|
#pragma init_seg(lib)
|
|
|
|
static RelocationManager s_relocMgr;
|
|
|
|
uintptr_t RelocationManager::s_baseAddr = 0;
|
|
|
|
RelocationManager::RelocationManager()
|
|
{
|
|
s_baseAddr = reinterpret_cast<uintptr_t>(GetModuleHandle(NULL));
|
|
}
|