2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-03-30 14:19:00 +03:00
metamod-r/metamod/src/osdep.cpp
2017-07-27 19:59:35 +03:00

154 lines
3.1 KiB
C++

#include "precompiled.h"
CSysModule::CSysModule() : m_handle(0), m_base(0), m_size(0)
{
}
#ifdef _WIN32
module_handle_t CSysModule::load(const char* filepath)
{
if (!m_handle) {
m_handle = LoadLibrary(filepath);
MODULEINFO module_info;
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof module_info)) {
m_base = (uintptr_t)module_info.lpBaseOfDll;
m_size = module_info.SizeOfImage;
}
}
return m_handle;
}
bool CSysModule::unload()
{
bool ret = true;
if (m_handle) {
ret = FreeLibrary(m_handle) != ERROR;
m_handle = 0;
m_base = 0;
m_size = 0;
}
return ret;
}
void* CSysModule::getsym(const char* name) const
{
return m_handle ? GetProcAddress(m_handle, name) : nullptr;
}
#else
static ElfW(Addr) dlsize(void* base)
{
ElfW(Ehdr) *ehdr;
ElfW(Phdr) *phdr;
ElfW(Addr) end;
ehdr = (ElfW(Ehdr) *)base;
/* Find the first program header */
phdr = (ElfW(Phdr)*)((ElfW(Addr))ehdr + ehdr->e_phoff);
/* Find the final PT_LOAD segment's extent */
for (int i = 0; i < ehdr->e_phnum; ++i)
if (phdr[i].p_type == PT_LOAD)
end = phdr[i].p_vaddr + phdr[i].p_memsz;
/* The start (virtual) address is always zero, so just return end.*/
return end;
}
module_handle_t CSysModule::load(const char* filepath)
{
if (!m_handle) {
m_handle = dlopen(filepath, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
char buf[1024], dummy[1024], path[260];
sprintf(buf, "/proc/%i/maps", getpid());
FILE* fp = fopen(buf, "r");
while (fgets(buf, sizeof buf, fp)) {
uintptr_t start, end;
int args = sscanf(buf, "%x-%x %128s %128s %128s %128s %255s", &start, &end, dummy, dummy, dummy, dummy, path);
if (args != 7) {
continue;
}
if (!Q_stricmp(path, filepath)) {
m_base = start;
m_size = end - start;
break;
}
}
fclose(fp);
}
return m_handle;
}
bool CSysModule::unload()
{
bool ret = true;
if (m_handle) {
ret = dlclose(m_handle) != 0;
m_handle = 0;
m_base = 0;
m_size = 0;
}
return ret;
}
void* CSysModule::getsym(const char* name) const
{
return m_handle ? dlsym(m_handle, name) : nullptr;
}
#endif
module_handle_t CSysModule::gethandle() const
{
return m_handle;
}
bool CSysModule::contain(void* addr) const
{
return addr && uintptr_t(addr) > m_base && uintptr_t(addr) < m_base + m_size;
}
const char* CSysModule::getloaderror()
{
#ifdef _WIN32
return str_GetLastError();
#else
return dlerror();
#endif
}
#ifdef _WIN32
// Windows doesn't provide a functon analagous to dlerr() that returns a
// string describing the error, so we include one here, as exampled at:
// http://msdn.microsoft.com/library/en-us/debug/errors_0sdh.asp
// except without FORMAT_MESSAGE_ALLOCATE_BUFFER, since we use a local
// static buffer.
static const char* str_GetLastError()
{
static char buf[MAX_STRBUF_LEN];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, MAX_STRBUF_LEN - 1, nullptr);
return buf;
}
#endif
const char* str_os_error()
{
#ifdef _WIN32
return str_GetLastError();
#else
return strerror(errno);
#endif
}