SafeNameAndChat/metamod/engineinfo.h
Artem Golubikhin b7e2e97111 Initial commit
2016-01-25 02:09:11 +00:00

258 lines
7.5 KiB
C++

// vi: set ts=4 sw=4 :
// vim: set tw=75 :
// engineinfo.h - info about HL engine, like file used and
// text segment range
//
#ifndef MM_ENGINEINFO_H
#define MM_ENGINEINFO_H
#ifdef _WIN32
typedef void* MemAddr;
#else
# include <link.h> // ElfW(Addr/Phdr) macros
typedef void* MemAddr;
#endif /* _WIN32 */
#include "extdll.h" // eiface.h: enginefuncs_t
#include "comp_dep.h"
#include "osdep.h" //unlikely, OPEN_ARGS
#include "new_baseclass.h"
// What we return in is_valid_code_pointer() when the EngineInfo object is
// in an INVALID state, i.e. no code address range could be determined.
static const bool c_DefaultReturnOnInvalidState = true;
static const int c_EngineInfo__typeLen = 10;
class EngineInfo : public class_metamod_new
{
private:
// data :
MemAddr m_codeStart;
MemAddr m_codeEnd;
// State is either NULL when not yet initialised,
// VALID if a code range could be determined
// or INVALID when no valid range for code addresses
// could be determined.
char m_state;
// Type of engine dso/dll used.
// For Linux this specifies the architecture, i.e. 'i486', 'i686',
// 'amd', 'amd64' etc.
// For Windows this is either 'sw' or 'hw' or 'swds' depending on
// the server type.
char m_type[c_EngineInfo__typeLen];
// functions :
// Check if string is valid name of engine dso/dll.
bool DLLINTERNAL check_for_engine_module( const char* pName );
#ifdef _WIN32
// Set info using the PE header found by module name.
// Returns 0 on success, error code on failure.
int DLLINTERNAL nthdr_module_name( void );
int DLLINTERNAL vac_pe_approx( enginefuncs_t* pFuncs );
// Set code segment start and end from PEheader. The base
// address, that relative addresses are based on, is passed in
// pBase.
void DLLINTERNAL set_code_range( unsigned char* pBase, PIMAGE_NT_HEADERS pNThdr );
#else
// Set info using the Programheader found via r_debug struct.
// Returns 0 on success, error code on failure.
int DLLINTERNAL phdr_r_debug( void );
// Set info using the Programheader found with reference address
// via dladdr(). Returns 0 on success, error code on failure.
int DLLINTERNAL phdr_dladdr( void* pMem );
// Set info using the Programheader found via ELF header passed as
// pElfHdr. Return 0 on success, error code on failure.
int DLLINTERNAL phdr_elfhdr( void* pElfHdr );
// Set code segment start and end from Programheader. The base
// address, that relative addresses are based on, is passed in
// pBase.
void DLLINTERNAL set_code_range( void* pBase, ElfW(Phdr)* pPhdr );
#endif /* _WIN32 */
public:
// codes :
enum {
STATE_NULL = 0,
STATE_VALID,
STATE_INVALID,
MODULE_NAME_NOTFOUND = 5,
INVALID_DOS_SIGN,
INVALID_NT_SIGN,
INVALID_ARG,
HEADER_NOTFOUND,
NOTFOUND
};
// functions :
EngineInfo() DLLINTERNAL;
EngineInfo& operator=( const EngineInfo& ) DLLINTERNAL;
EngineInfo( const EngineInfo& ) DLLINTERNAL;
const char* DLLINTERNAL type( void );
// Initilaise object, determining the bounds of the code segment of
// the HL engine shared object.
int DLLINTERNAL initialise( enginefuncs_t* pFuncs = NULL );
// Test if pMem is within bounds of the code segment.
bool DLLINTERNAL is_valid_code_pointer( void* pMem );
// Overloaded versions of above test to keep the ugly pointer
// conversion stuff in here.
bool DLLINTERNAL is_valid_code_pointer( const char* (*fp) (edict_t*) );
bool DLLINTERNAL is_valid_code_pointer( sequenceEntry_s* (*fp) (const char*, const char*) );
bool DLLINTERNAL is_valid_code_pointer( sentenceEntry_s* (*fp) (const char*, int, int*) );
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (char*) );
bool DLLINTERNAL is_valid_code_pointer( unsigned int (*fp) (const char*) );
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (void) );
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (const char*) );
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (int) );
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (int) );
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (int*, int) );
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (void) );
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (const edict_t*, const char*) );
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (const edict_t*, const char*, int) );
};
// We probably should run an initialisation here without a reference
// pointer so that the object has valid info in any case.
inline EngineInfo::EngineInfo() :
m_codeStart(NULL),
m_codeEnd(NULL),
m_state(STATE_NULL)
{
m_type[0] = '\0';
}
inline EngineInfo::EngineInfo( const EngineInfo& _rhs) :
m_codeStart(_rhs.m_codeStart),
m_codeEnd(_rhs.m_codeEnd),
m_state(STATE_NULL)
{
memcpy( m_type, _rhs.m_type, c_EngineInfo__typeLen );
}
inline EngineInfo& EngineInfo::operator=( const EngineInfo& _rhs)
{
m_state = _rhs.m_state;
m_codeStart = _rhs.m_codeStart;
m_codeEnd = _rhs.m_codeEnd;
memcpy( m_type, _rhs.m_type, c_EngineInfo__typeLen );
return *this;
}
inline const char* EngineInfo::type( void )
{
return m_type;
}
inline bool EngineInfo::is_valid_code_pointer( void* _pMem )
{
if ( STATE_INVALID == m_state ) {
return c_DefaultReturnOnInvalidState;
}
if ( NULL != _pMem && m_codeStart <= _pMem && _pMem <= m_codeEnd ) {
return true;
}
return false;
}
inline bool EngineInfo::is_valid_code_pointer( const char* (*_fp) (edict_t*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( sequenceEntry_s* (*_fp) (const char*, const char*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( sentenceEntry_s* (*_fp) (const char*, int, int*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (char*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( unsigned int (*_fp) (const char*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (void) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (const char*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (int) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (int) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (int*, int) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (void) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (const edict_t*, const char*) )
{
return is_valid_code_pointer( (void*)_fp );
}
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (const edict_t*, const char*, int) )
{
return is_valid_code_pointer( (void*)_fp );
}
#endif /* MM_ENGINEINFO_H */