TLS (BO2)

From COD Engine Research
Jump to: navigation, search

TLS Stands for Thread Local Storage. It is a section of data that is unique to each thread and is being pointed to by the register r13 in the powerpc architecture. Some functions make use of that tls to access some buffers like va Com_Error, etc... Not setting up the tls like the game would do it will most likely cause a crash when calling functions that make use of that storage.

struct TraceThreadInfo_t // not sure if the name is correct
{
	short unk0;
	short (*partitions)[0x1ED0];
	short (*partitions2)[0x1ED0];
	char (*ptr0)[0x60];
	char (*ptr1)[0x4C];
	char (*ptr2)[0x4];
};
 
struct va_info_t
{
	char va_string[4][0x400];
	int index;
};
 
struct CmdArgs
{
	int nesting; //0x0
		char unk0[0x60]; //0x4
	int localClientNum[8]; //0x64
	int argc[8]; //0x84
	const char **argv[8]; //0xA4
	char textPool[0x2000]; //0xC4
	const char* argvPool[0x200]; //0x20C4
	int usedTextPool[8]; //0x28C4
	int totalUsedArgvPool; //0x28E4
	int totalUsedTextPool;//0x28E8
};
 
struct tls_t
{
	int zero;
	va_info_t* va;
	jmp_buf* env; // located in the header <setjmp.h>
	TraceThreadInfo_t* data;
	CmdArgs* integers;
};

To access that storage, Sys_GetValue and Sys_SetValue are used.

void* Sys_GetValue(int index);
void Sys_SetValue(int index, void* value);

An example of how that buffer is accessed:

char* va(const char* fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	va_info_t* info = (va_info_t*)Sys_GetValue(1);
	int index = info->index++;
	char* buffer = info->va_string[index];
	int ret = vsnprintf(buffer, 0x400, fmt, args);
	va_end(args);
	if (ret < 0 || ret >= 0x400)
	{
		buffer[0x3FF] = '\0';
		Com_Error(ERR_DROP, "\x15Attempted to overrun string in call to va(): '%s'", buffer);
	}
	return buffer;
}