[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/srpg/Source.Python/master/src/core/modules/memory/memory_rtti.cpp [Back]  [Original]

/**
* =============================================================================
* Source Python
* Copyright (C) 2012-2015 Source Python Development Team.  All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program.  If not, see .
*
* As a special exception, the Source Python Team gives you permission
* to link the code of this program (as well as its derivative works) to
* "Half-Life 2," the "Source Engine," and any Game MODs that run on software
* by the Valve Corporation.  You must obey the GNU General Public License in
* all respects for all other code used.  Additionally, the Source.Python
* Development Team grants this exception to all derivative works.
*/

#include "memory_rtti.h"
#include "utilities/call_python.h"

#include 
#include 
#include 
#include 
#include 

#ifdef WIN32
struct _s_RTTIBaseClassDescriptor;
typedef _s_RTTIBaseClassDescriptor ClassDescriptor;
#else
class __class_type_info;
typedef __class_type_info ClassDescriptor;
#endif

class CBaseType : public IBaseType
{
public:
	CBaseType(const ClassDescriptor *descriptor, size_t offset);

	~CBaseType()
	{
		for (size_t i=0; iGetName());
	}

	void Dump()
	{
		Dump(0);
	}

	void Dump(int level)
	{
		std::string x = "";
		for (int i=0; i < level; ++i)
			x += "-";

		PythonLog(-1, "%s%s", x.c_str(), GetName());
		for (unsigned int i=0; i < GetNumBaseClasses(); ++i) {
			GetBaseClass(i)->Dump(level + 1);
		}
	}

private:
	ptrdiff_t m_Offset;
	size_t m_BaseTypes;
	CBaseType *m_Bases;
	const std::type_info *m_TypeInfo;
};

/* OS Specific Implementations */

const char *GetTypeName(const std::type_info &type)
{
	const char *temp = type.name();
#ifdef WIN32
	/* WIN32 uses 'class ' */
	while (*temp != ' ')
	{
		temp++;
	}
	return ++temp;
#else
	/* GCC uses '' */
	while (isdigit(*temp))
	{
		temp++;
	}

	return temp;
#endif
}

#ifdef WIN32
#include 

using namespace std;

using std::type_info;

typedef std::type_info TypeDescriptor;

struct PMD
{
	ptrdiff_t mdisp; //vftable offset
	ptrdiff_t pdisp; //vbtable offset
	ptrdiff_t vdisp; //vftable offset (for virtual base class)
};

struct _s_RTTICompleteObjectLocator;
struct _s_RTTIClassHierarchyDescriptor;
struct _s_RTTIBaseClassDescriptor;

struct _s_RTTICompleteObjectLocator
{
	DWORD signature;
	DWORD offset; //vftable offset to this
	DWORD cdOffset;
	TypeDescriptor *pTypeDescriptor;
	_s_RTTIClassHierarchyDescriptor *pClassHierarchyDescriptor;
};

struct _s_RTTIClassHierarchyDescriptor
{
	DWORD signature;
	DWORD attributes; //bit 0 multiple inheritance, bit 1 virtual inheritance
	size_t numBaseClasses; //at least 1 (all base classes, including itself)
	_s_RTTIBaseClassDescriptor **pBaseClassArray;
};

struct _s_RTTIBaseClassDescriptor
{
	TypeDescriptor *pTypeDescriptor;
	size_t numBaseClasses; //direct base classes
	PMD pmd; //Len=0xC
	DWORD attributes;
	_s_RTTIClassHierarchyDescriptor *pClassHierarchyDescriptor; //of this base class
};

template  // only ptrdiff_t and size_t allowed
R ReadData(size_t ptr)
{
	return *(( const R *)ptr);
}

template < typename R, typename T>
R ReadData( const T *ptr)
{
	return ReadData((size_t)ptr);
}

//We assume the vftable is at offset 0
//If it is not the case, we assume the vbtable should be at offset 0, and with its first entry equal to 0 (point to itself).
//Then its second entry should contain the offset of vftable
template < typename T>
_s_RTTICompleteObjectLocator *GetCompleteObjectLocator( const T *ptr) //not have vbtable
{
	ptrdiff_t offset=0;
	if (ReadData(ReadData(ptr))==0) offset=ReadData(ReadData(ptr)+4);
	return (_s_RTTICompleteObjectLocator *)(ReadData(ReadData((size_t)ptr+offset)-4));
}

CBaseType::CBaseType(const ClassDescriptor *descriptor, size_t offset)
{
	m_BaseTypes = 0;
	int basecount = descriptor->numBaseClasses;
	int current = 1;
	while (current pClassHierarchyDescriptor->pBaseClassArray[current];
		current+= temp->numBaseClasses;
		current++;
		m_BaseTypes++;
	}

	m_Offset = descriptor->pmd.mdisp + offset;
	m_TypeInfo = descriptor->pTypeDescriptor;
	m_Bases = (CBaseType *)malloc(sizeof(CBaseType) * m_BaseTypes);

	current = 1;
	int count = 0;
	while (current pClassHierarchyDescriptor->pBaseClassArray[current];
		current+= temp->numBaseClasses;
		current++;
		new (&m_Bases[count]) CBaseType(temp, m_Offset);
		count++;
	}
}

#else

class __class_type_info;

/* helper class for __vmi_class_type */
class __base_class_info
{
	/* abi defined member variables */
public:
	const __class_type_info *__base;    /* base class type */
	long __offset_flags;            /* offset and info */

	/* implementation defined types */
public:
	enum __offset_flags_masks {
		__virtual_mask = 0x1,
		__public_mask = 0x2,
		hwm_bit = 2,
		offset_shift = 8          /* bits to shift offset by */
	};

	/* implementation defined member functions */
public:
	bool __is_virtual_p () const
	{
		return __offset_flags & __virtual_mask;
	}

	bool __is_public_p () const
	{
		return __offset_flags & __public_mask;
	}

	__PTRDIFF_TYPE__ __offset () const
	{
		// This shift, being of a signed type, is implementation defined. GCC
		// implements such shifts as arithmetic, which is what we want.
		return static_cast (__offset_flags) >> offset_shift;
	}
};

class __class_type_info
	: public std::type_info
{
};

class __si_class_type_info
	: public __class_type_info
{
public:
	const __class_type_info *__base_type;
};

class __vmi_class_type_info : public __class_type_info
{
	/* abi defined member variables */
public:
	unsigned int __flags;         /* details about the class hierarchy */
	unsigned int __base_count;    /* number of direct bases */
	__base_class_info const __base_info[1]; /* array of bases */
};


struct vtable_prefix {
	ptrdiff_t whole_object;           // offset to most derived object
	const __class_type_info *whole_type;  // pointer to most derived type_info
	const void *origin;               // what a class's vptr points to
};

template 
inline const T *
adjust_pointer (const void *base, ptrdiff_t offset)
{
	return reinterpret_cast 
		(reinterpret_cast  (base) + offset);
}

const __class_type_info *typeid2(const void *ptr)
{
	const void *pVtable = *(const void **)(ptr);
	const vtable_prefix *prefix = adjust_pointer  (pVtable, -offsetof (vtable_prefix, origin));
	return prefix->whole_type;
}

enum InheritanceType
{
	Inheritance_None, /* Doubles as unknown */
	Inheritance_Single,
	Inheritance_VirtualMultiple,
};

InheritanceType GetInheritanceType(const __class_type_info *ptr)
{
	const __class_type_info *typeinfo = typeid2(ptr);

	if (strcmp(typeinfo->name(), "N10__cxxabiv120__si_class_type_infoE") == 0)
	{
		return Inheritance_Single;
	}
	else if (strcmp(typeinfo->name(), "N10__cxxabiv121__vmi_class_type_infoE") == 0)
	{
		return Inheritance_VirtualMultiple;
	}

	return Inheritance_None;
}

CBaseType::CBaseType(const ClassDescriptor *descriptor, size_t offset)
{
	InheritanceType type = GetInheritanceType(descriptor);

	switch (type)
	{
	case Inheritance_Single:
		{
			m_BaseTypes = 1;
			break;
		}
	case Inheritance_VirtualMultiple:
		{
			__vmi_class_type_info *vmiObject = (__vmi_class_type_info *)descriptor;
			m_BaseTypes = vmiObject->__base_count;
			break;
		}
	default:
		{
			m_BaseTypes = 0;
		}
	}

	m_Offset = offset;
	m_TypeInfo = descriptor;

	if (type == Inheritance_None)
	{
		m_Bases = NULL;
		return;
	}

	m_Bases = (CBaseType *)malloc(sizeof(CBaseType) * m_BaseTypes);

	if (type == Inheritance_Single)
	{
		__si_class_type_info *siObject = (__si_class_type_info *)descriptor;
		new (m_Bases) CBaseType(siObject->__base_type, offset);
		return;
	}

	__vmi_class_type_info *vmiObject = (__vmi_class_type_info *)descriptor;

	for (size_t i=0; i__base_info[i].__base, offset + vmiObject->__base_info[i].__offset());
	}
}
#endif

IBaseType *GetType(const void *ptr)
{
#ifdef _WIN32
	_s_RTTICompleteObjectLocator *locator = GetCompleteObjectLocator(ptr);
	return new CBaseType(locator->pClassHierarchyDescriptor->pBaseClassArray[0], 0);
#elif __linux__
	return new CBaseType(typeid2(ptr), 0);
#else
	#error Unsupported platform.
#endif
}

Web Proxy Viewer  |  New URL  |  Original Page