void LLScriptHeapRunTime::coalesce(S32 address1, S32 address2)
{
	// we need to bump the base offset by the second block's
	S32 toffset = address1;
	S32 offset1 = bytestream2integer(mBuffer, toffset);
	offset1 += bytestream2integer(mBuffer, address2);

	integer2bytestream(mBuffer, address1, offset1);
}
Example #2
0
LLScriptHeapEntry::LLScriptHeapEntry(U8 *entry)
: mEntry(entry)
{
	S32 offset = 0;
	mNext = bytestream2integer(entry, offset);
	mRefCount = bytestream2integer(entry, offset);
	mType = *(entry + offset);
	mData = entry + offset;
	mListOffset = offset;
}
Example #3
0
LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref)
{
	if (get_register(buffer, LREG_FR))
		return (new LLScriptLibData);
	S32 orig_offset = offset;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return (new LLScriptLibData);
	}
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	if (!entry.mType)
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		return NULL;
	}

	LLScriptLibData base, *tip = &base;

	if (entry.mType != LST_LIST)
	{
		return NULL;
	}
	else
	{
		// get length of list
		S32 i, length = bytestream2integer(buffer, offset);

		for (i = 0; i < length; i++)
		{
			S32 address = bytestream2integer(buffer, offset);
			tip->mListp = lsa_get_data(buffer, address, FALSE);
			tip = tip->mListp;
		}
	}
	if (b_dec_ref)
	{
		lsa_decrease_ref_count(buffer, orig_offset);
	}
	tip = base.mListp;
	base.mListp = NULL;
	return tip;
}
void LLScriptHeapRunTime::increaseRefCount(S32 address)
{
	if (!mBuffer)
		return;

	if (!address)
	{
		// unused temp string entry
		return;
	}

	// get current reference count
	S32 toffset = address + 4;
	S32 count = bytestream2integer(mBuffer, toffset);

	count++;

	if (mbPrint)
		printf("0x%X inc ref count %d\n", address - mHeapRegister, count);

	// see which type it is
	U8 type = *(mBuffer + toffset);

	if (type == LSCRIPTTypeByte[LST_STRING])
	{
		toffset = address + 4;
		integer2bytestream(mBuffer, toffset, count);
	}
	// TO DO: put list stuff here!
	else
	{
		set_fault(mBuffer, LSRF_HEAP_ERROR);
	}
}
void LLScriptHeapRunTime::decreaseRefCount(S32 address)
{
	if (!mBuffer)
		return;

	if (!address)
	{
		// unused temp string entry
		return;
	}

	// get offset
	S32 toffset = address;
	// read past offset (rely on function side effect)
	bytestream2integer(mBuffer, toffset);

	// get current reference count
	S32 count = bytestream2integer(mBuffer, toffset);

	// see which type it is
	U8 type = *(mBuffer + toffset);

	if (type == LSCRIPTTypeByte[LST_STRING])
	{
		count--;

		if (mbPrint)
			printf("0x%X dec ref count %d\n", address - mHeapRegister, count);

		toffset = address + 4;
		integer2bytestream(mBuffer, toffset, count);
		if (!count)
		{
			// we can blow this one away
			removeData(address);
		}
	}
	// TO DO: put list stuff here!
	else
	{
		set_fault(mBuffer, LSRF_HEAP_ERROR);
	}
}
Example #6
0
void lsa_decrease_ref_count(U8 *buffer, S32 offset)
{
	if (get_register(buffer, LREG_FR))
		return;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return;
	}
	S32 orig_offset = offset;
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	entry.mReferenceCount--;

	if (entry.mReferenceCount < 0)
	{
		entry.mReferenceCount = 0;
		set_fault(buffer, LSRF_HEAP_ERROR);
	}
	else if (!entry.mReferenceCount)
	{
		if (entry.mType == LST_LIST)
		{
			S32 i, num = bytestream2integer(buffer, offset);
			for (i = 0; i < num; i++)
			{
				S32 list_offset = bytestream2integer(buffer, offset);
				lsa_decrease_ref_count(buffer, list_offset);
			}
		}
		entry.mType = LST_NULL;
	}

	alloc_entry2bytestream(buffer, orig_offset, entry);
}
Example #7
0
LLScriptLSOParse::LLScriptLSOParse(FILE *fp)
{
	U8  sizearray[4];
	S32 filesize;
	S32 pos = 0;
	fread(&sizearray, 1, 4, fp);
	filesize = bytestream2integer(sizearray, pos);
	mRawData = new U8[filesize];
	fseek(fp, 0, SEEK_SET);
	fread(mRawData, 1, filesize, fp);

	initOpCodePrinting();
}
void LLScriptHeapRunTime::split(S32 address1, S32 size)
{
	S32 toffset = address1;
	S32 oldoffset = bytestream2integer(mBuffer, toffset);

	// add new offset and zero out reference count and block used
	S32 newoffset = oldoffset - size;
	S32 newblockpos = address1 + size;

	// set new offset
	integer2bytestream(mBuffer, newblockpos, newoffset);
	// zero out reference count
	integer2bytestream(mBuffer, newblockpos, 0);
	// mark as empty
	*(mBuffer + newblockpos) = 0;

	// now, change the offset of the original block
	integer2bytestream(mBuffer, address1, size + HEAP_BLOCK_HEADER_SIZE);
}
LLScriptLSOParse::LLScriptLSOParse(LLFILE *fp)
{
	U8  sizearray[4];
	S32 filesize;
	S32 pos = 0;
	if (fread(&sizearray, 1, 4, fp) != 4)
	{
		llwarns << "Short read" << llendl;
		filesize = 0;
	} else {
		filesize = bytestream2integer(sizearray, pos);
	}
	mRawData = new U8[filesize];
	fseek(fp, 0, SEEK_SET);
	if (fread(mRawData, 1, filesize, fp) != filesize)
	{
		llwarns << "Short read" << llendl;
	}

	initOpCodePrinting();
}
Example #10
0
void lsa_fprint_heap(U8 *buffer, LLFILE *fp)
{
	S32				offset = get_register(buffer, LREG_HR);
	S32				readoffset;
	S32				ivalue;
	F32				fpvalue;
	LLVector3		vvalue;
	LLQuaternion	qvalue;
	char			string[4096];		/*Flawfinder: ignore*/

	LLScriptAllocEntry entry;

	bytestream2alloc_entry(entry, buffer, offset);

	while (offset + entry.mSize < MAX_HEAP_SIZE)
	{
		fprintf(fp, "[0x%X] ", offset);
		fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
		fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
		fprintf(fp, "Size: %d = ", entry.mSize);

		readoffset = offset;

		switch(entry.mType)
		{
		case LST_INTEGER:
			ivalue = bytestream2integer(buffer, readoffset);
			fprintf(fp, "%d\n", ivalue);
			break;
		case LST_FLOATINGPOINT:
			fpvalue = bytestream2float(buffer, readoffset);
			fprintf(fp, "%f\n", fpvalue);
			break;
		case LST_STRING:
			bytestream2char(string, buffer, readoffset, sizeof(string));
			fprintf(fp, "%s\n", string);
			break;
		case LST_KEY:
			bytestream2char(string, buffer, readoffset, sizeof(string));
			fprintf(fp, "%s\n", string);
			break;
		case LST_VECTOR:
			bytestream2vector(vvalue, buffer, readoffset);
			fprintf(fp, "< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
			break;
		case LST_QUATERNION:
			bytestream2quaternion(qvalue, buffer, readoffset);
			fprintf(fp, "< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
			break;
		case LST_LIST:
			ivalue = bytestream2integer(buffer, readoffset);
			fprintf(fp, "%d\n", ivalue);
			break;
		default:
			fprintf(fp, "\n");
			break;
		}
		offset += entry.mSize;
		bytestream2alloc_entry(entry, buffer, offset);
	}
	fprintf(fp, "[0x%X] ", offset);
	fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
	fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
	fprintf(fp, "Size: %d", entry.mSize);
	fprintf(fp, "\n");
}
Example #11
0
LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref)
{
	if (get_register(buffer, LREG_FR))
		return (new LLScriptLibData);
	S32 orig_offset = offset;
	// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
	// and function clean up of ref counts isn't based on scope (a mistake, I know)
	offset += get_register(buffer, LREG_HR) - 1;
	if (  (offset < get_register(buffer, LREG_HR))
		||(offset >= get_register(buffer, LREG_HP)))
	{
		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
		return (new LLScriptLibData);
	}
	LLScriptAllocEntry entry;
	bytestream2alloc_entry(entry, buffer, offset);

	LLScriptLibData *retval = new LLScriptLibData;

	if (!entry.mType)
	{
		set_fault(buffer, LSRF_HEAP_ERROR);
		return retval;
	}

	retval->mType = (LSCRIPTType)entry.mType;
	if (entry.mType != LST_LIST)
	{
		switch(entry.mType)
		{
		case LST_INTEGER:
			retval->mInteger = bytestream2integer(buffer, offset);
			break;
		case LST_FLOATINGPOINT:
			retval->mFP = bytestream2float(buffer, offset);
			break;
		case LST_KEY:
			bytestream2char(gLSAStringRead, buffer, offset, sizeof(gLSAStringRead)); // global sring buffer? for real? :(
			retval->mKey = new char[strlen(gLSAStringRead) + 1];		/*Flawfinder: ignore*/
			strcpy(retval->mKey, gLSAStringRead);			/*Flawfinder: ignore*/
			break;
		case LST_STRING:
			bytestream2char(gLSAStringRead, buffer, offset, sizeof(gLSAStringRead));
			retval->mString = new char[strlen(gLSAStringRead) + 1];		/*Flawfinder: ignore*/
			strcpy(retval->mString, gLSAStringRead);			/*Flawfinder: ignore*/
			break;
		case LST_VECTOR:
			bytestream2vector(retval->mVec, buffer, offset);
			break;
		case LST_QUATERNION:
			bytestream2quaternion(retval->mQuat, buffer, offset);
			break;
		default:
			break;
		}
	}
	else
	{
		// get length of list
		S32 i, length = bytestream2integer(buffer, offset);
		LLScriptLibData *tip = retval;

		for (i = 0; i < length; i++)
		{
			S32 address = bytestream2integer(buffer, offset);
			tip->mListp = lsa_get_data(buffer, address, FALSE);
			tip = tip->mListp;
		}
	}
	if (retval->checkForMultipleLists())
	{
		set_fault(buffer, LSRF_NESTING_LISTS);
	}
	if (b_dec_ref)
	{
		lsa_decrease_ref_count(buffer, orig_offset);
	}
	return retval;
}
S32 LLScriptHeapRunTime::findOpenBlock(S32 size)
{
	S32 offset;
	S32 toffset;
	U8 blocktype;

	while(1)
	{
		if (mCurrentPosition + size >= mStackPointer)
		{
			set_fault(mBuffer, LSRF_STACK_HEAP_COLLISION);
			mCurrentPosition = 0;
		}

		toffset = mCurrentPosition;
		offset = bytestream2integer(mBuffer, toffset);
		if (!offset)
		{
			// we've reached the end of Heap, return this location if we'll fit
			// do we need to coalesce with last empty space?
			if (mLastEmpty)
			{
				// ok, that everything from mLastEmpty to us is empty, so we don't need a block
				// zero out the last empty's offset and return it
				mCurrentPosition = mLastEmpty;
				integer2bytestream(mBuffer, mLastEmpty, 0);
				mLastEmpty = 0;
			}
			// now, zero out next offset to prevent "trouble"
			offset = mCurrentPosition + size;
			integer2bytestream(mBuffer, offset, 0);

			// set HP to appropriate value
			set_register(mBuffer, LREG_HP, mCurrentPosition + size);
			return size;
		}

		// ok, is this slot empty?
		toffset += LSCRIPTDataSize[LST_INTEGER];

		blocktype = *(mBuffer + toffset++);

		if (!blocktype)
		{
			// Empty block, do we need to coalesce?
			if (mLastEmpty)
			{
				coalesce(mLastEmpty, mCurrentPosition);
				mCurrentPosition = mLastEmpty;
				toffset = mCurrentPosition;
				offset = bytestream2integer(mBuffer, toffset);
			}

			// do we fit in this block?
			if (offset >= size)
			{
				// do we need to split the block? (only split if splitting will leave > HEAP_BLOCK_SPLIT_THRESHOLD bytes of free space)
				if (offset - HEAP_BLOCK_SPLIT_THRESHOLD >= size)
				{
					split(mCurrentPosition, size);
					return size;
				}
				else
					return offset;
			}
		}
		// nothing found, keep looking
		mCurrentPosition += offset;
	}
	// fake return to prevent warnings
	mCurrentPosition = 0;
	return 0;
}
void LLScriptHeapRunTime::removeData(S32 address)
{
	if (!mBuffer)
		return;

	S32 toffset = address;
	// read past offset (relying on function side effect
	bytestream2integer(mBuffer, toffset);

	// make sure that reference count is 0
	integer2bytestream(mBuffer, toffset, 0);
	// show the block as empty
	*(mBuffer + toffset) = 0;

	// now, clean up the heap
	S32 clean = mHeapRegister;
	S32 tclean;
	S32 clean_offset;

	S32 nclean;
	S32 tnclean;
	S32 next_offset;

	U8  type;
	U8  ntype;

	for(;;)
	{
		tclean = clean;
		clean_offset = bytestream2integer(mBuffer, tclean);
		// is this block, empty?
		tclean += LSCRIPTDataSize[LST_INTEGER];
		type = *(mBuffer + tclean);
		
		if (!clean_offset)
		{
			if (!type)
			{
				// we're done! if our block is empty, we can pull in the HP and zero out our offset
				set_register(mBuffer, LREG_HP, clean);
			}
			return;
		}


		if (!type)
		{
			// if we're empty, try to coalesce with the next one
			nclean = clean + clean_offset;
			tnclean = nclean;
			next_offset = bytestream2integer(mBuffer, tnclean);
			tnclean += LSCRIPTDataSize[LST_INTEGER];
			ntype = *(mBuffer + tnclean);

			if (!next_offset)
			{
				// we're done! if our block is empty, we can pull in the HP and zero out our offset
				tclean = clean;
				integer2bytestream(mBuffer, tclean, 0);
				set_register(mBuffer, LREG_HP, clean);
				return;
			}

			if (!ntype)
			{
				// hooray!  we can coalesce
				tclean = clean;
				integer2bytestream(mBuffer, tclean, clean_offset + next_offset);
				// don't skip forward so that we can keep coalescing on next pass through the loop
			}
			else
			{
				clean += clean_offset;
			}
		}
		else
		{
			// if not, move on to the next block
			clean += clean_offset;
		}
	}
}